I'm currently "rearranging" my Java EE application, which consists of three components:
- MyAppInterface: mostly JPA- and JAXB-annotated POJOs, also some EJB Local Interfaces
- MyAppServer: JPA Facades, EJBs, Jersey resources
- MyAppWeb: GWT frontend, communicates with MyAppServer via HTTP/REST via loadbalancer
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...