gsapountzis
gsapountzis

Reputation: 11

Unenhanced entities with dynamic runtime enhancement with OpenJPA in OSGI (Karaf)

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.

Upvotes: 1

Views: 854

Answers (1)

gsapountzis
gsapountzis

Reputation: 11

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

Upvotes: 0

Related Questions