Java Class Loader issue/Maven issue in multiple Jetty container - java

I have a big appliance running using multiple application. I have multiple Jetty containers where multiple applications are deployed to each container.. Now, i am facing a simple class not found warning while deploying the application.
This is my analysis:
JettyContainer_1 contain App_1 which has many common JAR files which can be shared across all other containers so all applications can access these JAR files.
Now, the problems is that a spring framework class in shared libs in JettyContainer_1 is trying to load a class "ClassAInContainer3"(from jar file) from App_X in container 3. Then am getting the class not found error..
Here is the stack trace..
Caused by: java.lang.ClassNotFoundException: com.test.ClassAInContainer3
at java.net.URLClassLoader$1.run(URLClassLoader.java:366) ~[na:1.7.0_55]
at java.net.URLClassLoader$1.run(URLClassLoader.java:355) ~[na:1.7.0_55]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_55]
at java.net.URLClassLoader.findClass(URLClassLoader.java:354) ~[na:1.7.0_55]
at java.lang.ClassLoader.loadClass(ClassLoader.java:425) ~[na:1.7.0_55]
at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ~[na:1.7.0_55]
at org.springframework.util.ClassUtils.forName(ClassUtils.java:258) ~[spring-core.jar:3.2.0.RELEASE]
at org.springframework.amqp.support.converter.DefaultJavaTypeMapper.getClassIdType(DefaultJavaTypeMapper.java:82) ~[spring-amqp.jar:na]
... 16 common frames omitted
2015-08-19 05:38:16.123 UTC,WARN ,App1-web,messaging,com.test.Rabbit,null,SimpleAsyncTaskExecutor-1,Caught an exception while handling a rabbitmq message, Publisher/Consumer should have handled this.
org.springframework.amqp.support.converter.MessageConversionException: failed to resolve class name. Class not found [com.test.ClassAInContainer3]
at org.springframework.amqp.support.converter.DefaultJavaTypeMapper.getClassIdType(DefaultJavaTypeMapper.java:85) ~[spring-amqp.jar:na]
at org.springframework.amqp.support.converter.DefaultJavaTypeMapper.toJavaType(DefaultJavaTypeMapper.java:53) ~[spring-amqp.jar:na]
at org.springframework.amqp.support.converter.JsonMessageConverter.fromMessage(JsonMessageConverter.java:117) ~[spring-amqp.jar:na]
Any inputs on how to resolve this.. I am using Maven for building the application.. I suspect this is becoz since both libs are in different location, the spring class(present in jettyContainer1) cannot load the ClassAInContainer3 from App_3. So may be we can add some dependencies or class loader configurations..
Any inputs will be much appreciated.. Thanks in advance.. :)

