You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Prashant Bhat <pr...@gmail.com> on 2007/07/25 10:10:21 UTC

Modifications to Properties of Basic types inside LifecycleListener do not get saved!

Hi,

I've a mapped super class 'BaseEntity' that has common properties like
Date createdOn; Date updatedOn; boolean active; Company company; User
createdBy; etc.

Initially I used @EntityListeners defined at the BaseEntity and in
LifeCycleEvent handler on PrePersist(), I update these above common
properties.
I wanted my own instance of the listener(or to get hold of it), as I've to
update these from the UI module. But I couldn't find a way to do this in JPA
as it accepts only classes. Thanks to OpenJPA, I could achieve this easily
like this:

if (entityManagerFactory instanceof OpenJPAEntityManagerFactory) {
         ((OpenJPAEntityManagerFactory)
entityManagerFactory).addLifecycleListener(entityLifecycleHandler, (Class[])
null);
}

But in both the above cases, inside prePersist method, If I set the
properties of type Date or Boolean, they do not get saved.
Other properties like Company, User, etc. are saved properly.

Are the entities passed can not be modified in the listener? Or Is there any
other approach that could achieve this?

Thanks and Regards,
Prashant

Re: Modifications to Properties of Basic types inside LifecycleListener do not get saved!

Posted by Prashant Bhat <pr...@gmail.com>.
Hello Patrick,

I'm using latest openjpa built from source using java 1.5.0_11-b03. (At
runtime I'm using java6) And In my standalone application, I use Spring(
2.0.6) to manage transactions.
o/p of OpenJPAVersion:
OpenJPA 1.0.0-SNAPSHOT
version id: openjpa-1.0.0-SNAPSHOT-r420667:559353
Apache svn revision: 420667:559353

Yes, The test case TestLifecycleListener works with AllFieldTypes entity(I
tried to break it using many approaches, it works!). Actually, I don't find
a logical reason for this kind of behaviour in my application(As enum, other
entity references are saved but not Date, boolean!).  Probably, I've made a
mistake somewhere while configuring.

So, I put a breakpoint on the setter of that property(and a out.println) to
check which code is modifying it! Here are my observations:
In beforePersist method ->  lastUpdatedOn = Thu Jul 26 19:11:48 SGT 2007

And here lastUpdatedOn = null :->
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 112 in
BaseEntity))
    Role(BaseEntity).pcsetLastUpdatedOn(Date) line: 112
    Role(BaseEntity).pcReplaceField(int) line: not available
    Role(CompanyEntity).pcReplaceField(int) line: not available
    Role.pcReplaceField(int) line: not available
    StateManagerImpl.replaceField(PersistenceCapable, FieldManager, int)
line: 2872
    StateManagerImpl.settingObjectField(PersistenceCapable, int, Object,
Object, int) line: 1780
    VersionAttachStrategy(AttachStrategy).attachField(AttachManager, Object,
StateManagerImpl, FieldMetaData, boolean) line: 179
    VersionAttachStrategy.attach(AttachManager, Object, ClassMetaData,
PersistenceCapable, OpenJPAStateManager, ValueMetaData, boolean) line:
134
    AttachManager.attach(Object, PersistenceCapable, OpenJPAStateManager,
ValueMetaData, boolean) line: 239
    AttachManager.attach(Object) line: 100
    BrokerImpl.attach(Object, boolean, OpCallbacks) line: 3186
    DelegatingBroker.attach(Object, boolean, OpCallbacks) line: 1147
    EntityManagerImpl.merge(T) line: 665
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not
available [native method]
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
    Method.invoke(Object, Object...) line: 597

SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(Object,
Method, Object[]) line: 180
    $Proxy5.merge(Object) line: not available
    RoleDaoJpa(BaseDaoJpa<E>).save(E) line: 137

And by this line ->
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 114 in
BaseEntity))
    Role(BaseEntity).pcsetLastUpdatedOn(Date) line: 114
    Role(BaseEntity).pcClearFields() line: not available
    Role(CompanyEntity).pcClearFields() line: not available
    Role.pcClearFields() line: not available
    Role.pcNewInstance(StateManager, boolean) line: not available
    SaveFieldManager.saveField(int) line: 127
    StateManagerImpl.saveField(int) line: 2561
    StateManagerImpl.dirty(int, Boolean, boolean) line: 1474
    StateManagerImpl.settingStringField(PersistenceCapable, int, String,
String, int) line: 1816

it prints: lastUpdatedOn = null again So it is updated twice to null!
And then it prints, sql-trace logs for getting the next sequence number and
insert query in which these date fields are null!

Sorry for troubling you again. I'm not very familiar with OpenJPA code base,
so I thought posting this could be helpful in finding this issue I'm facing.

Thanks,
Prashant.


On 7/26/07, Patrick Linskey <pl...@gmail.com> wrote:
>
> Hi,
>
> I just added a test case that demonstrates that this works correctly
> --- see https://svn.apache.org/viewvc?view=rev&revision=559515
>
> What version of OpenJPA are you using? Until about a month ago, I
> think that the beforePersist() callback wasn't being invoked at all,
> but that would not result in the symptoms that you're describing.
>
> -Patrick
>

Re: Modifications to Properties of Basic types inside LifecycleListener do not get saved!

Posted by Patrick Linskey <pl...@gmail.com>.
Hi,

I just added a test case that demonstrates that this works correctly
--- see https://svn.apache.org/viewvc?view=rev&revision=559515

What version of OpenJPA are you using? Until about a month ago, I
think that the beforePersist() callback wasn't being invoked at all,
but that would not result in the symptoms that you're describing.

-Patrick

