<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
</head>
<body dir="ltr">
<div id="divtagdefaultwrapper" style="font-size:12pt;color:#000000;background-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;">
<p>Hi all:</p>
<p><br>
</p>
<p>I'm in the process of developing a web&nbsp;service-based User Federation SPI. I've gone through the properties SPI example and had a look at the ldap and kerberos SPIs. They seem pretty straightforward and at first glance I think I've implemented things properly.
 For my service requests, I'm using the Resteasy client through the proxy interface with a few simple calls to test things out. When I package and deploy, Keycloak doesn't seem to complain, however when I search for a user, i get the following trace:</p>
<p></p>
<div><i>09:20:20,956 ERROR [io.undertow.request] (default task-15) UT005023: Exception handling request to /auth/admin/realms/master/users: org.jboss.resteasy.spi.UnhandledException: java.lang.IllegalArgumentException: interface org.keycloak.federation.ws.client.WsServiceClient
 is not visible from class loader</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:168)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:411)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:202)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.keycloak.services.filters.KeycloakSessionServletFilter.doFilter(KeycloakSessionServletFilter.java:90)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)</i></div>
<div><i><span class="Apple-tab-span" style="white-space:pre"></span>at java.lang.Thread.run(Thread.java:745)</i></div>
<div><i><br>
</i></div>
<div>Some details about my environment:</div>
<div>Keycloak version: 2.1.0.Final, running in standalone mode</div>
<div>Java version: 1.8.0_101</div>
<div><br>
</div>
<div>Project structure:</div>
<div>or.keycloak.federation.ws</div>
<div><i>-client</i></div>
<div><i>--WsServiceClient.java</i></div>
<div><i>-ServiceModel.java</i></div>
<div><i>-WsFederationProvider.java</i></div>
<div><i>-WsFederationProviderFactory.java</i></div>
<div><i><br>
</i></div>
<div><i>-resources</i></div>
<div><i>--META-INF.services</i></div>
<div><i>---org.keycloak.models.UserFederationProviderFactory</i></div>
<div><br>
</div>
<div><br>
</div>
<div>My getInstance for the factory class looks like this:</div>
<div>
<pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'DejaVu Sans Mono';font-size:10.5pt;"><span style="color:#bbb529;">@Override<br></span><span style="color:#cc7832;">public </span>WsFederationProvider <span style="color:#ffc66d;">getInstance</span>(KeycloakSession session<span style="color:#cc7832;">, </span>UserFederationProviderModel model) {<br>    ResteasyClient client = <span style="color:#cc7832;">new </span><span style="color:#cc7833;">ResteasyClientBuilder</span>().<span style="color:#cc7833;">build</span>()<span style="color:#cc7832;">;<br></span><span style="color:#cc7832;">    </span>ResteasyWebTarget target = client.<span style="color:#cc7833;">target</span>(<span style="color:#9876aa;font-style:italic;">BASE_URL</span>)<span style="color:#cc7832;">;<br></span><span style="color:#cc7832;">    </span><span style="font-size: 10.5pt;">WsClientService</span><span style="font-size: 10.5pt;"> serviceClient = target.</span><span style="font-size: 10.5pt; color: rgb(204, 120, 51);">proxy</span><span style="font-size: 10.5pt;">(</span><span style="font-size: 10.5pt;">WsClientService</span><span style="font-size: 10.5pt;">.</span><span style="font-size: 10.5pt; color: rgb(204, 120, 50);">class</span><span style="font-size: 10.5pt;">)</span><span style="font-size: 10.5pt; color: rgb(204, 120, 50);">;</span><span style="color:#cc7832;"><br></span><span style="color:#cc7832;"><br></span><span style="color:#cc7832;">    return new </span><span style="color:#cc7833;">WsFederationProvider</span>(session<span style="color:#cc7832;">, </span>model<span style="color:#cc7832;">, </span>serviceClient)<span style="color:#cc7832;">;<br></span>}</pre>
<div>All dependencies in my POM are 'provided', so i've already ensured that the libraries aren't duplicated.</div>
<div><br>
</div>
Based on my research so far, this seems to be the preferred way to instantiate the RestClient to ensure the classloader picks it up on boot, however I'm still getting the exception. Can anybody provide any clues?&nbsp;</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
<i></i>Regards,
<p></p>
<p><br>
</p>
<p>Crafton</p>
<p><br>
</p>
</div>
</body>
</html>