The exception makes sense if the "spring framework class" is loaded by the Jetty class loader and the ClassAInContainer3 is loaded by the WebAppClassLoader (typically so, if it is in WEB-INF/lib or WEB-INF/classes of a webapp).
I started a Jetty server in debug and executed the following commands (in the Display view in Eclipse) while blocked in a breack point inside a web controller (i.e. I'm executing code loaded by a WebAppClassLoader):
this.getClass().getClassLoader()
org.eclipse.jetty.webapp.WebAppClassLoader) WebAppClassLoader=653648989#26f5e45d
If I try to climb the class loader hierarchy, I get the server class loader of Jetty:
this.getClass().getClassLoader().getParent()
(org.codehaus.plexus.classworlds.realm.ClassRealm) ClassRealm[plugin>org.eclipse.jetty:jetty-maven-plugin:9.3.2.v20150730, parent: sun.misc.Launcher$AppClassLoader#58644d46]
this is the root class loader, beyond this point I cannot go, in fact:
this.getClass().getClassLoader().getParent().getParent()
null
Now, if I invoke loadClass in the code of a class that's been loaded by the AppClassLoader (at server startup, typically), It will use its own class loader first (that is, the AppClassLoader itself) and then, if the class is not found, the parent class loader (because the servlet container will use a "parent last" loading strategy, but note that, as I stated before, there is no other class loader beyond AppClassLoader).
But it is perfectly feasible that the ClassAInContainer3 is not reachable by the AppClassLoader, because it is not in the classpath that is known to it. In fact look what happens if I try to load an instance of my web controller (a class contained in WEB-INF/classes) with the AppClassLoader:
this.getClass().getClassLoader().getParent().loadClass("org.test.showcase.HomeController")
Evaluation failed. Reason(s):
An exception occurred: java.lang.ClassNotFoundException
Exactly what I suspect is happening in your case.

Related

JAXB not available on Tomcat 9 and Java 9/10

TLDR: On Java 9/10, a web app in Tomcat has no access to JAXB even though its reference implementation is present on the class path.
Edit: No, this is not a duplicate of How to resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException in Java 9 - as you can tell by the What I tried section, I already tried the proposed solutions.
The Situation
We have a web app that runs on Tomcat and depends on JAXB. During our migration to Java 9 we opted for adding the JAXB reference implementation as a regular dependency.
Everything worked when launching the app from the IDE with embedded Tomcat, but when running it on a real Tomcat instance, I get this error:
Caused by: java.lang.RuntimeException: javax.xml.bind.JAXBException:
Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
at [... our-code ...]
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:278) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.find(ContextFinder.java:421) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.0.jar:2.3.0]
at [... our-code ...]
Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582) ~[?:?]
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190) ~[?:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:499) ~[?:?]
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:122) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:155) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:276) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.find(ContextFinder.java:421) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.0.jar:2.3.0]
at [... our-code ...]
Note:
Implementation of JAXB-API has not been found on module path or classpath.
These are the relevant files in webapps/$app/WEB-INF/lib:
jaxb-api-2.3.0.jar
jaxb-core-2.3.0.jar
jaxb-impl-2.3.0.jar
What is going on here?
What I tried
Adding JARs to Tomca's CLASSPATH
Maybe it helps to add the JARs to Tomcat's class path in setenv.sh?
CLASSPATH=
.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar:
.../webapps/$app/WEB-INF/lib/jaxb-impl-2.3.0.jar:
.../webapps/$app/WEB-INF/lib/jaxb-core-2.3.0.jar:
.../webapps/$app/WEB-INF/lib/javax.activation-1.2.0.jar
Nope:
Caused by: javax.xml.bind.JAXBException: ClassCastException: attempting to cast
jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bind/JAXBContext.class to
jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bind/JAXBContext.class.
Please make sure that you are specifying the proper ClassLoader.
at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:157) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:300) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:286) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.ContextFinder.find(ContextFinder.java:409) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.0.jar:2.3.0]
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.0.jar:2.3.0]
at de.disy.gis.webmapserver.factory.DefaultWmsRequestFactory.initializeCommandExtractor(DefaultWmsRequestFactory.java:103) ~[cadenza-gis-webmapserver-7.7-SNAPSHOT.jar:7.6]
at de.disy.gis.webmapserver.factory.DefaultWmsRequestFactory.lambda$new$0(DefaultWmsRequestFactory.java:87) ~[cadenza-gis-webmapserver-7.7-SNAPSHOT.jar:7.6]
That's clearly the same class, so apparently it has been loaded by two class loaders. I suspect the system class loader and the app's class loader, but why would loading JAXBContext be delegated to the system class loader once but not always? It almost looks as if the delegation behavior of the app's class loader changes while the program runs.
Adding the module
I don't really want to add java.xml.bind, but I tried it anyways by adding this to catalina.sh:
JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-modules=java.xml.bind"
Doesn't work either, though:
Caused by: java.lang.ClassCastException:
java.xml.bind/com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl
cannot be cast to com.sun.xml.bind.v2.runtime.JAXBContextImpl
at [... our-code ...]
Apart from the different class and stack trace, this is in line with what happened earlier: The class JAXBContextImpl was loaded twice, once from java.xml.bind (must have been the system class loader) and one other time (I assume by the app's loader from the JAR).
Searching for bugs
Searching Tomcat's bug database I found #62559. Could that be the same error?
Adding JAR's to Tomcat's lib
Following advice given on the Tomcat user mailing list, I added the JAXB JARs to Tomcat's CATALINA_BASE/lib directory, but got the same error as in the application's lib folder.
Analysis
First some random facts:
if not given a class loader, JAXBContext::newInstance will use the thread's context class loader when looking for the JAXB implementation - this is the case even if you call newInstance(Class...) (one might mistakenly think it uses the provided class instances' loader)
Tomcat builds a small class loader hierarchy to separate web applications from one another
by not relying on the module java.xml.bind, in Java 9, JAXB classes are not loaded by the bootstrap or system class loader
So here's what happened on Java 8:
we don't pass a class loader to JAXB (oops), so it uses the thread's context class loader
our conjecture is that Tomcat does not explicitly set the context class loader and so it will end up being the same one that loaded Tomcat: the system class loader
that's dandy because the system class loader sees the entire JDK and hence the JAXB implementation included therein
Java 9 enters - the piano stops playing and everybody puts down their scotch:
we added JAXB as a regular dependency and so it is loaded by the web app's class loader
just as on Java 8, JAXB searches the system class loader, though, and that one can't see the app's loader (only the other way around)
JAXB fails to find the implementation and goes belly up
Solution
The solution is to make sure JAXB uses the right class loader. We know of three ways:
call Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); but that's not really a good idea
create a context resolver, but that requires JAX-WS and that feels like replacing one evil with another
use the package-accepting variant of JAXBContext::newInstance (Javadoc from Java EE 7) that also takes a class loader and pass the correct loader, although that requires some refactoring
We used the third option and refactored towards the package-accepting variant of JAXBContext::newInstance. Menial work, but fixed the problem.
Note
User curlals provided the critical piece of information, but deleted their answer. I hope it was not because I asked for a few edits. All credit/karma should go to them! #curlals: If you restore and edit your answer, I will accept and upvote it.
Try the following and its dependencies. See a Maven repository for latest version.
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.0.1</version>
</dependency>
It also contains the Java Service Loader descriptors. See Using JAXB in Java 9+
I had this issue using Spring Boot (version 2.2.6) with embedded Tomcat in a specific part of my code where I used a CompletableFuture. The code worked perfectly with Java 8 and related unit test passed in Java 12. The issue appeared only when the application was executed inside Tomcat using Java 11 or 12.
Debugging the problem I discovered the issue was related to the fact that a different ClassLoader is used inside the CompletableFuture's Runner.
// here Thread.currentThread().getContextClassLoader().getClass()
// returns org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader
return CompletableFuture.runAsync(() -> {
// here returns jdk.internal.loader.ClassLoaders$AppClassLoader
});
The second ClassLoader is not able to load the JAXB classes. This behavior seems to be present only with Java 9+, indeed before Java 9 ForkJoinPool.common() returned an Executor with a ClassLoader of your main Thread, but after Java 9 it returns an executor with system ClassLoader.
Since the CompletableFuture.runAsync() method accepts an Executor as second parameter, it is possible to set the desired Executor in the code. Here an example of a possible solution.
First, define a proper ForkJoinWorkerThreadFactory:
public class JaxbForkJoinWorkerThreadFactory implements ForkJoinWorkerThreadFactory {
private final ClassLoader classLoader;
public JaxbForkJoinWorkerThreadFactory() {
classLoader = Thread.currentThread().getContextClassLoader();
}
#Override
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
ForkJoinWorkerThread thread = new JaxbForkJoinWorkerThread(pool);
thread.setContextClassLoader(classLoader);
return thread;
}
private static class JaxbForkJoinWorkerThread extends ForkJoinWorkerThread {
private JaxbForkJoinWorkerThread(ForkJoinPool pool) {
super(pool);
}
}
}
Then pass an Executor using that factory to the runAsync() method:
return CompletableFuture.runAsync(() -> {
// now you have the right ClassLoader here
}, getJaxbExecutor());
private ForkJoinPool getJaxbExecutor() {
JaxbForkJoinWorkerThreadFactory threadFactory = new JaxbForkJoinWorkerThreadFactory();
int parallelism = Math.min(0x7fff /* copied from ForkJoinPool.java */, Runtime.getRuntime().availableProcessors());
return new ForkJoinPool(parallelism, threadFactory, null, false);
}
TL;DR
A simple solution that worked for me is just to upgrade the Hibernate version.
I used Hibernate with version of 5.2.10.Final and they rely on JAXB. However, when I replaced undertow with Tomcat, that dependency went missing. I found this issue but none of the answers really solved my issue. When I found that jpa-model-gen was the issue I quickly realized, that it is the onlt Hibernate dependecy only that is looking for JAXB. Updating the hibernate version to a higher one solved my problem.
I too have experienced with the similar issue while using JAXB, i.e
Implementation of JAXB-API has not been found
which occurs randomly and it was harder to reproduce. Fortunately I had found a system environment where the above error is continuous, while other environments it worked smoothly.
Observation
With the extensive research into this issue, I found a classloader issue that causes this problem. Further I noticed,
JAXB implementation is visible to ParallelWebappClassLoader, a classloader present in Tomcat server
Sometimes it is not visible to jdk internal classloaders like AppClassLoader,(Even though it was visible for many cases)
Solution
JAXBContext object is thread-safe (while marshaller/unmarshaller is not) and can be re-used once initiated. Therefore,
I found a thread that works with ParallelWebappClassLoader (i.e that given thread's context class loader is ParallelWebappClassLoader) and created JAXBContext there and stored in a map for later usage
Retrieved the stored JAXBContext whenever necessary (other threads that uses different class loaders) and carried out marshall/unmarshall tasks. That saved the day for me :)

