Hey Andrus,

You were of course right ;-)

I was sure there was an easy way to make it work because I could run the test with Hibernate and it worked fine. But as I looked into the internals of Hibernate its not actually instrumenting any classes for this test case. I played around a bit and could not get it to instrument anything so I decided to move on.

I'll continue to assume a managed env until I can get something going. And then I'll come back to the non-managed env.

TTFN,


Bill Dudney
MyFaces - http://myfaces.apache.org
Cayenne - http://incubator.apache.org/projects/cayenne.html



On Mar 28, 2006, at 12:05 AM, Andrus Adamchik wrote:

I suggested to postpone the discussion, but here is one more note :-) Let me clarify - I understand how JPA runtime can get access to enhanced classes. The problem is that the same class can also be accessed directly in the application, bypassing JPA runtime (just like in my unit test) - that's what causes the problem.

Andrus



On Mar 28, 2006, at 10:55 AM, Andrus Adamchik wrote:
app class loader will not be getting at the classes directly but instead will be using the persistence unit's class loader.

That's what I thought initially too. Only after trying to make it work with test cases I realized the problem. With hierarchical ClassLoaders, a ClassLoader can either load classes directly or get them from its parent, but not from a child or a peer loader. In Java EE you can tweak loader hierarchy at the container level (or register ClassTransformers with the custom app ClassLoader subclass), so this is not a problem. AFAIK in Java SE you can't, except by using instrumentation API.

I hope I've overlooked something basic. So how about this. Since you and Jeff will be working on the enhancer shortly, let's postpone this discussion till we can test the enhancer. It would be great if someone can prove me wrong on that.

Andrus



On Mar 28, 2006, at 1:11 AM, Bill Dudney wrote:
Regarding the ClassTransformer... JPA ClassTransformer is there to presumably hide the details of how the actual enhancement is done. By itself it won't allow you to redefine the class in the application ClassLoader, only in your own ClassLoader. Consider a test case:

   Object object = query.getSingleResult();

assertEquals("Test1", MyPersistentClass.class.getName(), object.getClass().getName());
   assertTrue("Test2", object instanceof MyPersistentClass);

The first test succeeds, but the second one fails! Cause you'll be checking against MyPersistentClass from the app ClassLoader, not the enhanced MyPersistentClass from the JPA ClassLoader. Somehow we need to make a ClassTransformer to be a "delegate" for the app class loader to force the entire application to use the enhanced version of the class. The only way I know of is the instrumentation API.

My understanding is that the ClassTransformer is going to be employed by the EntityManager to transform the classes before returning them to the runtime.

Take a look at the comment on the bottom of page 148. The way I read that is the ClassTransformer will be given a chance to augment any class before making that class available to the runtime. My understanding is that things go something like this;

Java EE Environment;
1) Container loads the persistence.xml file into a PersistenceUnitInfo instance 2) Container creates the EntityManagerFactory implementation and passes in the PersistenceUnitInfo 3) EntityManagerFactory (cayenne impl) adds a ClassTransformer to the PersistenceUnitInfo
4) Container gets classes that are augmented by the ClassTransformer

JavaSE Environment;
1) Application loads JPA stuff with Persistence.createEntityManagerFactory(String) 2) JPA runtime parses the persistence.xml file associated with the named persistence unit 3) JPA runtime creates the EntityManagerFactory implementation and passes in the PersistenceUnitInfo 3) EntityManagerFactory (cayenne impl) adds a ClassTransformer to the PersistenceUnitInfo 4) JPA runtime gets classes that are augmented by the ClassTransformer

So either way the classes that are used by the application are augmented by the ClassTransformer. In other words the app class loader will not be getting at the classes directly but instead will be using the persistence unit's class loader.

So if this is true both 'Test1' and 'Test2' will work.

Thoughts?

Bill Dudney
MyFaces - http://myfaces.apache.org
Cayenne - http://incubator.apache.org/projects/cayenne.html




Reply via email to