On 7/25/07, Prashant Bhat <pr...@gmail.com> wrote:
> Just to verify this, I added following two properties to
> org.apache.openjpa.persistence.fields.EnumFieldType
> private Date createdOn;
> private boolean active = true;
>
> And modified TestEnumQueryConstructor :
> setup() {
>         if (emf instanceof OpenJPAEntityManagerFactory) {
>             ((OpenJPAEntityManagerFactory) emf).addLifecycleListener(new
> EntityLifecycleHandler(), (Class[]) null);
>         }
> ....
> }
>
> public void testEnumQueryConstructor() {
> ..
>         assertEquals(SampleEnum.BAR, e.getEnumField());
>         assertNotNull(e.getCreatedOn());
>         assertFalse(e.isActive());
> }
>
> public class EntityLifecycleHandler extends AbstractLifecycleListener {
>     @Override
>     protected void eventOccurred(LifecycleEvent event) {
>         switch (event.getType()) {
>         case LifecycleEvent.BEFORE_PERSIST:
>             if(event.getSource() instanceof EnumFieldType) {
>               EnumFieldType e = (EnumFieldType)event.getSource();
>               e.setCreatedOn(new Date());
>               e.setActive(false);
>               e.setEnumField(SampleEnum.BAR);
>             }
>             break;
>         default:
>             break;
>         }
>     }
>    }
>
> Both of these fail:
> assertNotNull(e.getCreatedOn());
> assertFalse(e.isActive());
>
> But assertEquals(SampleEnum.BAR, e.getEnumField()); passes the test!
>
> Sorry for not giving a full test case as I'm not very familiar with it! Hope
> this helps.
>
> Thanks and Regards,
> Prashant
>
> On 7/25/07, Prashant Bhat <pr...@gmail.com> wrote:
> >
> > Hi,
> >
> > I've a mapped super class 'BaseEntity' that has common properties like
> > Date createdOn; Date updatedOn; boolean active; Company company; User
> > createdBy; etc.
> >
> > Initially I used @EntityListeners defined at the BaseEntity and in
> > LifeCycleEvent handler on PrePersist(), I update these above common
> > properties.
> > I wanted my own instance of the listener(or to get hold of it), as I've to
> > update these from the UI module. But I couldn't find a way to do this in JPA
> > as it accepts only classes. Thanks to OpenJPA, I could achieve this easily
> > like this:
> >
> > if (entityManagerFactory instanceof OpenJPAEntityManagerFactory) {
> >          ((OpenJPAEntityManagerFactory)
> > entityManagerFactory).addLifecycleListener(entityLifecycleHandler, (Class[])
> > null);
> > }
> >
> > But in both the above cases, inside prePersist method, If I set the
> > properties of type Date or Boolean, they do not get saved.
> > Other properties like Company, User, etc. are saved properly.
> >
> > Are the entities passed can not be modified in the listener? Or Is there
> > any other approach that could achieve this?
> >
> > Thanks and Regards,
> >  Prashant
> >
> >
>


-- 
Patrick Linskey
202 669 5907

Re: Modifications to Properties of Basic types inside LifecycleListener do not get saved!

Posted by Prashant Bhat <pr...@gmail.com>.
Just to verify this, I added following two properties to
org.apache.openjpa.persistence.fields.EnumFieldType
private Date createdOn;
private boolean active = true;

And modified TestEnumQueryConstructor :
setup() {
        if (emf instanceof OpenJPAEntityManagerFactory) {
            ((OpenJPAEntityManagerFactory) emf).addLifecycleListener(new
EntityLifecycleHandler(), (Class[]) null);
        }
....
}

public void testEnumQueryConstructor() {
..
        assertEquals(SampleEnum.BAR, e.getEnumField());
        assertNotNull(e.getCreatedOn());
        assertFalse(e.isActive());
}

public class EntityLifecycleHandler extends AbstractLifecycleListener {
    @Override
    protected void eventOccurred(LifecycleEvent event) {
        switch (event.getType()) {
        case LifecycleEvent.BEFORE_PERSIST:
            if(event.getSource() instanceof EnumFieldType) {
              EnumFieldType e = (EnumFieldType)event.getSource();
              e.setCreatedOn(new Date());
              e.setActive(false);
              e.setEnumField(SampleEnum.BAR);
            }
            break;
        default:
            break;
        }
    }
   }

Both of these fail:
assertNotNull(e.getCreatedOn());
assertFalse(e.isActive());

But assertEquals(SampleEnum.BAR, e.getEnumField()); passes the test!

Sorry for not giving a full test case as I'm not very familiar with it! Hope
this helps.

Thanks and Regards,
Prashant

On 7/25/07, Prashant Bhat <pr...@gmail.com> wrote:
>
> Hi,
>
> I've a mapped super class 'BaseEntity' that has common properties like
> Date createdOn; Date updatedOn; boolean active; Company company; User
> createdBy; etc.
>
> Initially I used @EntityListeners defined at the BaseEntity and in
> LifeCycleEvent handler on PrePersist(), I update these above common
> properties.
> I wanted my own instance of the listener(or to get hold of it), as I've to
> update these from the UI module. But I couldn't find a way to do this in JPA
> as it accepts only classes. Thanks to OpenJPA, I could achieve this easily
> like this:
>
> if (entityManagerFactory instanceof OpenJPAEntityManagerFactory) {
>          ((OpenJPAEntityManagerFactory)
> entityManagerFactory).addLifecycleListener(entityLifecycleHandler, (Class[])
> null);
> }
>
> But in both the above cases, inside prePersist method, If I set the
> properties of type Date or Boolean, they do not get saved.
> Other properties like Company, User, etc. are saved properly.
>
> Are the entities passed can not be modified in the listener? Or Is there
> any other approach that could achieve this?
>
> Thanks and Regards,
>  Prashant
>
>