Re: JPA and class enhancers

From: Bill Dudney (bdudne..pache.org)
Date: Wed Mar 29 2006 - 15:41:15 EST

  • Next message: Andrus Adamchik: "CLA's from committers"

    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
    >>
    >>
    >



    This archive was generated by hypermail 2.0.0 : Wed Mar 29 2006 - 15:42:01 EST