You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Harald Wellmann <Ha...@gmx.de> on 2011/07/06 15:25:14 UTC
Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
I'm trying to use OpenJPA 2.1.0 with Spring 3.0.5 and Tomcat 6.0.32 and a JPA 2.0 persistence unit configured by annotations.
At first, the enhancer did not recognize any of my classes, which looks like the same problem as described in https://issues.apache.org/jira/browse/OPENJPA-1891.
Then I moved the Geronimo JPA JAR from my WAR to Tomcat's lib folder as described in this issue (but this feels wrong somehow).
After that, the enhancer starts to do some work but then fails with an exception which I don't really understand.
It may be related to an inheritance chain in my entity model
A -> B -> C
where A is an Entity and B and C are MappedSuperclasses.
Some trace output
8796 foo TRACE [main] openjpa.Enhance - Enhancing type "class com.A" loaded by WebappClassLoader
context: /foo-web
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@a210b5b
.
8808 foo TRACE [main] openjpa.Enhance - Enhancement for "com/A" completed. Class size: [669/3.516]
8809 foo TRACE [main] openjpa.Enhance - "com/B" requires runtime enhancement: true
209144 foo TRACE [main] openjpa.Enhance - Enhancing type "class com/B" loaded by WebappClassLoader
context: /foo-web
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@a210b5b
.
209170 foo TRACE [main] openjpa.Enhance - Enhancement for "com/B" completed. Class size: [1.204/5.336]
209008 foo WARN [main] openjpa.MetaData - The class "com.A" listed in the openjpa.MetaDataFactory configuration property could not be loaded by org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader
WebappClassLoader
context: /foo-web
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@a210b5b
; ignoring.
209008 foo TRACE [main] openjpa.MetaData - java.lang.NoSuchMethodError: com.C.pcGetManagedFieldCount()I
java.lang.NoSuchMethodError: com.C.pcGetManagedFieldCount()I
at com.B.<clinit>(B.java)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.apache.openjpa.meta.MetaDataRepository.classForName(MetaDataRepository.java:1552)
at org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypesInternal(MetaDataRepository.java:1528)
at org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypes(MetaDataRepository.java:1506)
at org.apache.openjpa.kernel.AbstractBrokerFactory.loadPersistentTypes(AbstractBrokerFactory.java:283)
at org.apache.openjpa.kernel.AbstractBrokerFactory.initializeBroker(AbstractBrokerFactory.java:239)
at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:213)
at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:154)
at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:423)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:485)
at $Proxy12.createEntityManager(Unknown Source)
The missing method appears to be one added by the enhancer, but com.C has not been enhanced yet.
I was able to deploy the same unenhanced persistence unit on Glassfish without problems, so there must be a problem on the interface between OpenJPA, Spring and Tomcat.
Any ideas anyone...?
Thanks,
Harald
--
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de
Re: Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
Posted by Pinaki Poddar <pp...@apache.org>.
Thank you Harald, for adding some real good perspectives.
> enhancement is a major nuisance in OpenJPA.
It is, by user-(un)friendliness. It is not, by the value it adds to runtime.
That enhancement is not user-friendly is our fault to get the ergonomics
right. The internal process that really enhances the bytecodes is pretty
solid.
> I'm spending valuable time explaining to my team why this is needed,
You may have known/told these but let me reiterate few strengths of
build-time enhancement.
Firstly, enhancement adds real value to runtime. Even if there are
niggles/wrinkles or outright pain in enhancing, once that pain is gone, when
the code finally runs in a production box -- the application runs faster.
a) performance -- there is no proxying, no virtual point arithmetic, no
extra overhead on the application objects -- which could be accessed
trillion times in a process lifetime
b) memory footprint -- no double copy of data
c) if remote client can afford/allow OpenJPA runtime, a better merge()
operation
> Why should users have to learn about extra build steps when they could do
> without?
Given everything a persistent object goes through in its life, to mange it
with transaction warranty and that too transparently from the user
application -- a managed agent *must* be present -- it could be subclassing,
it could be proxying, it could be source code generation, it could be
bytecode enhancement.
Bytecode enhancement is the most powerful and most performant. The other
vendors who had taken strong position in the past against byte-code
enhancement, had later used the same technique in one way or other.
So the question to ask is:
are we OK with suffering a development hiccup to build a better
application?
My experience tells me that a little effort to integrate build-time
enhancement in this age of massive automatic build environments goes a long
way.
> The most manifest problem with build-time enhancment is that it makes
> your entity JAR depend on OpenJPA. This is a no-go when you use (parts
> of) your entity model with different JPA providers.
This could be a hairy problem, but often solvable via configuration. Tell us
more about the scope and isolation via classloaders and the domain itself
via persistent units, then we can have a more concrete discussion.
Thank you again for bringing some real good points.
-----
Pinaki Poddar
Chair, Apache OpenJPA Project
--
View this message in context: http://openjpa.208410.n2.nabble.com/Problems-with-load-time-enhancement-and-Spring-s-TomcatInstrumentableClassLoader-tp6554347p6588167.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
Posted by Andrew Thompson <at...@columbia.edu>.
One minor factual quibble with the below. Hibernate does require build
time enhancement in some situations.
For example, if you have an entity with a Blob as a field, you have to
use their javaassist based byte code enhancement to allow that Blob to
be lazily loaded.
On Fri, 2011-07-15 at 19:32 +0200, Harald Wellmann wrote:
> Everyone I know who's moved from Hibernate to OpenJPA agrees that
> enhancement is a major nuisance in OpenJPA.
>
> I'm spending valuable time explaining to my team why this is needed,
> which of all the warning messages can be ignored and which are real
> problems, and why we didn't simply stick with Hibernate (answer: because
> Hibernate sucks on persistent maps).
>
> Enhancement is a violation of the KISS principle. Hibernate just works
> out of the box, and you don't have to worry about enhancement or weaving
> at all.
>
> I really think the onus is on OpenJPA: Why should users have to learn
> about extra build steps when they could do without?
>
> The most manifest problem with build-time enhancment is that it makes
> your entity JAR depend on OpenJPA. This is a no-go when you use (parts
> of) your entity model with different JPA providers.
>
>
> >
> > Can you please elaborate why you did not prefer *build-time enhancement*?
> >
> > build-time enhancement is
> > a) a simple post-compilation step
>
> Yes, but it makes your classes depend on OpenJPA.
>
> > b) easily integrable to any automated Ant/Maven based build environment
>
> This does not cover IDEs like Eclipse + Maven + m2e + WTP where any
> postprocessing of class files just breaks the toolchain.
>
> > c) saves a ton of trouble
>
> Funny - enhancement is really the one major _source_ of trouble I've had
> with OpenJPA since I started using it a year ago, and I'd really love to
> see it disappear.
>
> >
> > But it is not as popular as we would like it to be.
> > I am just trying to understand why.
> >
>
> Because it forces you to worry about things you don't want to know about.
>
> Deployment time enhancement at least works on Glassfish 3.1 or on OSGi
> with Equinox 3.7 with Aries 0.4-SNAPSHOT, but then you still have to
> worry about enhancement for out-of-container tests.
>
> And my project uses Spring and Tomcat (which are not so easy to get rid
> of) where load time enhancement just doesn't work at all for some
> reason, at least not with our fairly complex entity model.
>
> Best regards,
>
> Harald
>
>
>
>
Re: Problems with load time enhancement and Spring's TomcatInstrumentableClassLoader
Posted by Harald Wellmann <ha...@gmx.de>.
Everyone I know who's moved from Hibernate to OpenJPA agrees that
enhancement is a major nuisance in OpenJPA.
I'm spending valuable time explaining to my team why this is needed,
which of all the warning messages can be ignored and which are real
problems, and why we didn't simply stick with Hibernate (answer: because
Hibernate sucks on persistent maps).
Enhancement is a violation of the KISS principle. Hibernate just works
out of the box, and you don't have to worry about enhancement or weaving
at all.
I really think the onus is on OpenJPA: Why should users have to learn
about extra build steps when they could do without?
The most manifest problem with build-time enhancment is that it makes
your entity JAR depend on OpenJPA. This is a no-go when you use (parts
of) your entity model with different JPA providers.
>
> Can you please elaborate why you did not prefer *build-time enhancement*?
>
> build-time enhancement is
> a) a simple post-compilation step
Yes, but it makes your classes depend on OpenJPA.
> b) easily integrable to any automated Ant/Maven based build environment
This does not cover IDEs like Eclipse + Maven + m2e + WTP where any
postprocessing of class files just breaks the toolchain.
> c) saves a ton of trouble
Funny - enhancement is really the one major _source_ of trouble I've had
with OpenJPA since I started using it a year ago, and I'd really love to
see it disappear.
>
> But it is not as popular as we would like it to be.
> I am just trying to understand why.
>
Because it forces you to worry about things you don't want to know about.
Deployment time enhancement at least works on Glassfish 3.1 or on OSGi
with Equinox 3.7 with Aries 0.4-SNAPSHOT, but then you still have to
worry about enhancement for out-of-container tests.
And my project uses Spring and Tomcat (which are not so easy to get rid
of) where load time enhancement just doesn't work at all for some
reason, at least not with our fairly complex entity model.
Best regards,
Harald
Re: Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
Posted by Pinaki Poddar <pp...@apache.org>.
Hi,
Following is from Rick's Spring reference [1]
[1]
http://static.springsource.org/spring/docs/2.0.x/reference/orm.html#orm-jpa-setup-lcemfb
> When is load time weaving required?
>
> Not all JPA providers impose the need of a JVM agent (Hibernate being an
> example). If your provider does not require an agent or you have other
> alternatives (for example applying enhancements at build time through a
> custom compiler or an ant task) the load time weaver *should not* be used.
>
Can you please elaborate why you did not prefer *build-time enhancement*?
build-time enhancement is
a) a simple post-compilation step
b) easily integrable to any automated Ant/Maven based build environment
c) saves a ton of trouble
But it is not as popular as we would like it to be.
I am just trying to understand why.
-----
Pinaki
--
View this message in context: http://openjpa.208410.n2.nabble.com/Problems-with-load-time-enhancement-and-Spring-s-TomcatInstrumentableClassLoader-tp6554347p6559761.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
Posted by Harald Wellmann <Ha...@gmx.de>.
Yes, I read that more than once and double checked my configuration. I also posted in the Spring forum a while ago, with no replies so far.
It would be helpful to have some background on the requirements for load time enhancement from the OpenJPA side. How does it normally work in a Java EE container? Does OpenJPA make any assumptions on which classloader is used for
- OpenJPA itself
- javax.persistence.* classes
Should it be the container classloader or the application classloader?
If I knew what OpenJPA expects, it would be easier to find out if and where the Spring/Tomcat environment is different and then address the issue to the resposible party - I spent a whole day on this issue and I'm really stuck at this point...
Regards,
Harald
-------- Original-Nachricht --------
> Datum: Wed, 6 Jul 2011 08:46:22 -0500
> Von: Rick Curtis <cu...@gmail.com>
> An: users@openjpa.apache.org
> Betreff: Re: Problems with load time enhancement and Spring\'s TomcatInstrumentableClassLoader
> Harold -
>
> Please take a read through the spring doc[1] to see if they address your
> problem.
>
> [1]
> http://static.springsource.org/spring/docs/2.0.x/reference/orm.html#orm-jpa-setup-lcemfb
--
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de
Re: Problems with load time enhancement and Spring's TomcatInstrumentableClassLoader
Posted by Rick Curtis <cu...@gmail.com>.
Harold -
Please take a read through the spring doc[1] to see if they address your
problem.
[1]
http://static.springsource.org/spring/docs/2.0.x/reference/orm.html#orm-jpa-setup-lcemfb
On Wed, Jul 6, 2011 at 8:25 AM, Harald Wellmann <Ha...@gmx.de>wrote:
> I'm trying to use OpenJPA 2.1.0 with Spring 3.0.5 and Tomcat 6.0.32 and a
> JPA 2.0 persistence unit configured by annotations.
>
> At first, the enhancer did not recognize any of my classes, which looks
> like the same problem as described in
> https://issues.apache.org/jira/browse/OPENJPA-1891.
>
> Then I moved the Geronimo JPA JAR from my WAR to Tomcat's lib folder as
> described in this issue (but this feels wrong somehow).
>
> After that, the enhancer starts to do some work but then fails with an
> exception which I don't really understand.
>
> It may be related to an inheritance chain in my entity model
>
> A -> B -> C
>
> where A is an Entity and B and C are MappedSuperclasses.
>
> Some trace output
>
> 8796 foo TRACE [main] openjpa.Enhance - Enhancing type "class com.A"
> loaded by WebappClassLoader
> context: /foo-web
> delegate: false
> repositories:
> /WEB-INF/classes/
> ----------> Parent Classloader:
> org.apache.catalina.loader.StandardClassLoader@a210b5b
> .
> 8808 foo TRACE [main] openjpa.Enhance - Enhancement for "com/A"
> completed. Class size: [669/3.516]
> 8809 foo TRACE [main] openjpa.Enhance - "com/B" requires runtime
> enhancement: true
> 209144 foo TRACE [main] openjpa.Enhance - Enhancing type "class com/B"
> loaded by WebappClassLoader
> context: /foo-web
> delegate: false
> repositories:
> /WEB-INF/classes/
> ----------> Parent Classloader:
> org.apache.catalina.loader.StandardClassLoader@a210b5b
> .
> 209170 foo TRACE [main] openjpa.Enhance - Enhancement for "com/B"
> completed. Class size: [1.204/5.336]
> 209008 foo WARN [main] openjpa.MetaData - The class "com.A" listed in
> the openjpa.MetaDataFactory configuration property could not be loaded by
> org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader
> WebappClassLoader
> context: /foo-web
> delegate: false
> repositories:
> /WEB-INF/classes/
> ----------> Parent Classloader:
> org.apache.catalina.loader.StandardClassLoader@a210b5b
> ; ignoring.
> 209008 foo TRACE [main] openjpa.MetaData - java.lang.NoSuchMethodError:
> com.C.pcGetManagedFieldCount()I
> java.lang.NoSuchMethodError: com.C.pcGetManagedFieldCount()I
> at com.B.<clinit>(B.java)
> at java.lang.Class.forName0(Native Method)
> at java.lang.Class.forName(Class.java:247)
> at
> org.apache.openjpa.meta.MetaDataRepository.classForName(MetaDataRepository.java:1552)
> at
> org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypesInternal(MetaDataRepository.java:1528)
> at
> org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypes(MetaDataRepository.java:1506)
> at
> org.apache.openjpa.kernel.AbstractBrokerFactory.loadPersistentTypes(AbstractBrokerFactory.java:283)
> at
> org.apache.openjpa.kernel.AbstractBrokerFactory.initializeBroker(AbstractBrokerFactory.java:239)
> at
> org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:213)
> at
> org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156)
> at
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227)
> at
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:154)
> at
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:60)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at
> org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:423)
> at
> org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:485)
> at $Proxy12.createEntityManager(Unknown Source)
>
> The missing method appears to be one added by the enhancer, but com.C has
> not been enhanced yet.
>
> I was able to deploy the same unenhanced persistence unit on Glassfish
> without problems, so there must be a problem on the interface between
> OpenJPA, Spring and Tomcat.
>
> Any ideas anyone...?
>
> Thanks,
> Harald
>
>
-
*Rick Curtis*
Re: Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
Posted by Pinaki Poddar <pp...@apache.org>.
Hi Andrew,
Your decision to opt for build-time enhancement is the right choice. The
wrinkles around the mechanics of bytecode enhancement process is the
responsibility of OpenJPA team. And we perhaps havn't done a good job of it
from a usability point of view. Moreover, we have introduced several
alternatives that can bypass bytecode enhancement at build time. However,
these mechanics often carry forward edge errors that manifest as runtime
errors and are difficult to track.
Here are few suggestions. Please add our perspectives
a) emphasize the import of bytecode enhancement at build time in our
document. The XML
b) make the mechanics more accessible -- they exist but are hard to
find
c) block or at least inhibit other modes such that the developer can
do the right thing and not get tangled in a weave at runtime.
-----
Pinaki Poddar
Chair, Apache OpenJPA Project
--
View this message in context: http://openjpa.208410.n2.nabble.com/Problems-with-load-time-enhancement-and-Spring-s-TomcatInstrumentableClassLoader-tp6554347p6577479.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
Posted by Andrew Thompson <at...@columbia.edu>.
Pinaki,
The culprit in my case was maven/m2eclipse which by default executes the
maven builder on every change. This wasn't an issue at all related to
openjpa other then it was a required step within the build.
While that default behavior can, and should, be modified. My experience
was that it added confusion for developers who previously didn't have to
know about byte code enhancement or even a maven build.
-Andy
On Tue, 2011-07-12 at 17:56 -0700, Pinaki Poddar wrote:
> > even then that introduced a minute or two of build time in eclipse
> How are you invoking build-time enhancement in Eclipse?
>
> > which without hackery insists on a full project build.
> Who insists on a full project build on minor changes?
>
> -----
> Pinaki Poddar
> Chair, Apache OpenJPA Project
> --
> View this message in context: http://openjpa.208410.n2.nabble.com/Problems-with-load-time-enhancement-and-Spring-s-TomcatInstrumentableClassLoader-tp6554347p6577376.html
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
Re: Problems with load time enhancement and Spring's
TomcatInstrumentableClassLoader
Posted by Pinaki Poddar <pp...@apache.org>.
> even then that introduced a minute or two of build time in eclipse
How are you invoking build-time enhancement in Eclipse?
> which without hackery insists on a full project build.
Who insists on a full project build on minor changes?
-----
Pinaki Poddar
Chair, Apache OpenJPA Project
--
View this message in context: http://openjpa.208410.n2.nabble.com/Problems-with-load-time-enhancement-and-Spring-s-TomcatInstrumentableClassLoader-tp6554347p6577376.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.