Issue
I got this issue these days, when I'm migrating spring-security-saml-extensions-1-x to spring-security-saml2-service-provider which depends on opensaml 3.4.6. At first, I thought it's caused by re-initialize opensaml somehow, from the href="https://docs.spring.io/spring-security/reference/servlet/saml2/login/overview.html#servlet-saml2login-opensaml-customization" rel="nofollow noreferrer">documentation, it says it
Any class that uses both Spring Security and OpenSAML should statically initialize OpenSamlInitializationService at the beginning of the class.
But no matter I remove the line or not
static {
OpenSamlInitializationService.initialize();
}
The issue still happens. The stackframes like:
java.lang.IllegalStateException: Unable to load cache item
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:79)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572)
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:419)
at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:137)
......
Caused by: java.util.ServiceConfigurationError: org.opensaml.core.config.Initializer: Provider org.opensaml.xacml.config.impl.XMLObjectProviderInitializer not a subtype
at java.util.ServiceLoader.fail(ServiceLoader.java:239)
at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
at java.util.ServiceLoader$LazyIterator.access$700(ServiceLoader.java:323)
at java.util.ServiceLoader$LazyIterator$2.run(ServiceLoader.java:407)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:409)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
at org.opensaml.core.config.InitializationService.initialize(InitializationService.java:53)
at org.springframework.security.saml2.core.OpenSamlInitializationService.initialize(OpenSamlInitializationService.java:122)
at org.springframework.security.saml2.core.OpenSamlInitializationService.initialize(OpenSamlInitializationService.java:97)
at com.mytestsvr.api.config.SecurityConfig.<clinit>(SecurityConfig.java:284)
......
I think it's loaded twice since there's a cache item in the stack, but I don't have such opensaml in webapp folder except this one. Any suggestion for resolving such issue? Thanks in advance.
Solution
Finally, I googled an answer for this issue on the opensaml forum, http://shibboleth.net/pipermail/dev/2016-July/008417.html It says:
Since we know for a fact that org.opensaml.core.xml.config.XMLObjectProviderInitializer is absolutely a subtype of org.opensaml.core.config.Initializer (it's an impl of that interface)....
The only way that I know that this could happen is if you have a very strange classloader environment. This can happen if you have the jars living in different classloaders in a hierarchical environment (like a servlet container), and/or duplicate jars in the different classloaders. The classloader itself is part of the "identity" of a class. So for example if you have an instance of Foo from classloader A, and you do an "foo instanceof Foo" where the class of the latter Foo is loaded from classloader B, it will evaluate false. And the same is true for other cases of evaluating an instance's class identity against a class literal, etc.
To avoid all that, do not spread your jars (in this case OpenSAML) across multiple classloaders or have duplicate jars in different classloaders. If this is a web app, put all the OpenSAML jars in your war, and nowhere else. Specifically, make sure there are no other copies in the servlet container's other classloaders.
And I find that the process which start the tomcat has loaded another opensaml being introduced as the dependency of a framework(but it's actually no use, I think that's why it's hard to find out that in the directory). After removing this opensaml, it works fine!!!
Answered By - Ron
Answer Checked By - Cary Denson (JavaFixing Admin)