Issue Details (XML | Word | Printable)

Key: OPENJPA-146
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Unassigned
Reporter: Gokhan Ergul
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
OpenJPA

Entity enhancement fails while using EmbeddedId on a MappedSuperclass

Created: 14/Feb/07 12:00 PM   Updated: 01/Mar/07 02:13 AM
Return to search
Issue 606 of 675 issue(s)
<< Previous | OPENJPA-146 | Next >>
Component/s: kernel
Affects Version/s: None
Fix Version/s: 0.9.7

Time Tracking:
Not Specified

File Attachments:
  Size
Zip Archive test-case.zip 2007-02-14 12:04 PM Gokhan Ergul 2 kB
Environment: openjpa 0.9.6

Resolution Date: 20/Feb/07 04:35 PM


 Description  « Hide
Both buildtime and runtime class enhancement fail with the following error:

...
1339 TRACE [main] openjpa.Enhance - Enhancing type "class test.B".
Exception in thread "main" <0|false|0.9.6-incubating> org.apache.openjpa.util.GeneralException: null
        at org.apache.openjpa.enhance.PCEnhancer.run(PCEnhancer.java:350)
        at org.apache.openjpa.enhance.PCEnhancer.run(PCEnhancer.java:3711)
        at org.apache.openjpa.enhance.PCEnhancer.run(PCEnhancer.java:3661)
        at org.apache.openjpa.enhance.PCEnhancer.main(PCEnhancer.java:3633)
Caused by: java.lang.NullPointerException
        at org.apache.openjpa.enhance.PCEnhancer.enhanceObjectId(PCEnhancer.java:2745)
        at org.apache.openjpa.enhance.PCEnhancer.run(PCEnhancer.java:338)
        ... 3 more

Test code as follows:

test/A.java:
--------------
package test;

import javax.persistence.*;
import java.io.Serializable;

@MappedSuperclass
abstract public class A {

    @Embeddable
    public static class A_PK implements Serializable {
        @Basic
        protected int id1;
        
        @Basic
        protected String id2;
        
        public boolean equals (Object other) {
            return false;
        }

        public int hashCode () {
            return 0;
        }

    }

    @EmbeddedId
    protected A_PK pk;

    @Basic
    protected String val;

}
--------------

test/B.java:
--------------
package test;

import javax.persistence.Entity;

@Entity
public class B extends A {

}
--------------

META-INF/persistence.xml:
--------------
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
        version="1.0">
    <persistence-unit name="TestService" transaction-type="RESOURCE_LOCAL">
        <class>test.A$A_PK</class>
        <class>test.A</class>
        <class>test.B</class>
        <properties>
            <property name="openjpa.Log" value="DefaultLevel=TRACE"/>

            <property name="openjpa.ConnectionUserName" value="test"/>
            <property name="openjpa.ConnectionPassword" value="test"/>
            <property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/oam?useServerPrepStmts=false"/>
            <property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
        </properties>
    </persistence-unit>
</persistence>
--------------





 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Gokhan Ergul added a comment - 14/Feb/07 12:04 PM
Test case and trace output attached.

Abe White added a comment - 14/Feb/07 03:25 PM
We don't enhance the oid class anymore, so this bug is probably fixed or at least will manifest itself in a different way in the latest code.

Gokhan Ergul added a comment - 17/Feb/07 09:13 AM
0.9.7-snapshot seems to have solved this indeed, thanks.

Gokhan Ergul added a comment - 17/Feb/07 10:08 AM
Alright, it did manifest itself in a different way as you guessed:

java.lang.NullPointerException
at org.apache.openjpa.jdbc.meta.strats.EmbedValueHandler.map(EmbedValueHandler.java:50)
at org.apache.openjpa.jdbc.meta.strats.ObjectIdValueHandler.map(ObjectIdValueHandler.java:46)
at org.apache.openjpa.jdbc.meta.strats.HandlerStrategies.map(HandlerStrategies.java:56)
at org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy.map(HandlerFieldStrategy.java:77)
at org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:117)
...

Bit of debugging into the code:

(EmbedValueHandler.java)
    protected void map(ValueMapping vm, String name, ColumnIO io,
        boolean adapt, List cols, List args) {
        // have to resolve embedded value to collect its columns
        vm.getEmbeddedMapping().resolve(vm.MODE_META | vm.MODE_MAPPING);
...

vm .getEmbeddedMapping() returns null, since:

(ValueMetaDataImpl.java)
    public ClassMetaData getEmbeddedMetaData() {
        if (_embeddedMeta == null && isEmbeddedPC())
            addEmbeddedMetaData();
        return _embeddedMeta;
    }

and

    public boolean isEmbeddedPC() {
        return _decCode == JavaTypes.PC && isEmbedded();
    }

_decCode is JavaTypes.OID.

JavaTypes.PC was possibly overwritten by:

    public boolean resolve(int mode) {
...
        // oid as primary key field?
        if (_decCode == JavaTypes.PC && isEmbedded()
            && _owner.isPrimaryKey() && _owner.getValue() == this)
            _code = _decCode = JavaTypes.OID;

So I've changed

    public boolean isEmbeddedPC() {
        return _decCode == JavaTypes.PC && isEmbedded();
    }

to

    public boolean isEmbeddedPC() {
        return (_decCode == JavaTypes.PC || _decCode == JavaTypes.OID) && isEmbedded();
    }

seems to have fixed the problem, tho I'm not sure if it has any nasty sideeffects.

Any comments?

Abe White added a comment - 20/Feb/07 03:33 PM
Looks like a good fix to me. Do you need someone to commit this for you?

Abe White added a comment - 20/Feb/07 04:07 PM
Cancel my previous comment. Embedded PCs are handled very differently than OIDs at runtime, and so changing the isEmbeddedPC method to encompass OIDs as well might cause problems. I think the root of the problem has to do with metadata resolution of mapped superclass fields (after all, EmbeddedIds in Entities work fine, just not in MappedSuperclasses). I'll investigate further.

Abe White added a comment - 20/Feb/07 04:35 PM
Resolved with revision 509632. When copying OID superclass fields for mapping in a subclass, revert the type of the field to PC. It will re-resolve to OID when the copied field's metadata is resolved, and in the meantime it ensures that the copied field resolution will use the same code path as non-copied fields.

Gokhan Ergul added a comment - 20/Feb/07 06:39 PM
Fix confirmed, thanks.