java.lang.NoClassDefFoundError for class belonging to user-defined jar in JBOSS 7 EAP

02:35:43,076 WARN [org.jboss.modules] (default task-8) Failed to define class com.karthik.db.jpub.mapping.ObjUser in Module "deployment.CVRepo.war:main" from Service M
odule Loader: java.lang.NoClassDefFoundError: Failed to link com/karthik/db/jpub/mapping/ObjUser (Module "deployment.CVRepo.war:main" from Service Module Loader): oracle/sql/ORAData
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:446)
at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:274)
at org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:78)
at org.jboss.modules.Module.loadModuleClass(Module.java:605)
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)
Here, ObjUser class belongs to Data.jar. Data.jar exists in WEB-INF/lib folder of CVRepo.war
1) What is causing this error even though the jar - data.jar that contains the class - ObjUser.class is packaged in CVRepo.war. 2) Should external jars(data.jar) be removed from WEB-INF/lib folder of WAR and be added as module and be referenced in jboss-deployment.xml of WAR in JBOSS 7?
NoClassDefFoundError typically are thrown because the class is not in the classpath, which could be because of the packaging of the application or the classloader isolation settings specified. Look at the Tattletale Report: Class Location to locate where it is packaged and compare to the isolation settings & Java EE classpath defined for the particular deployment type.
Note: if the class does not exist in the application and the java source file does not list the class, decompile the class using javap or other decompiler and see if the class definition matches the source. Some IDEs can generate invalid classes when the classpath is missing classes, they could generate a class with invalid class references and if those get deployed it will cause unusual ClassNotFoundExceptions such as a class name with no package.
NoClassDefFoundError is thrown when the JVM tries to load a definition of a class and no definition can be found. NoClassDefFoundError is caused by typically a ClassNotFoundException or a ExceptionInInitializerError. After the initial ClassNotFoundException / ExceptionInInitializerError, the JVM will just throw a NoClassDefFoundError and will not show the original cause.
Review the full server.log and locate the first classloading exception
Refer the link basic Class Loading stuffs:
https://docs.jboss.org/author/display/AS71/Class+Loading+in+AS7

