6 Replies Latest reply on Nov 13, 2008 8:06 AM by itai.peleg

    exception while saving bidirectional entities

      we have errors when trying to create new entities that has bidirectional associations between entities. we got an exception while envers try to save the entities

      the entities:

      @javax.persistence.Entity
      @org.jboss.envers.Versioned
      public class Employment {
       @Id
       @GeneratedValue
       @org.hibernate.annotations.AccessType("property")
       private Long id;
      
       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "person_id")
       private Person person;
      
       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "organization_id")
       private Organization organization;
       ...
      }
      
      @javax.persistence.Entity
      @org.jboss.envers.Versioned
      public class Person {
       @Id
       @GeneratedValue
       @org.hibernate.annotations.AccessType("property")
       private Long id;
      
       @OneToMany(mappedBy="person")
       @VersionsJoinTable(name = "_rev_join_employment_person_")
       private Set<Employment> employments = new HashSet<Employment>();
      }
      
      @javax.persistence.Entity
      @org.jboss.envers.Versioned
      public class Organization {
       @Id
       @GeneratedValue
       @org.hibernate.annotations.AccessType("property")
       private Long id;
      
       @OneToMany(mappedBy="organization")
       @VersionsJoinTable(name = "_rev_join_employment_organization_")
       private Set<Employment> employments = new HashSet<Employment>();
      }
      
      


      the exception stacktrace:
      2008-11-12 08:21:56,956 DEBUG [SQL] - insert into _rev_join_organization_organization_email_ (revision_type, revision, organization_id, id) values (?, ?, ?, ?)
      2008-11-12 08:21:56,957 ERROR [JDBCTransaction] - exception calling user Synchronization
      org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.digitaltrowel.model.extractions.organization.Employment.createdByStepExecution at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:58)
       at org.hibernate.property.DirectPropertyAccessor$DirectGetter.getForInsert(DirectPropertyAccessor.java:63)
       at org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValuesToInsert(AbstractEntityTuplizer.java:294)
       at org.hibernate.tuple.entity.PojoEntityTuplizer.getPropertyValuesToInsert(PojoEntityTuplizer.java:239)
       at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValuesToInsert(AbstractEntityPersister.java:3696)
       at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
       at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
       at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
       at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
       at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
       at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
       at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
       at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
       at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:562)
       at org.hibernate.impl.SessionImpl.save(SessionImpl.java:550)
       at org.jboss.envers.synchronization.work.PersistentCollectionChangeWorkUnit.perform(PersistentCollectionChangeWorkUnit.java:67)
       at org.jboss.envers.synchronization.VersionsSync.executeInSession(VersionsSync.java:120)
       at org.jboss.envers.synchronization.VersionsSync.beforeCompletion(VersionsSync.java:144)
       at org.hibernate.transaction.JDBCTransaction.notifyLocalSynchsBeforeTransactionCompletion(JDBCTransaction.java:274)
       at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:140)
       at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)
       at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
       at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
       at com.digitaltrowel.test.AbstractTransactionalSpringContextTest$TransactionContext.endTransaction(AbstractTransactionalSpringContextTest.java:243)
       at com.digitaltrowel.test.AbstractTransactionalSpringContextTest.endTransaction(AbstractTransactionalSpringContextTest.java:201)
       at com.digitaltrowel.test.AbstractTransactionalSpringContextTest.commit(AbstractTransactionalSpringContextTest.java:195)
       at com.digitaltrowel.test.data.DataGenerationTest.testCreateData(DataGenerationTest.java:55)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:163)
       at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:233)
       at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:333)
       at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217)
       at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197)
       at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143)
       at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:142)
       at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
       at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
       at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
       at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
       at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
       at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
       at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
      Caused by: java.lang.IllegalArgumentException: Can not set com.digitaltrowel.model.batch.metadata.BatchStepExecution field com.digitaltrowel.model.versionedentity.VersionedEntity.createdByStepExecution to java.util.HashMap
       at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
       at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
       at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
       at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
       at java.lang.reflect.Field.get(Field.java:358)
       at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:55)
       ... 48 more
      


      any idea?

        • 1. Re: exception while saving bidirectional entities
          adamw

          Hello,

          the problem seems to be in the property "Employment.createdByStepExecution", what is the declaration of this field?

          Also, Envers didn't support "AccessType("property")" (values where always read directly from fields), but that is changed now - in trunk. So maybe that's the problem ... but please post the Employment class (or only the relevant part of it).

          --
          Adam

          • 2. Re: exception while saving bidirectional entities

            Hi Adam

            it doesn't seem like the "Employment.createdByStepExecution", because when i transiant it the error past to the next property...

            but any way here is the relevant part:

            @MappedSuperclass
            public abstract class VersionedEntity implements Serializable {
             @Id
             @GeneratedValue
             @org.hibernate.annotations.AccessType("property")
             private Long id;
             private Long entityId;
             private Date creationTimeStamp;
            
             @Embedded
             private Period validityPeriod;
             @Column(length = 5)
             private String executedJobRegister = "00000";
            
             @ManyToOne(fetch = FetchType.LAZY)
             @JoinColumn(name = "created_by_step_execution_id")
             private BatchStepExecution createdByStepExecution;
            }
            
            @Entity
            @org.jboss.envers.Versioned
            public class Employment extends VersionedEntity{
             @Column(name="pos")
             private String position;
             private Boolean currentPosition;
             private String subposition;
            
             @ManyToOne(fetch = FetchType.LAZY)
             @JoinColumn(name = "person_id")
             private Person person;
            
             @ManyToOne(fetch = FetchType.LAZY)
             @JoinColumn(name = "organization_id")
             private Organization organization;
            }
            
            @Entity
            @org.jboss.envers.Versioned
            public class Organization extends VersionedEntity{
             private String type;
             private Date activatedDate;
             private Date inactivatedDate;
            
             @Embedded
             private OrganizationName primaryName;
             @Embedded
             private JurisdictionInfo jurisdictionInfo;
             @OneToMany(mappedBy="organization")
             @VersionsJoinTable(name = "_rev_join_employment_organization_")
             private Set<Employment> employments = new HashSet<Employment>();
            }
            
            @Entity
            @org.jboss.envers.Versioned
            public class Person extends VersionedEntity {
             @Embedded
             private PersonName name;
             private String dtpid;
            
             @OneToMany(mappedBy="person")
             @VersionsJoinTable(name = "_rev_join_employment_person_")
             private Set<Employment> employments = new HashSet<Employment>();
            }
            
            @Entity
            @Table(name = "BATCH_STEP_EXECUTION")
            @org.hibernate.annotations.Immutable
            @org.jboss.envers.Versioned
            public class BatchStepExecution {
             @Id
             @org.hibernate.annotations.AccessType("property")
             @Column(name = "STEP_EXECUTION_ID", nullable = false, length = 19)
             private Long stepExecutionId;
             @Column(name = "VERSION", nullable = false, length = 19)
             @Unversioned
             private Long version;
             @Column(name = "STEP_NAME", nullable = false, length = 100)
            // @Unversioned
             private String stepName;
            }
            


            thanks Itai

            • 3. Re: exception while saving bidirectional entities
              adamw

              Looks like a bug somewhere, but hard to say where ... could you create a testcase and create a jira bug?

              Thanks,
              Adam

              • 4. Re: exception while saving bidirectional entities

                Hi Adam

                I open bug, id: HHH-3600

                thanks Itai

                • 5. Re: exception while saving bidirectional entities
                  adamw

                  Thanks :)
                  It turned out that I fixed this issue yesterday, as another user reported a similar problem - see HHH-3594.

                  The fix is in trunk, but it's really simple, so you can also apply it on the source and build; the only thing you need to change is add one "if" in three methods in VersionsEventListener:

                  public void onPreUpdateCollection(PreCollectionUpdateEvent event) {
                   CollectionEntry collectionEntry = getCollectionEntry(event);
                   if (!collectionEntry.getLoadedPersister().isInverse()) {
                   onCollectionAction(event, event.getCollection(), collectionEntry.getSnapshot(), collectionEntry);
                   }
                   }
                  
                   public void onPreRemoveCollection(PreCollectionRemoveEvent event) {
                   CollectionEntry collectionEntry = getCollectionEntry(event);
                   if (!collectionEntry.getLoadedPersister().isInverse()) {
                   onCollectionAction(event, null, collectionEntry.getSnapshot(), collectionEntry);
                   }
                   }
                  
                   public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
                   CollectionEntry collectionEntry = getCollectionEntry(event);
                   if (!collectionEntry.getLoadedPersister().isInverse()) {
                   onCollectionAction(event, event.getCollection(), null, collectionEntry);
                   }
                   }
                  


                  --
                  Adam

                  • 6. Re: exception while saving bidirectional entities

                    Thanks for the fast response, and yes it solve the problem!

                    Itai