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

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.

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

Related

Why is load time weaving using aspectjweaver javaagent so slow for me?

The project I'm working on is considerably large. While trying to get load time weaving working for this spring project, I was instructed to use both the spring-instrument javaagent as well as the aspectjweaver javaagent. However, I notice that when using the aspectjweaver agent, my launch time shoots up 4-6 fold. I can also see identical weave messages 4-6 times coming from ContextOverridingClassLoader.
If I remove aspectjweaver however, and only use spring-instrument, I notice my launch time decrease dramatically with only a single weave message per join point coming from AppClassLoader.
The only issue being that some specific classes are not woven (I found that this is due to the spring application context not yet being loaded before the faulty classes are loaded by the class loader, as spring is the mechanism that enables the weaving). I've found a solution of my own by creating a custom javaagent which enables weaving in the same manner that spring-instrument does, only it does so in the premain rather than on application context load. It now weaves all the classes and in reasonable time.
However, I'd prefer not to go down this hacky road as I can only presume that the two agents were designed the way it is for a reason.
I wonder if anyone else has seen a similar issue with the aspectjweaver javaagent and if someone might know why that agent is so slow compared to just using spring-instrument.
If the answer interests anyone, I've figured out the issue.
Spring uses a temporary classloader ContextOverridingClassLoader to get metadata about the bean classes prior to actually loading them into the context.
The spring-instrument javaagent (or more accurately, the spring framework code which may or may not use the spring-instrument javaagent) specifically only weaves classes loaded by the classloader used to load the application context.
Code inside of InstrumentationLoadTimeWeaver$FilteringClassFileTransformer:
if (!this.targetClassLoader.equals(loader)) {
return null;
}
return this.targetTransformer.transform(
loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
On the other hand, aspectjweaver does not have such a filtering mechanism and so will weave even those classes loaded by spring's temporary ContextOverridingClassLoader. Fortunately, aspectjweaver has an essentially undocumented system property (or at least I was unable to find any documentation on this) called aj.weaving.loadersToSkip. By setting this to:
-Daj.weaving.loadersToSkip=org.springframework.context.support.ContextTypeMatchClassLoader$ContextOverridingClassLoader
I was able to skip weaving for that classloader and speed up the loading of my application context tremendously.
Incidentally, I've found that both the spring-instrument and aspectjweaver ultimately both use ClassPreProcessorAgentAdapter to weave the classes, and thus it is probably not necessary to use both agents (aspectjweaver will weave a superset of the classes that spring-instrument will). However, depending on your configuration, the application might complain about the missing agent at startup so you might as well include it (at the cost of some additional unnecessary overhead).

Using SpringBoot as an application loader

I have a spring-boot app that acts as a small framework for other apps. It provides a couple of JMS queues and a DAO layer to retrieve and store data from a common set of data stores. The problem is that the original developer of this framework app is scanning all the package "com.mycompany" (rather than com.mycompany.framework) so that it can load the beans of the specific app that may be declared under com.mycompany.myapp1 or com.mycompany.myapp2 an which JARs are bundled together with the JARs of the framework.
We only load a single app in the JVM (app1 or app2), but these apps may share other libraries and sometimes we end up with beans in the context that we don't need. (these may be needed in app1 but not in app2)
So, what would be your advice ?
My problem is similar to what was described here:
https://github.com/spring-projects/spring-boot/issues/3300
I am debating if each app should be aware of the framework and load it. Or if the framework should instantiate a class loader and create a new Spring context loading the app specific code as suggested in the link above.
Perhaps you should consider leveraging some of Spring Boot's Auto Configuration capabilities such as #ConditionalOnProperty or #ConditionalOnClass in your framework. That way, you can only actually enable certain beans if and when the application using your framework takes some specific action (e.g. has a given jar on the classpath, or sets a configuration value). For reference check out: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-developing-auto-configuration

Can I use Websphere with Spring 3.1 and Ehcache?

I need to implement Ehcache in a project that uses Spring version 3.1 and Websphere. I tried to google something about this topic but I could'nt find anything. Have you guys ever used those three tools together? Thanks in advance.
As per EhCache docs,It will NOT detect Websphere Transaction Manager automatically,.
Automatically Detected Transaction Managers
Ehcache automatically detects and uses the following transaction
managers in the following order:
GenericJNDI (e.g. Glassfish, JBoss, JTOM and any others that register
themselves in JNDI at the standard location of
java:/TransactionManager
Weblogic (since 2.4.0)
Bitronix
Atomikos
No configuration is required; they work out of the box. The first found
is used.
And you can configure it as below.
If your Transaction Manager is not in the above list or you wish to
change the priority, provide your own lookup class based on an
implementation of net.sf.ehcache.transaction.manager.TransactionManagerLookup and
specify it in place of the DefaultTransactionManagerLookup in
ehcache.xml:
<transactionManagerLookup
class= "com.mycompany.transaction.manager.MyTransactionManagerLookupClass"
properties="" propertySeparator=":"/>
And to integrate & Use Spring with EhCache, refer this link
From Spring docs,
36.3 Declarative annotation-based caching For caching declaration, the abstraction provides a set of Java annotations:
#Cacheable triggers cache population #CacheEvict triggers cache eviction
#CachePut updates the cache without interfering with the method execution
#Caching regroups multiple cache operations to be applied on a
method
#CacheConfig shares some common cache-related settings at class-level

Is it possible to integrate OSGi with Spring Data?

I'm currently working on an OSGi application running under apache Karaf that uses JPA and QueryDSL.
I was wondering if I could use Spring Data with QueryDSL instead of the current approach.
The reason for this is that I find Spring repositories to be quite useful and having a template for NoSQL database accesses might be useful in the future.
I have tried to start a normal spring application without a web context with OSGi but I get a ClassNoutFoundException when it tries to load the applicationContext.xml or the ApplicationContext.class.
I don't want to use Spring DM since it is discontinued.
Basically the sole reason for wanting to try this integration is for the Spring Repositories, but if you think this is not necessary please tell me. Any information regarding how to achive this or if it's ok to persue this would be more than welcome.
Thank you
Update
I've managed to make spring work by starting the application context with org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext. The applicationContext is exported in OSGi as a service and I can get all the beans that I need by calling it.
The problem I'm having right now is that when I declare <jpa:repositories base-package="x.y.z" /> I get the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0' defined in URL [bundle://251.13:0/META-INF/spring/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1109)[187:org.springframework.context:3.1.4.RELEASE]
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.registerBeanPostProcessors(AbstractDelegatedExecutionApplicationContext.java:502)[193:org.eclipse.gemini.blueprint.core:1.0.0.RELEASE]
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.registerBeanPostProcessors(AbstractDelegatedExecutionApplicationContext.java:451)[193:org.eclipse.gemini.blueprint.core:1.0.0.RELEASE]
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:306)[193:org.eclipse.gemini.blueprint.core:1.0.0.RELEASE]
at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)[193:org.eclipse.gemini.blueprint.core:1.0.0.RELEASE]
at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:290)[193:org.eclipse.gemini.blueprint.core:1.0.0.RELEASE]
at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:137)[194:org.eclipse.gemini.blueprint.extender:1.0.0.RELEASE]
at java.lang.Thread.run(Thread.java:662)[:1.6.0_37]
Caused by: java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:142)[195:org.springframework.transaction:3.1.4.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79)[195:org.springframework.transaction:3.1.4.RELEASE]
at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:70)[195:org.springframework.transaction:3.1.4.RELEASE]
at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:103)[195:org.springframework.transaction:3.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1475)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1443)[185:org.springframework.beans:3.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)[185:org.springframework.beans:3.1.4.RELEASE]
As a JPA provider I'm using OpenJPA. The entityManagerFactory is a service which I can get by using the blueprint. I think I need to reference it in <jpa:repositories base-package="x.y.z" />, but how do I do that since the applicationContext.xml is read by spring and not the blueprint?
I would really appreciate any hint in the right direction.
Thank you
Use Querydsl-SQL directly in your code and
it will work well within OSGi as it does not use class loading, weaving, enhancing, caching and other tricks that sound really good but causes chaos
your code will run much faster than with any of the "cache-enhanced" JPA engines
others will be able to understand your code (not like JPA Criteria API queries)
you will know exactly what SQL commands run on the Database Server that minimizes problem-solving time
your code will be as database independent as with any ORM tool
Do not use Spring, spring-data, JPA and other monoholitic technologies together with OSGi as
they were designed to work within monoholitic systems where everything is in one application context, not in separate bundles
by using these technologies together with OSGi you will spend most of your time to fix bugs like this and looking for workarounds
People who argue with this, already spent lots of time on finding such workarounds. They managed to implement some business logic. They hope that they now truly found workarounds for every conceptual issue and they do not have to spend the same amount of work next time. They are in a bidding fee auction. Be honest guys! Somewhere deep you know I am right ;-).
I am saying this with the experience that I
tried the perfect stack based on Hibernate and Don't repeat the DAO article of IBM (much before Spring-Data hype began). Twice
wrote hibernate-osgi-adapter for Hibernate 4.1.x
Re-implemented the complete JPA chapter of OSGi Enterprise specification
Well you have a couple of choices here, try to get it to run with blueprint (probably the hardest - since you need to call spring beans, but I think could still be done), use Karaf 3.0.0.RC1 it also supports Blueprint Geminin which does have a tighter support for Spring and last but not least use Spring-DM, even if it is discontinued you are able to use and probable the best approach is to use spring-dm for certain Spring specific parts and std. Blueprint for the rest. Because you just use services through both frameworks everything will work, just don't mix the spring and blueprint descriptors in one bundle.

