Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 0.9.6, 0.9.7
    • Fix Version/s: 2.0.0-M2
    • Component/s: kernel
    • Labels:
      None
    • Environment:
      Java 6

      Description

      When using an application id class containing a reference to another entity (example given below) a NPE is thrown when merging/reattaching the instance to an entity manager.
      The problem is caused by the involved AttachStrategy where on line 89 (pc.pcNewInstance(null, appId, false) the call to pcNewInstance is null for the first parameter (StateManager). This statemanager is used to retrieve the object reference when reattaching using the method pcCopyKeyFieldsFromObjectId in the pcNewInstance method.

      Source for this bug:

      @Entity
      @Table(name = "domain_record")
      @IdClass(DomainRecord.DomainRecordId.class)
      public class DomainRecord implements Serializable {

      private static final long serialVersionUID = 2966781630801201103L;

      public static class DomainRecordId implements Serializable {

      private static final long serialVersionUID = 3629556841694516032L;

      private String zone;

      private String name;

      private Type type;

      private String data;

      public DomainRecordId() {
      }

      public DomainRecordId(DomainRecord record)

      { this.zone = record.zone.getName(); this.name = record.name; this.type = record.type; this.data = record.data; }

      public DomainRecordId(String zone, String name, Type type, String data)

      { this.zone = zone; this.name = name; this.type = type; this.data = data; }

      /**

      • @see java.lang.Object#hashCode()
        */
        @Override
        public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((data == null) ? 0 : data.hashCode()); result = PRIME * result + ((name == null) ? 0 : name.hashCode()); result = PRIME * result + ((type == null) ? 0 : type.hashCode()); result = PRIME * result + ((zone == null) ? 0 : zone.hashCode()); return result; }

      /**

      • @see java.lang.Object#equals(java.lang.Object)
        */
        @Override
        public boolean equals(Object obj)
        Unknown macro: { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final DomainRecordId other = (DomainRecordId) obj; if (data == null) { if (other.data != null) return false; } else if (!data.equals(other.data)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; if (zone == null) { if (other.zone != null) return false; } else if (!zone.equals(other.zone)) return false; return true; }

      }

      /**

      • @author markusw
      • @version $Revision$
        */
        public enum Type { A, AAAA, ALIAS, CNAME, HINFO, MX, NAPTR, NS, PTR, RP, SRV, TXT }

      @Id
      @ManyToOne(fetch = FetchType.LAZY, cascade =

      { CascadeType.ALL }

      )
      @JoinColumn(name = "domain", referencedColumnName = "name")
      private Domain zone;

      @Id
      @Column(length = 64)
      private String name;

      @Id
      @Enumerated(EnumType.STRING)
      private Type type;

      @Id
      @Column(length = 128)
      private String data;
      ...
      }

      1. OPENJPA-218-testcase.patch
        14 kB
        Fay Wang
      2. OPENJPA-218.patch
        1 kB
        Fay Wang

        Activity

        Markus Wolf created issue -
        Hide
        Markus Wolf added a comment -

        To be more complete I'll attach the NPE stacktrace:

        java.lang.NullPointerException
        at de.esw.services.model.DomainRecord.pcCopyKeyFieldsFromObjectId(DomainRecord.java)
        at de.esw.services.model.DomainRecord.pcNewInstance(DomainRecord.java)
        at org.apache.openjpa.kernel.AttachStrategy.persist(AttachStrategy.java:89)
        at org.apache.openjpa.kernel.VersionAttachStrategy.attach(VersionAttachStrategy.java:85)
        at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:236)
        at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:97)
        at org.apache.openjpa.kernel.BrokerImpl.attach(BrokerImpl.java:3124)
        at org.apache.openjpa.kernel.DelegatingBroker.attach(DelegatingBroker.java:1120)
        at org.apache.openjpa.persistence.EntityManagerImpl.merge(EntityManagerImpl.java:591)
        at org.springframework.orm.jpa.JpaTemplate$6.doInJpa(JpaTemplate.java:272)
        at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:191)
        at org.springframework.orm.jpa.JpaTemplate.merge(JpaTemplate.java:270)
        at de.esw.services.domain.DomainRecordProcessorImpl.update(DomainRecordProcessorImpl.java:53)

        Show
        Markus Wolf added a comment - To be more complete I'll attach the NPE stacktrace: java.lang.NullPointerException at de.esw.services.model.DomainRecord.pcCopyKeyFieldsFromObjectId(DomainRecord.java) at de.esw.services.model.DomainRecord.pcNewInstance(DomainRecord.java) at org.apache.openjpa.kernel.AttachStrategy.persist(AttachStrategy.java:89) at org.apache.openjpa.kernel.VersionAttachStrategy.attach(VersionAttachStrategy.java:85) at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:236) at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:97) at org.apache.openjpa.kernel.BrokerImpl.attach(BrokerImpl.java:3124) at org.apache.openjpa.kernel.DelegatingBroker.attach(DelegatingBroker.java:1120) at org.apache.openjpa.persistence.EntityManagerImpl.merge(EntityManagerImpl.java:591) at org.springframework.orm.jpa.JpaTemplate$6.doInJpa(JpaTemplate.java:272) at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:191) at org.springframework.orm.jpa.JpaTemplate.merge(JpaTemplate.java:270) at de.esw.services.domain.DomainRecordProcessorImpl.update(DomainRecordProcessorImpl.java:53)
        Hide
        Fay Wang added a comment - - edited

        I tried the following scenario to reproduce this problem without success:

        (1) create an EntityManager: em
        (2) create a DomainRecord: record
        (3) call persist: em.persist(record)
        (4) em.flush()
        (5) commit
        (6) em.clear()
        (7) em.merge(record)

        This situation can only be reproduced in the following scenario:
        (1) create an EntityManager: em
        (2) create a DomainRecord: record
        (3) em.merge(record)

        When merge is called on the record, this record does not have StateManagerImpl yet, causing NPE.

        Show
        Fay Wang added a comment - - edited I tried the following scenario to reproduce this problem without success: (1) create an EntityManager: em (2) create a DomainRecord: record (3) call persist: em.persist(record) (4) em.flush() (5) commit (6) em.clear() (7) em.merge(record) This situation can only be reproduced in the following scenario: (1) create an EntityManager: em (2) create a DomainRecord: record (3) em.merge(record) When merge is called on the record, this record does not have StateManagerImpl yet, causing NPE.
        Hide
        Fay Wang added a comment -

        The patch is to fix PCEnhancer to guard against null StateManagerImpl:

        Before the patch:
        -----------------------
        public void pcCopyKeyFieldsFromObjectId(Object paramObject)

        { ChildId localChildId = (ChildId)((ObjectId)paramObject).getId(); this.id = localChildId.id; Child tmp28_27 = this; tmp28_27.parent = ((Parent)tmp28_27.pcStateManager.getPCPrimaryKey(localChildId, 2 + pcInheritedFieldCount)); }

        After the patch:
        --------------------
        public void pcCopyKeyFieldsFromObjectId(Object paramObject)

        { ChildId localChildId = (ChildId)((ObjectId)paramObject).getId(); this.id = localChildId.id; if (this.pcStateManager == null) return; Child tmp28_27 = this; tmp28_27.parent = ((Parent)tmp28_27.pcStateManager.getPCPrimaryKey(localChildId, 2 + pcInheritedFieldCount)); }

        After the patch, the test case to merge new entity with IdClass works fine.

        Show
        Fay Wang added a comment - The patch is to fix PCEnhancer to guard against null StateManagerImpl: Before the patch: ----------------------- public void pcCopyKeyFieldsFromObjectId(Object paramObject) { ChildId localChildId = (ChildId)((ObjectId)paramObject).getId(); this.id = localChildId.id; Child tmp28_27 = this; tmp28_27.parent = ((Parent)tmp28_27.pcStateManager.getPCPrimaryKey(localChildId, 2 + pcInheritedFieldCount)); } After the patch: -------------------- public void pcCopyKeyFieldsFromObjectId(Object paramObject) { ChildId localChildId = (ChildId)((ObjectId)paramObject).getId(); this.id = localChildId.id; if (this.pcStateManager == null) return; Child tmp28_27 = this; tmp28_27.parent = ((Parent)tmp28_27.pcStateManager.getPCPrimaryKey(localChildId, 2 + pcInheritedFieldCount)); } After the patch, the test case to merge new entity with IdClass works fine.
        Fay Wang made changes -
        Field Original Value New Value
        Attachment OPENJPA-218.patch [ 12404377 ]
        Fay Wang made changes -
        Attachment OPENJPA-218-testcase.patch [ 12404386 ]
        Fay Wang made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Fix Version/s 2.0.0 [ 12313483 ]
        Resolution Fixed [ 1 ]
        Donald Woods made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Transition Time In Source Status Execution Times Last Executer Last Execution Date
        Open Open Resolved Resolved
        716d 5h 29m 1 Fay Wang 02/Apr/09 21:08
        Resolved Resolved Closed Closed
        340d 22h 22m 1 Donald Woods 09/Mar/10 18:31

          People

          • Assignee:
            Unassigned
            Reporter:
            Markus Wolf
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development