From 332e3f60995d5934e1c4877ffebf2d1edbb9457f Mon Sep 17 00:00:00 2001 From: Scott Rossillo Date: Mon, 5 Oct 2015 14:56:21 -0400 Subject: [PATCH] KEYCLOAK-1901: Add a Keycloak client builder Adds support for creating a Keycloak client using the builder pattern and supports customizing the underlying ResteasyClient used for connecting to the Keycloak server. --- .../org/keycloak/admin/client/Keycloak.java | 17 ++- .../admin/client/KeycloakBuilder.java | 107 ++++++++++++++++++ 2 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java index 6d6c7beff7..431a64664e 100755 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/Keycloak.java @@ -9,6 +9,12 @@ import org.keycloak.admin.client.resource.RealmsResource; import org.keycloak.admin.client.token.TokenManager; /** + * Provides a Keycloak client. By default, this implementation uses a {@link ResteasyClient RESTEasy client} with the + * default {@link ResteasyClientBuilder} settings. To customize the underling client, use a {@link KeycloakBuilder} to + * create a Keycloak client. + * + * @see KeycloakBuilder + * * @author rodrigo.sasaki@icarros.com.br */ public class Keycloak { @@ -18,9 +24,9 @@ public class Keycloak { private final ResteasyWebTarget target; private final ResteasyClient client; - private Keycloak(String serverUrl, String realm, String username, String password, String clientId, String clientSecret){ + Keycloak(String serverUrl, String realm, String username, String password, String clientId, String clientSecret, ResteasyClient resteasyClient){ config = new Config(serverUrl, realm, username, password, clientId, clientSecret); - client = new ResteasyClientBuilder().build(); + client = resteasyClient != null ? resteasyClient : new ResteasyClientBuilder().build(); tokenManager = new TokenManager(config, client); @@ -30,11 +36,11 @@ public class Keycloak { } public static Keycloak getInstance(String serverUrl, String realm, String username, String password, String clientId, String clientSecret){ - return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret); + return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret, null); } public static Keycloak getInstance(String serverUrl, String realm, String username, String password, String clientId){ - return new Keycloak(serverUrl, realm, username, password, clientId, null); + return new Keycloak(serverUrl, realm, username, password, clientId, null, null); } public RealmsResource realms(){ @@ -49,6 +55,9 @@ public class Keycloak { return tokenManager; } + /** + * Closes the underlying client. After calling this method, this Keycloak instance cannot be reused. + */ public void close() { client.close(); } diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java new file mode 100644 index 0000000000..c4a1c3315d --- /dev/null +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/KeycloakBuilder.java @@ -0,0 +1,107 @@ +package org.keycloak.admin.client; + +import org.jboss.resteasy.client.jaxrs.ResteasyClient; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; + +/** + * Provides a {@link Keycloak} client builder with the ability to customize the underlying + * {@link ResteasyClient RESTEasy client} used to communicate with the Keycloak server. + * + *

Example usage with a connection pool size of 20:

+ * + *
+ *   Keycloak keycloak = KeycloakBuilder.builder()
+ *     .serverUrl("https:/sso.example.com/auth")
+ *     .realm("realm")
+ *     .username("user")
+ *     .password("pass")
+ *     .clientId("client")
+ *     .clientSecret("secret")
+ *     .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(20).build())
+ *     .build();
+ * 
+ * + * @author Scott Rossillo + * @see ResteasyClientBuilder + */ +public class KeycloakBuilder { + private String serverUrl; + private String realm; + private String username; + private String password; + private String clientId; + private String clientSecret; + private ResteasyClient resteasyClient; + + public KeycloakBuilder serverUrl(String serverUrl) { + this.serverUrl = serverUrl; + return this; + } + + public KeycloakBuilder realm(String realm) { + this.realm = realm; + return this; + } + + public KeycloakBuilder username(String username) { + this.username = username; + return this; + } + + public KeycloakBuilder password(String password) { + this.password = password; + return this; + } + + public KeycloakBuilder clientId(String clientId) { + this.clientId = clientId; + return this; + } + + public KeycloakBuilder clientSecret(String clientSecret) { + this.clientSecret = clientSecret; + return this; + } + + public KeycloakBuilder resteasyClient(ResteasyClient resteasyClient) { + this.resteasyClient = resteasyClient; + return this; + } + + /** + * Builds a new Keycloak client from this builder. + */ + public Keycloak build() { + if (serverUrl == null) { + throw new IllegalStateException("serverUrl required"); + } + + if (realm == null) { + throw new IllegalStateException("realm required"); + } + + if (username == null) { + throw new IllegalStateException("username required"); + } + + if (password == null) { + throw new IllegalStateException("password required"); + } + + if (clientId == null) { + throw new IllegalStateException("clientId required"); + } + + return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret, resteasyClient); + } + + private KeycloakBuilder() { + } + + /** + * Returns a new Keycloak builder. + */ + public static KeycloakBuilder builder() { + return new KeycloakBuilder(); + } +}