Which Spring Entity Manager Factory should I use?

There are two entity manager factory beans in Spring that would work for my application. The org.springframework.orm.jpa.LocalEntityManagerFactoryBean and org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean. I am using Spring 3.0 with EclipseLink JPA 2.2.
What I've read about these two are that they are the same. Except that LocalContainerEntityManagerFactoryBean uses weaving. What is it? And, why would I want to use it?
"Weaving" is a term for program transformation, usually heard around "aspect oriented programming" area. The transformation is usually not done to the source but the .class (the bytecode) and a techy term for changing bytecode is "bytecode instrumentation".
why would I want to use it?
The JPA implementation you use may rely on such bytecode instrumentation for some features it provides and hence you might be forced into using it.
And for weaving to work correctly, you might need to specify a -javaagent: For eg,see section 'Eclipse Junit' here.
It looks like LocalContainerEntityManagerFactoryBean allows you to configure a weaver implementation ( one of DefaultContextLoadTimeWeaver, GlassFishLoadTimeWeaver, InstrumentationLoadTimeWeaver, OC4JLoadTimeWeaver, ReflectiveLoadTimeWeaver, SimpleLoadTimeWeaver, WebLogicLoadTimeWeaver
at an XML file, instead of relying on a -javaagent runtime argument.
This configuration isn't such a big factor, I'd guess.
Other features which the docs explain, sound like deciding factors.
LocalEntityManagerFactoryBean bootstrap is appropriate for standalone applications which solely use JPA for data access. If you want to set up your persistence provider for an external DataSource and/or for global transactions which span multiple resources, you will need to either deploy it into a full Java EE 5 application server and access the deployed EntityManagerFactory via JNDI, or use Spring's LocalContainerEntityManagerFactoryBean with appropriate configuration for local setup according to JPA's container contract.
If you plan on deploying your application to an Application Server and letting the Application Server manage the Entity Manager Factory and Transactions than the LocalContainerEntityManagerFactoryBean might be a better option. If you rather have the Application be more isolated, than the LocalEntityManagerFactoryBean would be more appropriate.
This blog can help provide more insight: http://second-kind-demon.blogspot.com/2011/06/spring-jpa-java-ee-jboss-deployment.html

Resources