| Summary: | IndexOutOfBoundsException in DatabaseSessionImpl.initializeDescriptors because @MapKey Annotation is not found. | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | z_Archived | Reporter: | Hans Harz <hansharz_bugzilla> | ||||||
| Component: | Eclipselink | Assignee: | Tom Ware <tom.ware> | ||||||
| Status: | CLOSED FIXED | QA Contact: | |||||||
| Severity: | major | ||||||||
| Priority: | P2 | CC: | andrew, eclipselink.orm-inbox, michael.f.obrien, s-b-u, tom.ware | ||||||
| Version: | unspecified | Flags: | tom.ware:
iplog+
|
||||||
| Target Milestone: | --- | ||||||||
| Hardware: | PC | ||||||||
| OS: | Windows 7 | ||||||||
| Whiteboard: | asm submitted_patch | ||||||||
| Attachments: |
|
||||||||
|
Description
Hans Harz
Created attachment 178527 [details]
Original jar and the one written by Proguard (and three dependencies)
1. unzip the file
2. add EclipseLink 2.1 and javax_persistence in the "derFetteMainer_lib" folder
3. just execute the both jars two see the difference.
- Original one "derFetteMainer.jar" executes fine, and prints three lines.
- The one written by Proguard "derFetteMainer_ob.jar" throws an EL-93 exception.
Created attachment 178529 [details]
The workspace for this simple test
Complete workspace just add EclipseLink 2.1 and javax_persistence in the lib folder.
I found a workaround after stepping through asm and EclipseLink classes (it's horrible what's going on in the asm library. Why don't you use java reflection to get the annotations?!)
It is possible to patch the method
org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAsmFactory.ClassMetadataVisitor.addAnnotations(Attribute, Map<String, MetadataAnnotation>)
like this:
/**
* If the attribute is an annotations attribute, add all annotations attached to it.
*/
public void addAnnotations(final Attribute attr, final Map<String, MetadataAnnotation> annotations)
{
if (attr instanceof RuntimeVisibleAnnotations) {
final RuntimeVisibleAnnotations visibleAnnotations = (RuntimeVisibleAnnotations) attr;
for (final Iterator iterator = visibleAnnotations.annotations.iterator(); iterator.hasNext();) {
final Annotation visibleAnnotation = (Annotation) iterator.next();
// Only add annotations that we care about.
if ((visibleAnnotation.type.indexOf("javax/persistence") != -1)
|| (visibleAnnotation.type.indexOf("org/eclipse/persistence") != -1)) {
final MetadataAnnotation annotation = buildAnnotation(visibleAnnotation);
annotations.put(annotation.getName(), annotation);
}
}
}
//FIX: also read "sub-annotations"
if ((attr != null && attr.next instanceof RuntimeVisibleAnnotations)) {
final RuntimeVisibleAnnotations visibleAnnotations = (RuntimeVisibleAnnotations) attr.next;
for (final Iterator iterator = visibleAnnotations.annotations.iterator(); iterator.hasNext();) {
final Annotation visibleAnnotation = (Annotation) iterator.next();
// Only add annotations that we care about.
if ((visibleAnnotation.type.indexOf("javax/persistence") != -1)
|| (visibleAnnotation.type.indexOf("org/eclipse/persistence") != -1)) {
final MetadataAnnotation annotation = buildAnnotation(visibleAnnotation);
if (!annotations.containsKey(annotation.getName())) {
annotations.put(annotation.getName(), annotation);
}
}
}
}
}
But I think this is only a workaround and should be elaborated more precisely.
FYI: ASM is used to get annotations to avoid some needing a special classloader to introspect the classes. Setting target and priority. See the following page for details of the meanings of these fields: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines Here is our version of a fix for this issue:
Note that this is a bit different (and more robust) than Hans's solution, as it checks ALL of the Attributes in the hierarchy, instead of just the first two. We ran into an issue where there were many Annotations that needed to be saved.
/**
* If the attribute is an annotations attribute, add all annotations attached to it.
*/
public void addAnnotations(Attribute attr, Map<String, MetadataAnnotation> annotations) {
Attribute toUse = attr;
while (toUse != null) {
if (toUse instanceof RuntimeVisibleAnnotations) {
addAnnotationsHelper(annotations, (RuntimeVisibleAnnotations) toUse);
}
toUse = toUse.next;
}
}
private void addAnnotationsHelper(Map<String, MetadataAnnotation> annotations, RuntimeVisibleAnnotations visibleAnnotations) {
for (Iterator iterator = visibleAnnotations.annotations.iterator(); iterator.hasNext();) {
Annotation visibleAnnotation = (Annotation) iterator.next();
// Only add annotations that we care about.
if ((visibleAnnotation.type.indexOf("javax/persistence") != -1) || (visibleAnnotation.type.indexOf("org/eclipse/persistence") != -1)) {
MetadataAnnotation annotation = buildAnnotation(visibleAnnotation);
annotations.put(annotation.getName(), annotation);
}
}
}
Taking an initial look to determine feasability of including patch from this bug. Checked in fix as suggested. Tested with attached test case and JPA LRG. I was unable to write a regression test due to the unavailabliity of an ofuscator in the test framework. Reviewed: Tom Ware - reviewed user submitted fix *** Bug 304602 has been marked as a duplicate of this bug. *** The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |