[ 
https://issues.apache.org/jira/browse/OPENJPA-672?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Kevin Sutter resolved OPENJPA-672.
----------------------------------

    Resolution: Duplicate

Shoot.  I knew I had opened a JIRA issue...  This is a dup of OPENJPA-646.

> Annotations, Enums, and our TemporaryClassLoader
> ------------------------------------------------
>
>                 Key: OPENJPA-672
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-672
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: lib
>    Affects Versions: 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.1.0
>            Reporter: Kevin Sutter
>            Assignee: Kevin Sutter
>
> I thought I had opened a JIRA for this dev forum discussion 
> (http://n2.nabble.com/Sun-JDK-problem-with-duplicate-annotations-tt218302.html#a218302),
>  but I guess not.
> I have been tracking this problem via a problem report with the IBM JDK team 
> (since I was able to eventually reproduce the same problem with both the Sun 
> JDK and IBM JDK).  So far, we have not determined a definite problem with the 
> JDK processing of annotations and enums.
> Here's a summary of the basic problem (from the dev forum post):
> The scenario is that I have annotations doubly defined (ie. 
> javax.persistence.OneToMany and alt.persistence.OneToMany).  A single entity 
> might utilize both of them, like this:
>     @javax.persistence.OneToMany(cascade=javax.persistence.CascadeType.REMOVE)
>     @alt.persistence.OneToMany(cascade=alt.persistence.CascadeType.REMOVE)
>     Collection<Fill> buySideFills;
> This results in the following callstack snippet when running with the 
> -javaagent version of enhancement and the Sun JDK (fixpack 15):
> java.lang.ArrayStoreException: 
> sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy
>     at 
> sun.reflect.annotation.AnnotationParser.parseEnumArray(AnnotationParser.java:673)
>     at 
> sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:462)
>     at 
> sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:286)
>     at 
> sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:222)
>     at 
> sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
>     at 
> sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
>     at java.lang.reflect.Field.declaredAnnotations(Field.java:1002)
>     at java.lang.reflect.Field.getDeclaredAnnotations(Field.java:995)
>     at 
> java.lang.reflect.AccessibleObject.getAnnotations(AccessibleObject.java:179)
>     at 
> org.apache.openjpa.lib.util.J2DoPriv5Helper$1.run(J2DoPriv5Helper.java:51)
>     at java.security.AccessController.doPrivileged(Native Method)
>     at 
> org.apache.openjpa.persistence.PersistenceMetaDataDefaults.annotated(PersistenceMetaDataDefaults.java:293)
>     at 
> org.apache.openjpa.persistence.PersistenceMetaDataDefaults.getAccessType(PersistenceMetaDataDefaults.java:262)
>     at 
> org.apache.openjpa.persistence.PersistenceMetaDataDefaults.getAccessType(PersistenceMetaDataDefaults.java:250)
>     at 
> org.apache.openjpa.meta.AbstractMetaDataDefaults.populate(AbstractMetaDataDefaults.java:155)
>     at 
> org.apache.openjpa.persistence.PersistenceMetaDataDefaults.populate(PersistenceMetaDataDefaults.java:227)
>     at 
> org.apache.openjpa.meta.MetaDataRepository.addMetaData(MetaDataRepository.java:794)
>     at 
> org.apache.openjpa.meta.MetaDataRepository.addMetaData(MetaDataRepository.java:780)
>     at 
> org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser.getMetaData(AnnotationPersistenceMetaDataParser.java:657)
>     at 
> org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser.parseClassAnnotations(AnnotationPersistenceMetaDataParser.java:480)
>     at 
> org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser.parse(AnnotationPersistenceMetaDataParser.java:352)
>     at 
> org.apache.openjpa.persistence.PersistenceMetaDataFactory.load(PersistenceMetaDataFactory.java:229)
>     at 
> org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:474)
>     at 
> org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:294)
>     at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:248)
>     at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:219)
>     at 
> org.apache.openjpa.enhance.PCClassFileTransformer.transform0(PCClassFileTransformer.java:139)
>     at 
> org.apache.openjpa.enhance.PCClassFileTransformer.transform(PCClassFileTransformer.java:120)
>     at 
> sun.instrument.TransformerManager.transform(TransformerManager.java:122)
>     at 
> sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:155)
>     at java.lang.ClassLoader.defineClass1(Native Method)
>     at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
>     at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
>     at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
>     at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
>     at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
>     at java.security.AccessController.doPrivileged(Native Method)
>     at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
>     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
>     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
>     at java.lang.Class.forName0(Native Method)
>     at java.lang.Class.forName(Class.java:242)
>     at 
> org.apache.openjpa.meta.MetaDataRepository.classForName(MetaDataRepository.java:1298)
>     at 
> org.apache.openjpa.meta.MetaDataRepository.loadPersistentTypes(MetaDataRepository.java:1280)
>     at 
> org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:138)
>     at 
> org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newBrokerImpl(JDBCBrokerFactory.java:119)
>     at 
> org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:189)
>     at 
> org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:142)
>     at 
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:192)
>     at 
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:145)
>     at 
> org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:1)
> From working with the JDK team, the problem is surfacing because the 
> ClassLoader (AppClassLoader) that is used to load the Enum type when the 
> alt.persistence.OneToMany is loaded is not the same ClassLoader 
> (TemporaryClassLoader) when the Enum type is loaded by our enhancement 
> processing.  Thus, the AnnotationTypeMismatchExceptionProxy from the JDK.
> One way to workaround the problem is to add a test for Enum types in the 
> TemporaryClassLoader and use the AppClassLoader in this case (much like we do 
> for Annotation types):
>             if (isAnnotation(classBytes) || isEnum(classBytes))
>                 return Class.forName(name, resolve, 
> getClass().getClassLoader());
> The JDK team suggested removing the check for isAnnotation (and isEnum) 
> altogether since that resolved the simple testcase that I had put together 
> for their benefit.  Unfortunately, that doesn't work for our enhancement 
> processing for a couple of reasons.  The _strats structure in 
> PersistentMetaDataDefaults depended on the 
> org.apache.openjpa.persistence.PersistentCollection class.  By removing the 
> conditional above, then we had a mismatch in classloaders for this data 
> structure, much like the jdk problem.
> I tried changing the key for this _strats structure to use the class name 
> string instead of the actual class instance.  This got us around our 
> immediate concern, but eventually I hit another JDK issue with mismatched 
> classloaders when processing the annotations in 
> AnnotationPersistentMetaDataParser:
>                     parsePersistentCollection(fmd, (PersistentCollection)
>                         el.getAnnotation(PersistentCollection.class));
> The loading of this PersistentCollection.class used the AppClassLoader, so 
> the lookup via getAnnotation didn't find anything since the original 
> annotation was loaded by the TemporaryClassLoader.  Trying to get around this 
> situation was creating some pretty ugly code.
> So, I am leaning towards the original workaround as a "solution" with proper 
> commenting.  By allowing the AppClassLoader to load enum types (vs the 
> TemporaryClassLoader), we would "pollute" the AppClassLoader with left over 
> enum classes.  This would seem to be a minor drawback.  Of course, if we ever 
> need to allow for the enhancement of enum classes, then we're up a creek...
> Enough detail for now.  Comments and suggestions are welcome.
> Kevin

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to