Javaassist and Webstart
-
27-10-2019 - |
Question
This looks like an old problem that is resolved, but unfortunately I couldn't find a good reference. I have a Java application using Javaassist. It was working fine until I upgraded it to a webstart application. Now Javaassist gives me a classNotFoundException. The class is definitely in class path though.
I found this related post https://community.jboss.org/message/302408 which is kind of old and I couldn't decode it. Can someone gime me a hand here?
thanks
Here is the code snippet:
ctClasses = new HashMap<String, CtClass>();
classPool = ClassPool.getDefault();
try {
ctEntity = classPool.get("org.myclass");
} catch (NotFoundException e) {
logger.error("Could not find entity class, this should not happen");
throw new RuntimeException("Could not find Entity class",e);
}
There is nothing in stacktrace.
java.lang.RuntimeException: Could not find Entity class
at ca.cbc.panacea.metadata.JavassistClassGeneratorImpl.<init>(JavassistClassGeneratorImpl.java:32)
at ca.cbc.panacea.metadata.ClassGeneratorFactory.getDefaultClassGenerator(ClassGeneratorFactory.java:12)
at ca.cbc.panacea.metadata.ClassCreator.<init>(ClassCreator.java:30)
at ca.cbc.panacea.Panacea.digestMappingFile(Panacea.java:75)
at ca.cbc.panacea.console.PanaceaConsole.validateMappingFile(PanaceaConsole.java:46)
at ca.cbc.panacea.console.PanaceaConsoleUI.actionPerformed(PanaceaConsoleUI.java:132)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6373)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6138)
at java.awt.Container.processEvent(Container.java:2085)
at java.awt.Component.dispatchEventImpl(Component.java:4735)
at java.awt.Container.dispatchEventImpl(Container.java:2143)
at java.awt.Component.dispatchEvent(Component.java:4565)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4621)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4282)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4212)
at java.awt.Container.dispatchEventImpl(Container.java:2129)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4565)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:679)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:638)
at java.awt.EventQueue$1.run(EventQueue.java:636)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
at java.awt.EventQueue$2.run(EventQueue.java:652)
at java.awt.EventQueue$2.run(EventQueue.java:650)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:649)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Caused by: javassist.NotFoundException: ca.cbc.panacea.metadata.Entity
at javassist.ClassPool.get(ClassPool.java:436)
at ca.cbc.panacea.metadata.JavassistClassGeneratorImpl.<init> (JavassistClassGeneratorImpl.java:29)
The problem is actually the ClassLoader. JNLP uses a different classloader than java command line. The question is how to reconcile JNLP class loader with Javassist.
Solution
The key is setting up the ClassPool
to see the class loader of your application's classes. This can be done by adding a classpath to the ClassPool:
ctClasses = new HashMap<String, CtClass>();
classPool = ClassPool.getDefault();
//Add the classloader of your application's classes so Javassist can find them
ClassLoader loader = org.MyClass.class.getClassLoader();
pool.appendClassPath(new LoaderClassPath(loader));
try {
ctEntity = classPool.get("org.MyClass");
} catch (NotFoundException e) {
logger.error("Could not find entity class, this should not happen");
throw new RuntimeException("Could not find Entity class",e);
}
You need to do customize the classpath of the class pool for any application that does not load its classes from the system classloader, such as web-start applications, Eclipse plugins and applications that run under a Java EE container.
More details under the class search path section of the Javassist tutorial.