adorsys / keycloak-config-cli

Import YAML/JSON-formatted configuration files into Keycloak - Configuration as Code for Keycloak.
Apache License 2.0
714 stars 134 forks source link

keycloak-config-cli fails to start with NoClassDefFoundError: org/apache/commons/lang3/StringUtils #616

Closed thomasdarimont closed 2 years ago

thomasdarimont commented 2 years ago

Current Behavior

The latest keycloak-config-cli release 4.6.0-16.1.0 fails to start with a NoClassDefFoundError.

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-01-17 10:23:58.409 ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'keycloakConfigRunner' defined in URL [jar:file:/app/keycloak-config-cli.jar!/BOOT-INF/classes!/de/adorsys/keycloak/config/KeycloakConfigRunner.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'keycloakImportProvider' defined in URL [jar:file:/app/keycloak-config-cli.jar!/BOOT-INF/classes!/de/adorsys/keycloak/config/provider/KeycloakImportProvider.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [de.adorsys.keycloak.config.provider.KeycloakImportProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:671)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:659)
    at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1300)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:744)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:309)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290)
    at de.adorsys.keycloak.config.KeycloakConfigApplication.main(KeycloakConfigApplication.java:35)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
    at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:467)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'keycloakImportProvider' defined in URL [jar:file:/app/keycloak-config-cli.jar!/BOOT-INF/classes!/de/adorsys/keycloak/config/provider/KeycloakImportProvider.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [de.adorsys.keycloak.config.provider.KeycloakImportProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:315)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:296)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
    ... 25 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [de.adorsys.keycloak.config.provider.KeycloakImportProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:224)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:311)
    ... 39 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
    at org.apache.commons.text.matcher.StringMatcherFactory.stringMatcher(StringMatcherFactory.java:237)
    at org.apache.commons.text.StringSubstitutor.<clinit>(StringSubstitutor.java:274)
    at de.adorsys.keycloak.config.provider.KeycloakImportProvider.<init>(KeycloakImportProvider.java:77)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:211)
    ... 41 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 50 common frames omitted

Expected Behavior

keycloak-config-cli container should start without error

Steps To Reproduce

  1. create bug.yaml bug.yml:

    realm: demo
    enabled: true
  2. start keycloak 16.1.x

  3. start keycloak-config-cli container

    CLI_VERSION=v4.6.0-16.1.0
    docker run \
    -e KEYCLOAK_URL=http://localhost:8080/auth \
    -e KEYCLOAK_USER=admin \
    -e KEYCLOAK_PASSWORD=admin \
    -e KEYCLOAK_AVAILABILITYCHECK_ENABLED=true \
    -e KEYCLOAK_AVAILABILITYCHECK_TIMEOUT=120s \
    -e IMPORT_PATH=/config \
    -e IMPORT_FORCE=false \
    -e IMPORT_VARSUBSTITUTION=true \
    -e IMPORT_VARSUBSTITUTIONINVARIABLES=true \
    -v $(pwd)/bug.yaml:/config/bug.yaml:z \
    --rm \
    --net host \
    adorsys/keycloak-config-cli:$CLI_VERSION

Environment

Anything else?

No response

schmitzhermes commented 2 years ago

Hi - I spotted the same bug, it's probably related to this change 4970c9ae. It reduces the scope of the commons-lang3 dependency to test instead of the default scope compile, however it's needed at runtime. I will open a PR that fixes the issue. @jkroepke maybe you can elaborate what your intention was and if my PR #617 fixes it?

jkroepke commented 2 years ago

Thanks a lot for this finding, I don't know why this happing even on my local machine.

617 fixes this problem, thanks. But does someone knows how I could add a test for this case? All tests are green (since the dependency was scoped for test). But at the end, its not a complete end 2 end test and keycloak-config-cli has a lot test scoped dependencies.

thomasdarimont commented 2 years ago

Thanks for the quick fix!

Regarding: "But does someone knows how I could add a test for this case?" How about creating a smoke-test which starts a plain Keycloak / Keycloak.x container that is then provisionied with the keycloak-config-cli container? Then you inspect the exit code of the keycloak-config-cli container.

schmitzhermes commented 2 years ago

Hmm the only thing I can think of is starting the JAR (as a "smoke test") in the github actions build process (possibly with a failing config) and check whether the output / exit code is the one you expected