Keycloak theme selector SPI setup

Hii,

As per out project requirement we need the different theme for the different clients under same realm,
as per the keycloak official documentation got the below reference for creating the theme selector SPI
https://www.keycloak.org/docs/latest/server_development/#_implementing_spi

i’m new to maven plugin development, does any one have proper SPI example setup for same,
also what are the steps if i want to deploy that theme selectors SPI plugin to the keycloak server hosted on the docker

Hii,

i followed the keycloak documentation and created the themeSelector SPI,
also set it as default themeSelector, by adding entry to the standalone.xml file and added themeSelectorSPI to the deployments directory of keycloak server.

but the server is not able to start and getting below error
and server doesn’t start

I already followed the existing questions solutions

Error Log which prevent keycloak server from starting:


15:13:52,365 INFO  [org.keycloak.services] (ServerService Thread Pool -- 60) KC-SERVICES0001: Loading config from standalone.xml or domain.xml
15:13:52,895 INFO  [org.keycloak.url.DefaultHostnameProviderFactory] (ServerService Thread Pool -- 60) Frontend: <request>, Admin: <frontend>, Backend: <request>
15:13:53,114 FATAL [org.keycloak.services] (ServerService Thread Pool -- 60) Error during startup: java.lang.RuntimeException: Failed to find provider {interface org.keycloak.forms.account.AccountProvider=freemarker, interface org.keycloak.forms.login.LoginFormsProvider=freemarker, interface org.keycloak.services.x509.X509ClientCertificateLookup=default, interface org.keycloak.headers.SecurityHeadersProvider=default, interface org.keycloak.events.EventStoreProvider=jpa, interface org.keycloak.transaction.JtaTransactionManagerLookup=jboss, interface org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionProvider=default} for themeSelector
        at org.keycloak.keycloak-services@11.0.0//org.keycloak.services.DefaultKeycloakSessionFactory.checkProvider(DefaultKeycloakSessionFactory.java:188)
        at org.keycloak.keycloak-services@11.0.0//org.keycloak.services.DefaultKeycloakSessionFactory.init(DefaultKeycloakSessionFactory.java:98)
        at org.keycloak.keycloak-services@11.0.0//org.keycloak.services.resources.KeycloakApplication.createSessionFactory(KeycloakApplication.java:260)
        at org.keycloak.keycloak-services@11.0.0//org.keycloak.services.resources.KeycloakApplication.startup(KeycloakApplication.java:124)
        at org.keycloak.keycloak-wildfly-extensions@11.0.0//org.keycloak.provider.wildfly.WildflyPlatform.onStartup(WildflyPlatform.java:29)
        at org.keycloak.keycloak-services@11.0.0//org.keycloak.services.resources.KeycloakApplication.<init>(KeycloakApplication.java:114)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
        at org.jboss.resteasy.resteasy-jaxrs@3.12.1.Final//org.jboss.resteasy.core.ConstructorInjectorImpl.construct(ConstructorInjectorImpl.java:152)
        at org.jboss.resteasy.resteasy-jaxrs@3.12.1.Final//org.jboss.resteasy.spi.ResteasyProviderFactory.createProviderInstance(ResteasyProviderFactory.java:2811)
        at org.jboss.resteasy.resteasy-jaxrs@3.12.1.Final//org.jboss.resteasy.spi.ResteasyDeployment.createApplication(ResteasyDeployment.java:371)
        at org.jboss.resteasy.resteasy-jaxrs@3.12.1.Final//org.jboss.resteasy.spi.ResteasyDeployment.startInternal(ResteasyDeployment.java:283)
        at org.jboss.resteasy.resteasy-jaxrs@3.12.1.Final//org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:93)
        at org.jboss.resteasy.resteasy-jaxrs@3.12.1.Final//org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.init(ServletContainerDispatcher.java:140)
        at org.jboss.resteasy.resteasy-jaxrs@3.12.1.Final//org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.init(HttpServletDispatcher.java:42)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.security.RunAsLifecycleInterceptor.init(RunAsLifecycleInterceptor.java:78)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:103)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:305)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.ManagedServlet.createServlet(ManagedServlet.java:145)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:585)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:556)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1530)
        at io.undertow.servlet@2.1.3.Final//io.undertow.servlet.core.DeploymentManagerImpl.start(DeploymentManagerImpl.java:598)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:97)
        at org.wildfly.extension.undertow@20.0.1.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:78)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
        at java.base/java.lang.Thread.run(Thread.java:830)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.JBossThread.run(JBossThread.java:485)

Any suggestions or workaround for this issue ?

@xgp any solutions or workaround on this issue i’m facing?

@scSameer94 you have an option to select theme per client in ui:

Thanks @Polkovodin

I already tried that solution.
i have one realm inside that i creted 2 clients client A and client B,
then i added one custom theme and selected it to the client A and client b has default theme only.
but after redirection to client A, that custom theme is not loaded,
unless and until i apply that custom theme to the Realm.

i’m using the keycloak standalone server version 11.0.0

Is there any another configuration that need to be setup for this to work, if yes then please suggest, as setting up ThemeSelector SPI taking lot time than i expected.

Thanks @Polkovodin I tried this client themes setting with keycloak server latest version 15.0.2,
It seems to work fine with that version.
i.e. we i tried custom theme to one client and default theme to another client, it loads client themes only after redirection.
it seems it has some issues with lower versions, but we’re upgrading to latest version so my issue is resolved.