Hello
I am using the latest keycloak-x docker image. (Quarkus distribution)
I am trying to create a custom user spi, to try it basically.
I don’t know if it’s a build issue or a code issue, but when Keycloak loads the extension, I got this stacktrace:
my-app-auth-1 | ERROR: Failed to run 'build' command.
my-app-auth-1 | ERROR: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
my-app-auth-1 | [error]: Build step org.keycloak.quarkus.deployment.KeycloakProcessor#configureProviders threw an exception: java.util.ServiceConfigurationError: org.keycloak.storage.UserStorageProviderFactory: org.example.keycloakuserstore.CustomUserStorageProviderFactory Unable to get public no-arg constructor
my-app-auth-1 | at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:582)
my-app-auth-1 | at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:673)
my-app-auth-1 | at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1233)
my-app-auth-1 | at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1265)
my-app-auth-1 | at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1300)
my-app-auth-1 | at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1385)
my-app-auth-1 | at org.keycloak.provider.DefaultProviderLoader.load(DefaultProviderLoader.java:60)
my-app-auth-1 | at org.keycloak.provider.ProviderManager.load(ProviderManager.java:94)
my-app-auth-1 | at org.keycloak.quarkus.deployment.KeycloakProcessor.loadFactories(KeycloakProcessor.java:404)
my-app-auth-1 | at org.keycloak.quarkus.deployment.KeycloakProcessor.configureProviders(KeycloakProcessor.java:247)
my-app-auth-1 | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
my-app-auth-1 | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
my-app-auth-1 | at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
my-app-auth-1 | at java.base/java.lang.reflect.Method.invoke(Method.java:566)
my-app-auth-1 | at io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:887)
my-app-auth-1 | at io.quarkus.builder.BuildContext.run(BuildContext.java:277)
my-app-auth-1 | at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
my-app-auth-1 | at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
my-app-auth-1 | at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
my-app-auth-1 | at java.base/java.lang.Thread.run(Thread.java:829)
my-app-auth-1 | at org.jboss.threads.JBossThread.run(JBossThread.java:501)
my-app-auth-1 | Caused by: java.lang.NoSuchMethodException: org.example.keycloakuserstore.CustomUserStorageProviderFactory.<init>()
my-app-auth-1 | at java.base/java.lang.Class.getConstructor0(Class.java:3349)
my-app-auth-1 | at java.base/java.lang.Class.getConstructor(Class.java:2151)
my-app-auth-1 | at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:660)
my-app-auth-1 | at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:657)
my-app-auth-1 | at java.base/java.security.AccessController.doPrivileged(Native Method)
my-app-auth-1 | at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:668)
my-app-auth-1 | ... 19 more
Here is the content of the CustomUserStorageProviderFactory:
class CustomUserStorageProviderFactory implements UserStorageProviderFactory<CustomUserStorageProvider> {
@Override
public CustomUserStorageProvider create(KeycloakSession session, ComponentModel model) {
// here you can setup the user storage provider, initiate some connections, etc.
CustomRepository repository = new CustomRepository();
return new CustomUserStorageProvider(session, model, repository);
}
@Override
public String getId() {
return "demo-user-provider";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return ProviderConfigurationBuilder.create()
.property("myParam", "My Param", "Some Description", ProviderConfigProperty.STRING_TYPE, "some value", null)
.build();
}
}
I didn’t overrided the init
method because I want the default behavior. But this stack trace line is weird : Caused by: java.lang.NoSuchMethodException: org.example.keycloakuserstore.CustomUserStorageProviderFactory.<init>()
. So I tried to add an init method, but it doesn’t change anything.
Here is the content of my gradle build (I’m new to this Java world):
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.keycloak:keycloak-core:16.0.0'
implementation 'org.keycloak:keycloak-services:16.0.0'
implementation 'org.keycloak:keycloak-server-spi:16.0.0'
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
}
test {
useJUnitPlatform()
}
I do have a META-INF
as the doc state, META-INF/services/org.keycloak.storage.UserStorageProviderFactory
:
org.example.keycloakuserstore.CustomUserStorageProviderFactory
Can you help me figure it out why it is not loading?
Thanks in advance, and if you need any other informations, please, let me know.
EDIT: I tried to:
- use Java 17, 11 and 1.8
- use Maven instead of Gradle with a pom.xml taken from keycloak-quickstarts
- use other keycloak x version (15 and 16)
Nothing have worked so far. I’m pretty sure it’s not a big thing, but, eh, I don’t know what it is.