[
https://issues.apache.org/jira/browse/OPENJPA-386?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12746273#action_12746273
]
Jody Grassel commented on OPENJPA-386:
--------------------------------------
The problem was how ClassMetaData.hasConcretePCSuperclass() handled mapped
superclasses. Let's say we have the following classes:
@MappedSuperclass
public class MSC
@Entity
@IdClass(MyIdClass.class)
public class EntityA extends MSC
(Note that the @MappedSuperclass type "MSC" is not abstract, which is perfectly
legal with the JPA Spec.)
Now, when an entity extending the MSC is annotated with @IdClass, the metadata
processing notes that there are PC-enhanced superclasses, and needs to analyze
them to check if they declare any identity elements, in order to ensure that
the @IdClass specified will address them. It uses this method in ClassMetaData
to check if it has a PC superclass that is concrete (effectively, any entity
class types that are further up the inheritance tree.:
/**
* Return true if this class has a concrete persistent superclass.
*/
private boolean hasConcretePCSuperclass() {
if (_super == null)
return false;
if (!Modifier.isAbstract(_super.getModifiers())))
return true;
return getPCSuperclassMetaData().hasConcretePCSuperclass();
}
The line: if (!Modifier.isAbstract(_super.getModifiers()))) is responsible for
detecting @MappedSuperclasses, however it relies exclusively on the class being
abstract, something that, while recommended, is not required by the JPA Spec.
So it will incorrectly treat a @MappedSuperclass as a regular entity, resulting
in this Exception:
org.apache.openjpa.util.MetaDataException: Field "testcase.EntityA.id" cannot
be a primary key. Primary key fields can only be declared in base persistent
classes that also declare their identity type- to be "application".
at
org.apache.openjpa.meta.ClassMetaData.validateNoPKFields(ClassMetaData.java:2025)
at
org.apache.openjpa.meta.ClassMetaData.validateAppIdClass(ClassMetaData.java:1905)
at
org.apache.openjpa.meta.ClassMetaData.validateIdentity(ClassMetaData.java:1851)
at
org.apache.openjpa.meta.ClassMetaData.validateMeta(ClassMetaData.java:1768)
at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1641)
...
The solution was to simply add another check for the @MappedSuperclass. This
is already done with the ClassMetaData.isAbstract() method in trunk (which is
set true if a class type explicitly is annotated with @MappedSuperclass, or is
defined as a mapped-superclass by ORM XML), which was brought down to 1.2.x and
1.3.x in OPENJPA-1061. With the following change:
private boolean hasConcretePCSuperclass() {
if (_super == null)
return false;
if (!Modifier.isAbstract(_super.getModifiers()) &&
(!getPCSuperclassMetaData().isAbstract()))
return true;
return getPCSuperclassMetaData().hasConcretePCSuperclass();
}
With the above change, a @MappedSuperclass can now be identified whether or not
its class type is actually a Java abstract class or not.
> org.apache.openjpa.meta.ClassMetaData.validateAppIdClass() does not take
> @MappedSuperclass into account
> -------------------------------------------------------------------------------------------------------
>
> Key: OPENJPA-386
> URL: https://issues.apache.org/jira/browse/OPENJPA-386
> Project: OpenJPA
> Issue Type: Bug
> Components: kernel
> Affects Versions: 0.9.7, 1.0.0, 1.0.2
> Environment: BEA WebLogic 10.0 under Windows XP SP1
> Reporter: Matthew L. Schwickerath
> Assignee: Jody Grassel
>
> We have a @MappedSuperclass that is the base for all of our entity bean
> classes. This class contains the @Version (and @Column for the version
> field) that all of our entity beans use. But, in
> ClassMetaData.validateAppIdClass(), if an entity bean class has a superclass,
> and the entity bean has an @IdClass, it expects that superclass to have an
> @IdClass also. All of our entity beans have an @IdClass (even if they only
> have a single part key), but our @MappedSuperclass does not have an @IdClass.
> This scenario works under JBoss 4.2.0 and Sun AS 9, but produces a
> NullPointerException in OpenJPA at:
> if (_super != null) {
> // concrete superclass oids must match or be parent of ours
> ClassMetaData sup = getPCSuperclassMetaData();
> if (!sup.getObjectIdType().isAssignableFrom(_objectId)) // <---
> NullPointerException here
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.