Using admin client from within application deployed as Wildfly *.ear file

Hi,

I have a Java EE application I run via Wildfly 25 and deploy as a *.ear file (containing a *.ejb and a *.war file). My application authenticates to an external, third-party system to access REST service. This external system has recently implemented Keycloak for SSO authentication. The third-party has provided an SDK with examples for authentication and access via their own class library along with a set of Keycloak 12.0.2 *.jar files and dependencies. The example code uses the Keycloak admin client (org.keycloak.admin.client.Keycloak) as follows:

...
keycloak = Keycloak.getInstance(
						getKeycloakAuthServerUrl(),
						getKeycloakRealm(),
						username,
						password,
						getKeycloakResource(),
						null,  //this is the secret.  If we decide to use the secret to authenticate, put it here
						sslContext,
						null, //CustomJacksonProvider
						true,
						null  //authToken...we don't have one yet, so it's null
				);
...

When I build a quick test with the SDK and compile and run it as a standalone Java project, the code runs as expected and I get a successful connection attempt. When I transplant this same code into my JEE app (where it is deployed within a Stateless Session EJB), I observe the following exception:

19:11:47,419 SEVERE [ConvServiceFactory] (EJB default - 1) Failure in Keycloak Direct auth: java.lang.IllegalArgumentException: org.jboss.resteasy.client.jaxrs.internal.proxy.ResteasyClientProxy referenced from a method is not visible from class loader
	at java.base/java.lang.reflect.Proxy$ProxyBuilder.ensureVisible(Proxy.java:858)
	at java.base/java.lang.reflect.Proxy$ProxyBuilder.validateProxyInterfaces(Proxy.java:681)
	at java.base/java.lang.reflect.Proxy$ProxyBuilder.<init>(Proxy.java:627)
	at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$1(Proxy.java:426)
	at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
	at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
	at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:424)
	at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1006)
	at com.c60ext//org.jboss.resteasy.client.jaxrs.ProxyBuilder.proxy(ProxyBuilder.java:99)
	at com.c60ext//org.jboss.resteasy.client.jaxrs.ProxyBuilder.build(ProxyBuilder.java:166)
	at com.c60ext//org.jboss.resteasy.client.jaxrs.internal.ClientWebTarget.proxy(ClientWebTarget.java:93)
	at com.c60ext//org.keycloak.admin.client.token.TokenManager.<init>(TokenManager.java:56)
	at com.c60ext//org.keycloak.admin.client.Keycloak.<init>(Keycloak.java:55)

Because the standalone Java project works as expected, this error makes me think that the Keycloak class org.keycloak.admin.client.Keycloak and/or Keycloak version 12.0.2 may not be intended for use from within a Wildfly runtime environment.

Any input or direction anyone might provide would be appreciated.

Thanks!

-Andy

This is most likely because the admin client relies on a different version of RestEasy libs than the Wildfly 25 app server.

You’ll have to exclude the RestEasy dependencies from the admin client and provide a custom RestEasyClient instance to the Keycloak instance (creating it via the KeycloakBuilder.build() methods, not Keycloak.getInstance()).

Thank you for the response. I have attempted the following approaches, with neither working:

  1. For the error reported above:
org.jboss.resteasy.client.jaxrs.internal.proxy.ResteasyClientProxy referenced from a method is not visible from class loader

this was achieved by attempting to exclude all of the built-in Wildfly 4.7.X Resteasy modules by way of my application’s jboss-deployment-structure.xml configuration file and incorporate all of the older Resteasy library dependencies by way of a user-defined Wildfly module dependency. It would seem that the attempt to exclude the built-in Resteasy files may not have been entirely successful, with the Keycloak.getInstance() method possibly internally loading a 4.7.X ResteasyClient class instead of the older 3.X version and causing the class loader error.

  1. If I eliminate all of the older 3.X Resteasy dependency libraries from the deployment and rely on the built-in 4.7.X Resteasy client libraries, along with replacing Keycloak.getInstance() with KeycloakBuilder.build() (and providing the method call with a 4.7.X ResteasyClient instance), I am faced with at least two missing class errors for interfaces that have been deprecated and do not exist in the newer Resteasy framework - ClientExecutor and ClientInterceptor. These interfaces and custom class implementations are used within the third-party provider’s REST services / Keycloak setup, so it would seem that I have a hard requirement on the part of the third party to make use of the older 3.X Resteasy libraries (which seems challenging and/or impossible to achieve when running Wildfly 25).

I guess we’ll have to look at some alternative for this.

Thanks,

-Andy

Hi,

I’ve made another attempt at this using Wildfly 23 (which uses Resteasy 3.15 libraries) and the KeycloakBuilder.build() approach. This seems to get things close to working (eliminating the class loader error), but one wrinkle is that the original code I’m replacing uses the Keycloak.getInstance() method and supplies an instance of javax.net.ssl.SSLContext as an argument. The KeycloakBuilder.build() method does not appear to support providing or setting (after the fact) an instance of javax.net.ssl.SSLContext :

KeycloakBuilder

vs.

Keycloak#getInstance

Is there a way to provide the SSLContext instance as part of the KeycloakBuilder.build()? Maybe I’m overlooking something? Please let me know if I can provide any additional information.

Thanks!

-Andy