WebLogic EAR deployment sometimes fails on Guava java.lang.LinkageError: loader constraint violation

I have an EAR application containing 3 ejbModules and 4 webModules, which is redeployed during development quite often (multiple times per day) on WebLogic 12.2.1.1 (Java EE 7).
Google Guava 18.0 is used in various components within these applications.
In the 4 weblogic.xml's and 1 weblogic-application.xml I've marked the Guava packages as provided by my application instead of the version supplied by WebLogic:
<prefer-application-packages>
<package-name>com.google.common.*</package-name>
</prefer-application-packages>
During some deployments using WLST the deployment fails with this exception:
[ServerConnectionImpl.upload():862] : Uploaded app to D:\Domains\NAMED_SERVER\.\servers\AdminServer\upload\app-ear
[BasicOperation.execute():472] : Initiating deploy operation for app, app-ear, on targets:
[BasicOperation.execute():474] : PEARL_WL1
Task 62 initiated: [Deployer:149026]deploy application app-ear on NAMED_SERVER.
dumping Exception stack
Task 62 failed: [Deployer:149026]deploy application app-ear on NAMED_SERVER.
Target state: deploy failed on Server PEARL_WL1
java.lang.LinkageError: loader constraint violation: loader (instance of weblogic/utils/classloaders/ChangeAwareClassLoader) previously initiated loading for a different type with name "com/google/common/base/Supplier"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at weblogic.utils.classloaders.GenericClassLoader.defineClassInternal(GenericClassLoader.java:1109)
at weblogic.utils.classloaders.GenericClassLoader.defineClass(GenericClassLoader.java:1042)
at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:1034)
at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:986)
at weblogic.utils.classloaders.ChangeAwareClassLoader.findClass(ChangeAwareClassLoader.java:83)
at weblogic.utils.classloaders.GenericClassLoader.doFindClass(GenericClassLoader.java:607)
at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:539)
at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:492)
at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:469)
at weblogic.utils.classloaders.ChangeAwareClassLoader.loadClass(ChangeAwareClassLoader.java:53)
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at weblogic.ejb.container.injection.EjbComponentContributor.getCtrlIntfMethods(EjbComponentContributor.java:147)
at weblogic.ejb.container.injection.EjbComponentContributor.buildInterceptionMetadata(EjbComponentContributor.java:248)
at weblogic.ejb.container.injection.EjbComponentContributor.contribute(EjbComponentContributor.java:187)
at weblogic.ejb.container.injection.InjectionBasedEjbComponentContributor.contribute(InjectionBasedEjbComponentContributor.java:96)
at weblogic.j2ee.injection.J2eeComponentContributor.contribute(J2eeComponentContributor.java:48)
at weblogic.ejb.container.injection.EjbComponentContributor.contribute(EjbComponentContributor.java:94)
at weblogic.ejb.container.injection.InjectionBasedEjbComponentContributor.contribute(InjectionBasedEjbComponentContributor.java:130)
at com.oracle.pitchfork.server.Bootstrap.deploy(Bootstrap.java:140)
at com.oracle.pitchfork.spi.WLSBootstrap.deploy(WLSBootstrap.java:106)
at com.oracle.pitchfork.server.Bootstrap.deploy(Bootstrap.java:104)
at com.oracle.pitchfork.spi.BaseComponentBrokerImpl.initialize(BaseComponentBrokerImpl.java:48)
at com.oracle.pitchfork.spi.EjbComponentCreatorBrokerImpl.initialize(EjbComponentCreatorBrokerImpl.java:44)
at weblogic.ejb.container.injection.EjbComponentCreatorImpl.initialize(EjbComponentCreatorImpl.java:44)
at weblogic.ejb.container.injection.InjectionBasedEjbComponentCreator.initialize(InjectionBasedEjbComponentCreator.java:54)
at weblogic.ejb.container.deployer.EJBDeployer.initializeComponentCreator(EJBDeployer.java:539)
at weblogic.ejb.container.deployer.EJBDeployer.activate(EJBDeployer.java:753)
It seems that there is a Google Guava conflict after all, possible loaded twice.
I've verified that my EAR only contains 1 guava.jar, in /lib.
Any ideas how to test/debug what exactly goes wrong sometimes?
[Addition]
What seems to go wrong is that one of my ejbModules uses Guava (only com.google.common.base.Supplier)
I'm using Java 8, so rewriting to java.util.function.Supplier effectively removed the need for Guava on this ejbModule and fixed the deployment problem.
The question remains is WHY this problem occurred.
I did specify in weblogic-application.xml to use the Guava.jar inside the EAR.
Any ideas why I can't override Guava correctly?

