title: Keycloak Custom SPI Deployment with external Jar
body: <p>I have a SPI implementation which is:</p>
  
  <ul>
  <li>Custom SPI, directly implemented via SPI interface</li>
  <li>has an external jar which does not exist in JBoss base</li>
  </ul>
  
  <p>1) EAR deployment: I tried EAR deployment and deploy my .ear to /standalone/deployments. This solves the external jar problem which is bundled within EAR's lib folder. But now SPI is not initializing (which I saw when I debug) and also I get an exception when I trigger the SPI:</p>
  
  <pre><code>11:34:02,185 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Keycloak 9.0.2 (WildFly Core 10.0.3.Final) started in 12070ms - Started 732 of 1031 services (613 services are lazy, passive or on-demand)
  11:34:18,209 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-1) Uncaught server error: java.lang.NullPointerException
          at org.keycloak.keycloak-services@9.0.2//org.keycloak.services.DefaultKeycloakSessionFactory.getAllProviderIds(DefaultKeycloakSessionFactory.java:362)
  </code></pre>
  
  <p>Then I thought maybe keycloak is not able to import extended SPI via standalone/deployment deployment, which is also mentioned <a href="https://www.keycloak.org/docs/latest/server_development/index.html#registering-provider-implementations" rel="noreferrer">here</a> if you develop custom SPI keycloak suggests (or requires?) module deployment.</p>
  
  <p>2) Then I tried module deployment; now I can see that my custom SPI is initializing, but now keycloak can not find my external JAR. </p>
  
  <pre><code>13:17:05,682 FATAL [org.keycloak.services] (ServerService Thread Pool -- 65) java.lang.RuntimeException: org.jboss.modules.ModuleNotFoundException: com.orbitz.consul
  </code></pre>
  
  <p>As a solution, I found somewhere that I can put my dependent jar and all its dependent jar's to <strong>${KEYCLOAK_HOME}\modules\system\layers\keycloak</strong> but I don't want to install my external JAR and its all dependencies manually to keycloak's base (maybe automatically somehow?). Any solution?</p>
  
  <p>Script to deploy as a module:</p>
  
  <pre><code>./jboss-cli.bat --command="module add --name=de.easy.one.bouncer.spi.registry --resources=target/registry-spi-1.0.1-SNAPSHOT.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-services,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,javax.api,javax.ws.rs.api,com.fasterxml.jackson.core.jackson-core,com.fasterxml.jackson.core.jackson-databind,com.fasterxml.jackson.core.jackson-annotations,org.jboss.logging,com.orbitz.consul"
  </code></pre>
  
  <p>And added it to standalone.xml as follows:</p>
  
  <pre><code>&lt;provider&gt;module:de.easy.one.bouncer.spi.registry&lt;/provider&gt;
  </code></pre>
  
  <p>META-INF/services</p>
  
  <hr>
  
  <p>file name --> file content</p>
  
  <p>org.keycloak.provider.Spi --> <code>de.easy.one.bouncer.spi.registry.spi.RegistryProviderSpi</code></p>
  
  <p>de.easy.one.bouncer.spi.registry.spi.RegistryProviderFactory --> <code>de.easy.one.bouncer.spi.registry.consul.ConsulRegistryProviderFactory</code></p>
  
  <hr>
  
  <p>my pom.xml</p>
  
  <pre><code>&lt;dependencies&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
          &lt;artifactId&gt;lombok&lt;/artifactId&gt;
          &lt;scope&gt;provided&lt;/scope&gt;
          &lt;optional&gt;true&lt;/optional&gt;
      &lt;/dependency&gt;
  
      &lt;dependency&gt;
          &lt;groupId&gt;org.keycloak&lt;/groupId&gt;
          &lt;artifactId&gt;keycloak-server-spi&lt;/artifactId&gt;
          &lt;scope&gt;provided&lt;/scope&gt;
      &lt;/dependency&gt;
  
      &lt;dependency&gt;
          &lt;groupId&gt;org.keycloak&lt;/groupId&gt;
          &lt;artifactId&gt;keycloak-server-spi-private&lt;/artifactId&gt;
          &lt;scope&gt;provided&lt;/scope&gt;
      &lt;/dependency&gt;
  
      &lt;dependency&gt;
          &lt;groupId&gt;org.keycloak&lt;/groupId&gt;
          &lt;artifactId&gt;keycloak-services&lt;/artifactId&gt;
          &lt;scope&gt;provided&lt;/scope&gt;
      &lt;/dependency&gt;
  
      &lt;!-- this is not provided and I want to use as external jar --&gt;
      &lt;dependency&gt;
          &lt;groupId&gt;com.orbitz.consul&lt;/groupId&gt;
          &lt;artifactId&gt;consul-client&lt;/artifactId&gt;
          &lt;version&gt;1.4.2&lt;/version&gt;
      &lt;/dependency&gt;
  &lt;/dependencies&gt;
  </code></pre>