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.