Vaadin/OSGi : ScssStylesheet class not found

I use vaadin and OSGi to create a modular application. After a long fight, I was able to deploy successfully the application. However, I can't load the style. When I try to access to
http://localhost:8080/myapp/VAADIN/themes/myTheme/styles.css
I got the following exception:
exception
javax.servlet.ServletException: Servlet execution threw an exception
root cause
java.lang.NoClassDefFoundError: com/vaadin/sass/internal/ScssStylesheet
com.vaadin.server.VaadinServlet.serveOnTheFlyCompiledScss(VaadinServlet.java:957)
com.vaadin.server.VaadinServlet.serveStaticResourcesInVAADIN(VaadinServlet.java:790)
com.vaadin.server.VaadinServlet.serveStaticResources(VaadinServlet.java:760)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:257)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:201)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
java.lang.ClassNotFoundException: com.vaadin.sass.internal.ScssStylesheet
org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
java.lang.ClassLoader.loadClass(ClassLoader.java:356)
com.vaadin.server.VaadinServlet.serveOnTheFlyCompiledScss(VaadinServlet.java:957)
com.vaadin.server.VaadinServlet.serveStaticResourcesInVAADIN(VaadinServlet.java:790)
com.vaadin.server.VaadinServlet.serveStaticResources(VaadinServlet.java:760)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:257)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:201)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)[/code]
com.vaadin.sass.internal.ScssStylesheet class is offered by vaadin-theme-compiler-7.x.x.jar but the server doesn't import this package. Then, I "hacked" the vaadin server bundle by adding DynamicImport-Package: * in vaadin server's MANIFEST. The previous exception does not appear but I got the same for org.w3c.css.sac.CSSException.
Note that by deploying the application .war file on tomcat, I had no error and the app looks like I expected (because all libraries are added under WEB-INF/lib and tomcat add them on the class loader). So, the problem is pure OSGi.
based on the Vaadin 7.1.3 bundles, the following changes need to be made:
import com.vaadin.theme-compiler in com.vaadin.server
import org.w3c.css.sac in com.vaadin.shared.deps and com.vaadin.theme-compiler
provide a ScssStylesheetResolver via ScssStylesheet.setStylesheetResolvers which loads from bundle resources, not (only) filesystem / classloader as the default implementation.
if you import parts of the original themes in your theme, consider creating it as a fragment to com.vaadin.themes, which in turn can then be used as a base for the ScssStylesheetResolver
This sounds like a packaging bug in Vaadin which should be reported to the authors. If the core Vaadin bundle needs to access classes from the package com.vaadin.sass.internal then it should include that in its Import-Package header.
With respect to org.w3c.css.sac, you don't specify which bundle throws an error but it sounds like the same kind of problem. Whichever bundle uses that package should import it via Import-Package.

