I am developing an MVC web application in java using spring framework and maven tool using .
I am getting the following error when i am running my application.
HTTP Status 500 - java.lang.LinkageError: loader constraint violation: when resolving method
"org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(Ljavax/servlet/ServletConfig;)Lorg/apache/tomcat/InstanceManager;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class,
org/apache/jsp/redirect_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for the method's defining class,
org/apache/jasper/runtime/InstanceManagerFactory, have different Class objects for the type org/apache/tomcat/InstanceManager used in the signature
You have server specific jar files in your WEB-INF/lib folder of your web application. For ex : jsp-api.jar, el-api.jar, servlet-api.jar etc. You need to remove exclude all these if you are using maven for dependency management.
And after removing it, if you are getting compilation error in your code, then add server runtime from Project properties.
Is there servlet-api.jar is part of war file ? Please remove it during deployment because every webserver has there own servlet-api implementation. So only use it in your code for compilation purpose.
Based on the error you posted, the classloader that is loading org/apache/jsp/redirect_jsp, and the class loader for
org/apache/jasper/runtime/InstanceManagerFactory, have different Class objects for the type org/apache/tomcat/InstanceManager which means you are referencing a jar that contains org.apache.tomcat.InstanceManager in two different class loaders and those loaders have a delegation relationship. Class objects are unique based on their fully qualified class name and their loader.
Here is a pretty good article to read about this type of error.
You need to find out how you are loading the class twice and modify your setup so that you only load it once.
As mentioned in previous posts, it should be due to conflicting libraries in your project (jsp-api, servlet-api, el-api etc) which you need to exclude.
If you are using spring-boot, you need to exclude tomcat libs when you are generating a war to be deployed in tomcat.
For ex.
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
</exclusion>
Related
I am facing this problem in spring boot application where I am using Two jars. And in those jars there are two classes with the same package name and same class name and one method with the same name . Problem occurs when class loader loads the class from different jar and tries to call this method, If jar A is loaded first then method is called and everything works fine , But if jar B is called first then, NOSUCHMETHODERROR exception is thrown at runtime. Can you please help to fix this. Is there a way by which I can force the classloader to load a particular jar first, always in Spring boot app, Or probably any other fix for this.
NOTE: I am using JAVA 8 and I don't have access to the source code of these jar files.
If you are loading those jars as a dependency you could exclude it from Maven via
<exclusions>
<exclusion>
<groupId>org.XXXX</groupId>
<artifactId>jar1-api</artifactId>
</exclusion>
</exclusions>
exception loader constraint violation: when resolving method "org.apache.hadoop.io.IOUtils.cleanup(Lorg/apache/commons/logging/Log;[Ljava/io/Closeable;)V" the class loader (instance of weblogic/utils/classloaders/ChangeAwareClassLoader) of the current class, org/apache/hadoop/hdfs/FileInputStreamCache, and the class loader (instance of weblogic/utils/classloaders/GenericClassLoader) for resolved class, org/apache/hadoop/io/IOUtils, have different Class objects for the type org/apache/commons/logging/Log used in the signature
I get this when using the application, not when deploying the ear. If i understand this wright, i have two classloaders that have two different logging objects? how can i refer them both to one?
EDIT 1
After further investigation, I think this error is due to the fact we are using a common jars library and there is another version of commons there, making them conflict. Is there any way to specify weblogic to use a specific library and not packaging? I would like to investigate this further
You need to check the WEB-INF/lib directory of your WAR files to ensure that they do not contain jars that also exist in the EAR/lib directory.
Web apps will always use the WEB-INF/lib classes before looking for them in the EAR file. However, classes loaded from the EAR will only see the other classes in the EAR. If you have the same (or similar) jar file in both places this will lead to class loading issues such as you describe.
You will have to update your weblogic-application.xml to use the use the prefer-application-package to tell the web logic to use the jar from the web-inf/lib instead of the jar from web logic. refer to the link Weblogic 10.3.5 Overriding Spring Version
<weblogic-application>
<prefer-application-packages>
<package-name>org.apache.*</package-name>
<package-name>org.springframework.*</package-name>
</prefer-application-packages>
</weblogic-application>
I've got an interesting problem in which the org.apache.log4j.Logger class is not found during runtime. I'm trying to get authorized and that is where it's failing:
OAuthAuthorizer oauthAuthorizer = new OAuthAuthorizer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET, SAML_PROVIDER_ID, userId);
I'm using JDeveloper 11.1.1.6. Here is what I know:
I've looked in my UI.war/WEB-INF/lib directory and I see the log4j-1.2.17.jar there.
The class complaining about it is org.opensaml.xml.XMLConfigurator
Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/Logger
at org.opensaml.xml.XMLConfigurator.<clinit>(XMLConfigurator.java:60)
at org.opensaml.DefaultBootstrap.initializeXMLTooling(DefaultBootstrap.java:195)
at org.opensaml.DefaultBootstrap.bootstrap(DefaultBootstrap.java:91)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.getSAMLBuilder(SAML2AssertionGenerator.java:156)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.createSubject(SAML2AssertionGenerator.java:187)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.buildAssertion(SAML2AssertionGenerator.java:114)
at com.intuit.ipp.aggcat.util.SAML2AssertionGenerator.generateSignedAssertion(SAML2AssertionGenerator.java:83)
at com.intuit.ipp.aggcat.util.SamlUtil.createSignedSAMLPayload(SamlUtil.java:156)
at com.intuit.ipp.aggcat.util.OAuthUtil.getOAuthTokens(OAuthUtil.java:60)
at com.intuit.ipp.aggcat.core.OAuthAuthorizer.<init>(OAuthAuthorizer.java:85)
at com.incomemax.view.intuit.WebUtil.getAggCatService(WebUtil.java:91)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:305)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:246)
... 64 more
I decomplied XMLConfigurator and oddly it doesn't import org.apache.log4j.Logger It uses org.slf4j.Logger which is also in my jars directory (slf4j-api-1.7.5.jar). Also interesting is that line 60 (see stack trace) is a blank line in my decompile.
Of course if I add Logger.xxxxx during design time, it finds it just fine.
I'm using the code/jars directly from the sample java code, but imported into my existing application.
I've been scouring the web for answers and I believe I've checked all the areas I can think of. I also referenced this very good page: http://myarch.com/classnotfound/
Given authorization is step 1 in using the Intuit Developer API, I'm kinda stuck.
Adding output from #jhadesdev suggestion:
All versions of log4j Logger:
zip:C:/Users/Chris/AppData/Roaming/JDeveloper/system11.1.1.6.38.61.92/DefaultDomain/servers/DefaultServer/tmp/_WL_user/j2ee-app/lt5l71/war/WEB-INF/lib/log4j-1.2.17.jar!/org/apache/log4j/Logger.class
All versions of log4j visible from the classloader of the OAuthAuthorizer class:
zip:C:/Users/Chris/AppData/Roaming/JDeveloper/system11.1.1.6.38.61.92/DefaultDomain/servers/DefaultServer/tmp/_WL_user/j2ee-app/lt5l71/war/WEB-INF/lib/log4j-1.2.17.jar!/org/apache/log4j/Logger.class
All versions of XMLConfigurator:
jar:file:/C:/Oracle/Middleware11116/modules/com.bea.core.bea.opensaml2_1.0.0.0_6-1-0-0.jar!/org/opensaml/xml/XMLConfigurator.class
zip:C:/Users/Chris/AppData/Roaming/JDeveloper/system11.1.1.6.38.61.92/DefaultDomain/servers/DefaultServer/tmp/_WL_user/j2ee-app/lt5l71/war/WEB-INF/lib/ipp-java-aggcat-v1-devkit-1.0.2.jar!/org/opensaml/xml/XMLConfigurator.class
zip:C:/Users/Chris/AppData/Roaming/JDeveloper/system11.1.1.6.38.61.92/DefaultDomain/servers/DefaultServer/tmp/_WL_user/j2ee-app/lt5l71/war/WEB-INF/lib/xmltooling-1.3.1.jar!/org/opensaml/xml/XMLConfigurator.class
All versions of XMLConfigurator visible from the class loader of the OAuthAuthorizer class:
jar:file:/C:/Oracle/Middleware11116/modules/com.bea.core.bea.opensaml2_1.0.0.0_6-1-0-0.jar!/org/opensaml/xml/XMLConfigurator.class
zip:C:/Users/Chris/AppData/Roaming/JDeveloper/system11.1.1.6.38.61.92/DefaultDomain/servers/DefaultServer/tmp/_WL_user/j2ee-app/lt5l71/war/WEB-INF/lib/ipp-java-aggcat-v1-devkit-1.0.2.jar!/org/opensaml/xml/XMLConfigurator.class
zip:C:/Users/Chris/AppData/Roaming/JDeveloper/system11.1.1.6.38.61.92/DefaultDomain/servers/DefaultServer/tmp/_WL_user/j2ee-app/lt5l71/war/WEB-INF/lib/xmltooling-1.3.1.jar!/org/opensaml/xml/XMLConfigurator.class
I'm still working on interpreting the results.
During runtime your application is unable to find the jar.
Taken from this answer by Jared:
It is important to keep two different exceptions straight in our head
in this case:
java.lang.ClassNotFoundException This an Exception, it indicates that the
class was not found on the classpath. This indicates that we were
trying to load the class definition, and the class did not exist on
the classpath.
java.lang.NoClassDefFoundError This is Error, it indicates that the JVM
looked in its internal class definition data structure for the
definition of a class and did not find it. This is different than
saying that it could not be loaded from the classpath. Usually this
indicates that we previously attempted to load a class from the
classpath, but it failed for some reason - now we're trying again,
but we're not even going to try to load it, because we failed
loading it earlier. The earlier failure could be a
ClassNotFoundException or an ExceptionInInitializerError (indicating
a failure in the static initialization block) or any number of other
problems. The point is, a NoClassDefFoundError is not necessarily a
classpath problem.
for similarities and differences
You can use the following maven dependency in your pom file. Otherwise, you can download the following two jars from net and add it to your build path.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
This is copied from my working project. First make sure it is working in your project. Then you can change the versions to use any other(versions) compatible jars.
For AggCat, you can refer the POM file of the sample java application.
https://github.com/IntuitDeveloperRelations/IPP_Sample_Code/blob/master/CustomerAccountData/Java/AggCatSampleApplication/pom.xml
Thanks
Check in Deployment Assembly,
I have the same error, when i generate the war file with the "maven clean install" way and deploy manualy, it works fine, but when i use the runtime enviroment (eclipse) the problems come.
The solution for me (for eclipse IDE) go to: "proyect properties" --> "Deployment Assembly" --> "Add" --> "the jar you need", in my case java "build path entries".
Maybe can help a litle!
With the suggestions #jhadesdev and the explanations from others, I've found the issue here.
After adding the code to see what was visible to the various class loaders I found this:
All versions of log4j Logger:
zip:<snip>war/WEB-INF/lib/log4j-1.2.17.jar!/org/apache/log4j/Logger.class
All versions of log4j visible from the classloader of the OAuthAuthorizer class:
zip:<snip>war/WEB-INF/lib/log4j-1.2.17.jar!/org/apache/log4j/Logger.class
All versions of XMLConfigurator:
jar:<snip>com.bea.core.bea.opensaml2_1.0.0.0_6-1-0-0.jar!/org/opensaml/xml/XMLConfigurator.class
zip:<snip>war/WEB-INF/lib/ipp-java-aggcat-v1-devkit-1.0.2.jar!/org/opensaml/xml/XMLConfigurator.class
zip:<snip>war/WEB-INF/lib/xmltooling-1.3.1.jar!/org/opensaml/xml/XMLConfigurator.class
All versions of XMLConfigurator visible from the classloader of the OAuthAuthorizer class:
jar:<snip>com.bea.core.bea.opensaml2_1.0.0.0_6-1-0-0.jar!/org/opensaml/xml/XMLConfigurator.class
zip:<snip>war/WEB-INF/lib/ipp-java-aggcat-v1-devkit-1.0.2.jar!/org/opensaml/xml/XMLConfigurator.class
zip:<snip>war/WEB-INF/lib/xmltooling-1.3.1.jar!/org/opensaml/xml/XMLConfigurator.class
I noticed that another version of XMLConfigurator was possibly getting picked up.
I decompiled that class and found this at line 60 (where the error was in the original stack trace) private static final Logger log = Logger.getLogger(XMLConfigurator.class); and that class was importing from org.apache.log4j.Logger!
So it was this class that was being loaded and used. My fix was to rename the jar file that contained this file as I can't find where I explicitly or indirectly load it. Which may pose a problem when I actually deploy.
Thanks for all help and the much needed lesson on class loading.
Based on the stacktrace, an intuit class com.intuit.ipp.aggcat.util.SAML2AssertionGenerator needs a saml jar on the classpath.
A saml class org.opensaml.xml.XMLConfigurator needs on it's turn log4j, which is inside the WAR but cannot find it.
One explanation for this is that the class XMLConfigurator that needs log4j was found not inside the WAR but on a downstream classloader. could a saml jar be missing from the WAR?
The class XMLConfigurator that needs log4j cannot find it at the level of the classloader that loaded it, and the log4j version on the WAR is not visible on that particular classloader.
In order to troubleshoot this, a way is to add this before the oauth call:
System.out.println("all versions of log4j Logger: " + getClass().getClassLoader().getResources("org/apache/log4j/Logger.class") );
System.out.println("all versions of XMLConfigurator: " + getClass().getClassLoader().getResources("org/opensaml/xml/XMLConfigurator.class") );
System.out.println("all versions of XMLConfigurator visible from the classloader of the OAuthAuthorizer class: " + OAuthAuthorizer.class.getClassLoader().getResources("org/opensaml/xml/XMLConfigurator.class") );
System.out.println("all versions of log4j visible from the classloader of the OAuthAuthorizer class: " + OAuthAuthorizer.class.getClassloader().getResources("org/apache/log4j/Logger.class") );
Also if you are using Java 7, have a look at jHades, it's a tool I made to help troubleshooting these type of problems.
In order to see what is going on, could you post the results of the classpath queries above, for which container is this happening, tomcat, jetty? It would be better to put the full stacktrace with all the caused by's in pastebin, just in case.
Had the same problem, it was indeed caused by weblogic stupidly using its own opensaml implementation. To solve it, you have to tell it to load classes from WEB-INF/lib for this package in weblogic.xml:
<prefer-application-packages>
<package-name>org.opensaml.*</package-name>
</prefer-application-packages>
maybe <prefer-web-inf-classes>true</prefer-web-inf-classes> would work too.
java.lang.ClassNotFoundException is indicate that class is not found in class path.
it could be the version of log4j is not compatible.
check for different log4j version.
I had the same issue, for me this fixed the issue:
right click on the project ->maven -> update project
Add compile 'org.apache.logging.log4j:log4j-1.2-api:2.17.1' and then it will automatically work
In my case, the error was due to some dependencies using log4j v 1.x that I removed from the classpath. So I introduced the log4j-1.2-api to bridge v 1.x to 2.x as recommended in the Apache Migration guide:
After introducing this dependency in my build.gradle, the error disappeared :
implementation 'org.apache.logging.log4j:log4j-1.2-api:2.17.+!!'
Following works for me everytime I face the problem
rightclick on project(say abc-war)-> properties -> Deployment assembly->add->java build path entries->Maven dependencies.
I have updated our projects (Java EE based running on Websphere 8.5) to use a new release of a company internal framework (and Ejb 3.x deployment descriptors rather than the 2.x ones). Since then my integration Tests fail with the following exception:
[java.lang.ClassNotFoundException: com.ibm.xml.xlxp2.jaxb.JAXBContextFactory]
I can build the application with the previous framework release and everything works fine.
While debugging i noticed that within the ContextFinder (javax.xml.bind) there are two different behaviours:
Previous Version (Everything works just fine): None of the different places brings up a factory class so the default factory class gets loaded which is com.sun.xml.internal.bind.v2.ContextFactory (defined as String constant within the class).
Upgraded Version (ClassNotFound): There is a resource "META-INF/services/javax.xml.bind.JAXBContext" beeing loaded successfully and the first line read makes the ContextFinder attempt to load "com.ibm.xml.xlxp2.jaxb.JAXBContextFactory" which causes the error.
I now have two questions:
What sort is that resource? Because inside our EAR there is two WARs and none of those two contains a folder services in its
META-INF directory.
Where could that value be from otherwise? Because a filediff showed me no new or changed properties files.
No need to say i am going to read all about the JAXB configuration possibilities but if you have first insights on what could have gone wrong or help me out with that resource (is it a real file i have to look for?) id appreciate a lot. Many Thanks!
EDIT (according to comments Input/Questions):
Out of curiosity, does your framework include JAXB JARs? Did the old version of your framework include jaxb.properties?
Indeed (i am a bit surprised) the framework has a customized eclipselink-2.4.1-.jar inside the EAR that includes both a JAXB implementation and a jaxb.properties file that shows the following entry in both versions (the one that finds the factory as well as in the one that throws the exception):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
I think this is has nothing to do with the current issue since the jar stayed exactly the same in both EARs (the one that runs/ the one with the expection)
It's also not clear to me why the old version of the framework was ever selecting the com.sun implementation
There is a class javax.xml.bind.ContextFinder which is responsible for initializing the JAXBContextFactory. This class searches various placess for the existance of a jaxb.properties file or a "javax.xml.bind.JAXBContext" resource. If ALL of those places dont show up which Context Factory to use there is a deault factory loaded which is hardcoded in the class itself:
private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
Now back to my problem:
Building with the previous version of the framework (and EJB 2.x deployment descriptors) everything works fine). While debugging i can see that there is no configuration found and thatfore above mentioned default factory is loaded.
Building with the new version of the framework (and EJB 3.x deployment descriptors so i can deploy) ONLY A TESTCASE fails but the rest of the functionality works (like i can send requests to our webservice and they dont trigger any errors). While debugging i can see that there is a configuration found. This resource is named "META-INF/services/javax.xml.bind.JAXBContext". Here are the most important lines of how this resource leads to the attempt to load 'com.ibm.xml.xlxp2.jaxb.JAXBContextFactory' which then throws the ClassNotFoundException. This is simplified source of the mentioned javax.xml.bind.ContextFinder class:
URL resourceURL = ClassLoader.getSystemResource("META-INF/services/javax.xml.bind.JAXBContext");
BufferedReader r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8"));
String factoryClassName = r.readLine().trim();
The field factoryClassName now has the value 'com.ibm.xml.xlxp2.jaxb.JAXBContextFactory'
Because this has become a super lager question i will also add a bounty :)
I will work the entire day on this and let you know if there is any news.
Update/ Solution
This question has been solved. The original problem has occured because misconfiguration of complexly build multi model maven projects which one dependency used a updated version of a customized eclipse link jar that contained a definition for a JAXBFactory not available in the component where the error occured. Setting the JAXB context factory in most cases is configured with a jaxb.propertie file or JAXBContext file that contains the same definition. Detailed loading process of the appropriate JAXBContextFactory happens in javax.xml.bind.ContextFinder.
The error has not yet been solved (during the fact over 4 major EE/SE Applications lead to the error) and there is no general answer but that defined JAXBContextFactorys must exist in your classpath (wow what a wonder...) so you either have a that ClassNotFound Error because youre missing resources (well thats the acctual cause) or because you have a wrong JAXBContextFactory defined in any of the above mentioned propertie files which contain a definition according to the below answer.
Very many thanks for your great comments and support, i realy appreciate!
You can include a jaxb.properties file in the same package as your domain model to specify the JAXB (JSR-222) implementation you wish to use. For example it would look like the following to specify EclipseLink MOXy as your JAXB provider.
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
For More Information
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
Another quick and dirty solution (a workaround, really) that worked for me is to explicitly include a JAXB implementation to the maven build. For example
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.7</version>
</dependency>
Note that this adds a somehow unnecessary dependency to your build, as JAXB obviously already is part of each JRE >= version 6.
Most likely this will only work when the WAS classloader is set to parent last.
Developing a heavily XML-based Java-application, I recently encountered an interesting problem on Ubuntu Linux.
My application, using the Java Plugin Framework, appears unable to convert a dom4j-created XML document to Batik's implementation of the SVG specification.
On the console, I learn that an error occurs:
Exception in thread "AWT-EventQueue-0" java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;" the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader) of the current class, org/apache/batik/dom/svg/SVGOMDocument, and the class loader (instance of <bootloader>) for interface org/w3c/dom/Document have different Class objects for the type org/w3c/dom/Attr used in the signature
at org.apache.batik.dom.svg.SVGDOMImplementation.createDocument(SVGDOMImplementation.java:149)
at org.dom4j.io.DOMWriter.createDomDocument(DOMWriter.java:361)
at org.dom4j.io.DOMWriter.write(DOMWriter.java:138)
I figure that the problem is caused by a conflict between the original classloader from the JVM and the classloader deployed by the plugin framework.
To my knowledge, it's not possible to specify a classloader for the framework to use. It might be possible to hack it, but I would prefer a less aggressive approach to solving this problem, since (for whatever reason) it only occurs on Linux systems.
Has one of you encountered such a problem and has any idea how to fix it or at least get to the core of the issue?
LinkageError is what you'll get in a classic case where you have a class C loaded by more than one classloader and those classes are being used together in the same code (compared, cast, etc). It doesn't matter if it is the same Class name or even if it's loaded from the identical jar - a Class from one classloader is always treated as a different Class if loaded from another classloader.
The message (which has improved a lot over the years) says:
Exception in thread "AWT-EventQueue-0" java.lang.LinkageError:
loader constraint violation in interface itable initialization:
when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;"
the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader)
of the current class, org/apache/batik/dom/svg/SVGOMDocument,
and the class loader (instance of ) for interface org/w3c/dom/Document
have different Class objects for the type org/w3c/dom/Attr used in the signature
So, here the problem is in resolving the SVGOMDocument.createAttribute() method, which uses org.w3c.dom.Attr (part of the standard DOM library). But, the version of Attr loaded with Batik was loaded from a different classloader than the instance of Attr you're passing to the method.
You'll see that Batik's version seems to be loaded from the Java plugin. And yours is being loaded from " ", which is most likely one of the built-in JVM loaders (boot classpath, ESOM, or classpath).
The three prominent classloader models are:
delegation (the default in the JDK - ask parent, then me)
post-delegation (common in plugins, servlets, and places where you want isolation - ask me, then parent)
sibling (common in dependency models like OSGi, Eclipse, etc)
I don't know what delegation strategy the JPF classloader uses, but the key is that you want one version of the dom library to be loaded and everyone to source that class from the same location. That may mean removing it from the classpath and loading as a plugin, or preventing Batik from loading it, or something else.
Sounds like a classloader hierarchy problem. I can't tell what type of environment your application is deployed in, but sometimes this problem can occur in a web environment - where the application server creates a hierarchy of classloaders, resembling something like:
javahome/lib - as root
appserver/lib - as child of root
webapp/WEB-INF/lib - as child of child of root
etc
Usually classloaders delegate loading to their parent classloader (this is known as "parent-first"), and if that classloader cannot find the class, then the child classloader attempts to. For example, if a class deployed as a JAR in webapp/WEB-INF/lib tries to load a class, first it asks the classloader corresponding to appserver/lib to load the class (which in turn asks the classloader corresponding to javahome/lib to load the class), and if this lookup fails, then WEB-INF/lib is searched for a match to this class.
In a web environment, you can run into problems with this hierarchy. For example, one mistake/problem I've run into before was when a class in WEB-INF/lib depended on a class deployed in appserver/lib, which in turn depended on a class deployed in WEB-INF/lib. This caused failures because while classloaders are able to delegate to the parent classloader, they cannot delegate back down the tree. So, the WEB-INF/lib classloader would ask appserver/lib classloader for a class, appserver/lib classloader would load that class and try to load the dependent class, and fail since it could not find that class in appserver/lib or javahome/lib.
So, while you may not be deploying your app in a web/app server environment, my too-long explanation might apply to you if your environment has a hierarchy of classloaders set up. Does it? Is JPF doing some sort of classloader magic to be able to implement it's plugin features?
May be this will help someone because it works out pretty good for me. The issue can be solve by integrating your own dependencies. Follow this simple steps
First check the error which should be like this :
Method execution failed:
java.lang.LinkageError: loader constraint violation:
when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;"
the class loader (instance of org/openmrs/module/ModuleClassLoader) of the current class, org/slf4j/LoggerFactory,
and the class loader (instance of org/apache/catalina/loader/WebappClassLoader) for resolved class, org/slf4j/impl/StaticLoggerBinder,
have different Class objects for the type taticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory; used in the signature
See the two highlighted class. Google search for them like "StaticLoggerBinder.class jar download" & "LoggeraFactory.class jar download". This will show you first or in some case second link (Site is http://www.java2s.com ) which is one of the jar version you have included in your project. You can smartly identify it yourself, but we are addicted of google ;)
After that you will know the jar file name, in my case it is like slf4j-log4j12-1.5.6.jar & slf4j-api-1.5.8
Now the latest version of this file is available here http://mvnrepository.com/ (actually all version till date, this is the site from where maven get your dependencies).
Now add both file as a dependencies with the latest version (or keep both file version same, either chosen version is old). Following is the dependency you have to include in pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
Can you specify a class loader? If not, try specifying the context class loader like so:
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(yourClassLoader);
callDom4j();
} finally {
thread.setContextClassLoader(contextClassLoader);
}
I'm not familiar with the Java Plugin Framework, but I write code for Eclipse, and I run into similar issues from time to time. I don't guarantee it'll fix it, but it's probably worth a shot.
The answers from Alex and Matt are very helpful. I could benefit from their analysis too.
I had the same problem when using the Batik library in a Netbeans RCP framework, the Batik library being included as a "Library Wrapper Module". If some other module makes use of XML apis, and no dependency on Batik is needed and established for that module, the class loader constraint violation problem arises with similar error messages.
In Netbeans, individual modules use dedicated class loaders, and the dependence relationship between modules implies suitable class loader delegation routing.
I could resolve the problem by simply omitting the xml-apis jar file from the Batik library bundle.
As specified in this question, enabling the -verbose:class will make the JVM log information about all classes being loaded, which can be incredibly helpful to understand where the classes are coming from in more complex scenarios & applications.
The output you get looks roughly like this (copied from that question):
[Opened /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/sunrsasign.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jsse.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jce.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/charsets.jar]
[Loaded java.lang.Object from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.io.Serializable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.String from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
I find this class be loaded twice. Find the reason is that parallelWebappClassLoader load class by itself first rather than use it's parent classLoader.