OSGi using jpa persistence unit from another bundl

2019-09-08 18:43发布

问题:

I use ServiceMix with Apache Felix and my Enterprise Application consist of several bundles. For example I have a bundle with my jpa entity classes and another bundle with business logic and dao-classes. Because of I use OpenJPA the entity-bundle project needs the persistenc.xml in META-INF folder for bytecode injection at compiletime, but this bundle provides the persistence unit by the Meta-Persistence header in the bundle manifest. Inside of the dao providing bundle I inject the entity manager by using blueprint.xml:

<bean id="systemUserDAOBean" class="server.daos.SystemUserDAO">
  <tx:transaction method="*" value="Required" /> 
  <jpa:context property="entityManager" unitname="mypu" />
</bean>

if I call at runtime the following method of a dao:

public SystemUser readSystemUser(String username) {
        final EntityManager em = getEntityManager();
        final Query q = em.createQuery("select a from SystemUser a where a.username = '"+username+"'");
        return (SystemUser) q.getSingleResult();
}

a ClassCastException will be thrown:

java.lang.ClassCastException: mypackage.SystemUser cannot be cast to mypackage.SystemUser

What I found out until now is, that the class loader which loaded the class of the entitymanager returning object is different to the classloader which loaded the returning type of the method. Maybe the first classloader is the classloader of the entity bundle and the second the classloader of the dao providing bundle?!

If I copy the persistence.xml into the DAO-Bundle and use its persistence unit in the blueprint.xml the ClassCastException will not be thrown. But in this case I have two identically persistence.xml-files inside of the same application, what I dont want. :(

does anyone have an idea how to solve that issue?

thank you, Phill

EDIT: When I restart servicemix the exception is gone until I update the persistence bundle. And I found out, that both classloader come from the persistence bundle.

回答1:

It sounds like you have copied the domain classes (including, I assume, SystemUser) into multiple bundles. You should not to this because, as you have discovered, Java considers the same class loaded by different ClassLoaders to be different classes, and hence you get the ClassCastException.

You should export the domain package from one bundle, using the Export-Package header. Probably this should be done from your persistence bundle. All other bundles should import that package.