NoClassDefFoundError in spring

I wrote a Spring application which runs on Weblogic 10.3. In this application I have some JMS Queue consumers.
Sometimes I got an error when the application is closing or opening (I saw this error in both situation) saying:
java.lang.NoClassDefFoundError: org/springframework/jms/connection/SmartConnectionFactory
at org.springframework.jms.connection.ConnectionFactoryUtils.releaseConnection(ConnectionFactoryUtils.java:72)
at org.springframework.jms.listener.AbstractJmsListeningContainer.refreshSharedConnection(AbstractJmsListeningContainer.java:385)at org.springframework.jms.listener.DefaultMessageListenerContainer.refreshConnectionUntilSuccessful(DefaultMessageListenerContainer.java:779)
at org.springframework.jms.listener.DefaultMessageListenerContainer.recoverAfterListenerSetupFailure(DefaultMessageListenerContainer.java:761)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:892)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.ClassNotFoundException: org.springframework.jms.connection.SmartConnectionFactory
at weblogic.utils.classloaders.GenericClassLoader.findLocalClass(GenericClassLoader.java:283)
at weblogic.utils.classloaders.GenericClassLoader.findClass(GenericClassLoader.java:256)
at weblogic.utils.classloaders.ChangeAwareClassLoader.findClass(ChangeAwareClassLoader.java:54)
at java.lang.ClassLoader.loadClass(ClassLoader.java:303)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:176)
at weblogic.utils.classloaders.ChangeAwareClassLoader.loadClass(ChangeAwareClassLoader.java:35)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
... 6 more
Why do I get this error and what should I do to solve it?
The version of the spring.jar is 2.5.5
That Exception means that the class is not getting loaded into the JVM. Make sure that the spring.jar is in the Weblogic server's classpath or library folder.
It's all very well that you have this class in your war, but in Weblogic, the war has its own classloader. Since your stack trace shows a JMS listener, I'd ask: where is the listener? If it's in the war, then you have a mystery. But it sure looks as though it's somewhere else, and it's that somewhere else that would be missing this Spring class.

Categories

Resources