I'm currently "rearranging" my Java EE application, which consists of three components:
Both MyAppServer and MyAppWeb use the classes defined in MyAppInterface; MyAppServer "exports" some of its EJBs via local interfaces in MyAppInterface. MyAppInterface is kind of the API, it's what you need to work with MyAppServer.
In Maven I am packaging MyAppInterface as jar, both MyAppServer and MyAppWeb are packaged as war with a dependency on MyAppInterface in a compile scope. So MyAppInterface.jar ends up in both war-files.
When I deploy both war-files as separate applications on the same Glassfish, deployment is successful. The JAXB-Jersey-powered communication between them works, so I have to assume that both applications can classload MyAppInterface.
But in one case, I'd like to access a MyAppServer-EJB from MyAppWeb. The JNDI-lookup via InitialContext works, but when I try to cast the obtained proxy to the local interface, I get a ClassCast exception:
com.sun.enterprise.container.common.spi.util.InjectionException: Error creating managed object for class: class com.skalio.bonusapp.web.server.StoreServiceImpl
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:315)
at com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:717)
at com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:1959)
...
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:307)
... 28 more
Caused by: java.lang.ClassCastException: $Proxy365 cannot be cast to com.skalio.bonusapp.beans.SettingsBeanLocal
at com.skalio.bonusapp.web.server.StoreServiceImpl.getServerSettings(StoreServiceImpl.java:85)
at com.skalio.bonusapp.web.server.StoreServiceImpl.(StoreServiceImpl.java:47)
... 33 more
Google makes me believe that this could be a classloading issue, possibly related to the the duplicate inclusion of MyAppInterface.jar. Is that correct? What do you suggest to do?
How would you distribute and package the components?
Note: At the moment I'd like to avoid creating an EAR and rather keep flexibility of choosing what components to deploy where...
Yes, for local EJB, the interface JAR needs to be in a shared location for class loading. The EJB spec actually doesn't require local EJBs to be accessible across applications (or standalone modules), but most application servers implement local EJB with simple proxies.
You either need to package your modules in an EAR with the JAR in the lib directory, or you need to arrange for the JAR to be loaded by a product-wide class loader that is visible to both applications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With