1
votes

We have three Karaf features each containing three custom bundles (api, impl, web). The 'impl' bundle of each feature also contains the entities used by that feature. We deploy these features in Karaf 3.0.1 and use OpenJPA 2.3.0 that comes with Karaf 3.0.1 as our persistence provider.

We use dynamic run-time enhancement for the entities in the three features. For the two features, the entities are always enhanced at deployment time and they work fine. The problem is that for the third feature, Karaf and OpenJPA occasionally miss to enhance a subset of the entities resulting in the following exception:

<openjpa-2.3.0-r422266:1540826 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a javaagent: "
<list-of-missed-unenhanced-classes>"
at org.apache.openjpa.enhance.ManagedClassSubclasser.prepareUnenhancedClasses(ManagedClassSubclasser.java:115)
at org.apache.openjpa.kernel.AbstractBrokerFactory.loadPersistentTypes(AbstractBrokerFactory.java:312)
at org.apache.openjpa.kernel.AbstractBrokerFactory.initializeBroker(AbstractBrokerFactory.java:236)
at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:212)
at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:155)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:226)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:59)
...

We are aware of the openjpa.RuntimeUnenhancedClasses option but would not like to use it since it has known limitations and has been disabled by default in OpenJPA 2.0.0.

We are aware of compile-time enhancement and we are using it successfully but we have reasons to try to enable run-time enhancement.

Our current understanding is that on EntityManagerFactory creation time, OpenJPA registers with Aries JPA, through a PersistenceUnitInfo callback, a ClassTransformer to be used by Karaf. This ClassTransformer is indeed used for all entities of the first two features but only for a subset of the entities for the third feature.

Investigating further we tried to log the time when the ClassTransformer is registered and the time when each entity class is loaded. We noticed a difference between the two succeeding and the failing bundle which may or may not be relevant. For the succeeding bundles, the Aries JPA features attempts to load each of the entity classes just before the ClassTransformer registration, while for the failing module there is no such attempt.

1
I regard doing run-time enhancement to be a bad design. It might be OK during development phase but surely not for production. You should go for compile-time enhancement with the openjpa maven plugin. - Achim Nierbeck
@AchimNierbeck We have a requirement of deploying the aforementioned features both in environments using OpenJPA and in environments using Hibernate, this is the reason for trying run-time enhancement with OpenJPA. Is there a best practice for this case other than providing separate bundles for each environment ? - gsapountzis
The only other way would be to add the enhanced classes to a fragment bundle that extends the host bundle containing the DAO classes. This way you could have two different fragment bundles for Hibernate and OpenJPA environments. - Achim Nierbeck

1 Answers

0
votes

This is a actually a problem between Karaf and OpenJPA.

The problem is that classloading in Karaf is multi-threaded while the OpenJPA class enhancer is not thread-safe. So you basically have multiple classloading threads calling into a single non-thread-safe instance of the OpenJPA class enhancer.

See https://issues.apache.org/jira/browse/OPENJPA-2222