You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Donny Nadolny <do...@gmail.com> on 2011/05/29 16:34:12 UTC

BeanEditForm for hibernate entity with version field

I've got a BeanEditForm for my User entity which has a version field:

    @Version
    public long getVersion() {
        return version;
    }
    public void setVersion(long version) {
        this.version = version;
    }

I've got an admin screen to edit a user, and I would like to make sure I
don't overwrite changes made by the user (they can change their password,
for example) or by the application, while I'm on the edit screen. I've tried
a few things, but I always see the same behavior: any changes in the
database get overwritten when I hit "save" in the BeanEditForm.

Test 1:
EditUser.tml:
<t:BeanEditForm object="user" t:id="editUserForm"/>

EditUser.java:
    @CommitAfter
    public Object onSuccessFromEditUserForm() {
        return UserIndex.class;
    }

I open the EditUser page in the browser, I change the user in the database
(increasing the version field by one), then I hit save in the browser,
expecting Hibernate to throw an exception. Instead, it saves the changes,
increasing the version again. Eg I start at version 0, open the page, edit
the db to change a field and set version to 1, then I hit save in the
browser, it clobbers my changes and sets version to be 2.


Test 2:
I tried out the code from JumpStart
http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
says it handles versioning. My code now looks like this:
tml:
<t:BeanEditForm object="user" t:id="editUserForm">
<p:version>
<t:hidden value="user.version"/>
</p:version>
</t:BeanEditForm>

The java code is the same as Test 1.

Again, the changes get clobbered.

Test 3:
I noticed that the hidden field didn't have an ID set, so I tried:
<t:hidden value="user.version" t:id="version"/>
Same thing, changes get overwritten.

Test 4:
Managing the version myself. In the tml I have:
    <t:BeanEditForm object="user" t:id="editUserForm">
        <p:version>
            <t:hidden t:id="versionWhenLoaded"/>
        </p:version>
    </t:BeanEditForm>

In java, I have:
    @PageActivationContext
    private User user;

    @Property
    private long versionWhenLoaded;

    public void setupRender() {
        versionWhenLoaded = user.getVersion();
    }

    @CommitAfter
    public Object onSuccessFromEditUserForm() {
        user.setVersion(versionWhenLoaded);
        return UserIndex.class;
    }

Again, changes get overwritten. I really would expect the last case to work
- maybe I need to do something special in Hibernate to set the version
field?

I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so Hibernate
3.6.0-Final).

I've confirmed that Hibernate does throw a
StaleObjectStateExceptionexception when it tries to make changes to
the user at the same time, by
having another page which does, essentially:
User user = userDAO.findById(1);
timeProvider.sleep(10000);
user.setFirstName("something different");
sessionManager.commit();
I load it twice, and the second page throws StaleObjectStateException.

Any ideas?

Re: BeanEditForm for hibernate entity with version field

Posted by Geoff Callender <ge...@gmail.com>.
The link http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud
has been replaced by:

	http://jumpstart.doublenegative.com.au/jumpstart/previews/easycrud/persons

On 30/05/2011, at 12:34 AM, Donny Nadolny wrote:

> I've got a BeanEditForm for my User entity which has a version field:
> 
>    @Version
>    public long getVersion() {
>        return version;
>    }
>    public void setVersion(long version) {
>        this.version = version;
>    }
> 
> I've got an admin screen to edit a user, and I would like to make sure I
> don't overwrite changes made by the user (they can change their password,
> for example) or by the application, while I'm on the edit screen. I've tried
> a few things, but I always see the same behavior: any changes in the
> database get overwritten when I hit "save" in the BeanEditForm.
> 
> Test 1:
> EditUser.tml:
> <t:BeanEditForm object="user" t:id="editUserForm"/>
> 
> EditUser.java:
>    @CommitAfter
>    public Object onSuccessFromEditUserForm() {
>        return UserIndex.class;
>    }
> 
> I open the EditUser page in the browser, I change the user in the database
> (increasing the version field by one), then I hit save in the browser,
> expecting Hibernate to throw an exception. Instead, it saves the changes,
> increasing the version again. Eg I start at version 0, open the page, edit
> the db to change a field and set version to 1, then I hit save in the
> browser, it clobbers my changes and sets version to be 2.
> 
> 
> Test 2:
> I tried out the code from JumpStart
> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> says it handles versioning. My code now looks like this:
> tml:
> <t:BeanEditForm object="user" t:id="editUserForm">
> <p:version>
> <t:hidden value="user.version"/>
> </p:version>
> </t:BeanEditForm>
> 
> The java code is the same as Test 1.
> 
> Again, the changes get clobbered.
> 
> Test 3:
> I noticed that the hidden field didn't have an ID set, so I tried:
> <t:hidden value="user.version" t:id="version"/>
> Same thing, changes get overwritten.
> 
> Test 4:
> Managing the version myself. In the tml I have:
>    <t:BeanEditForm object="user" t:id="editUserForm">
>        <p:version>
>            <t:hidden t:id="versionWhenLoaded"/>
>        </p:version>
>    </t:BeanEditForm>
> 
> In java, I have:
>    @PageActivationContext
>    private User user;
> 
>    @Property
>    private long versionWhenLoaded;
> 
>    public void setupRender() {
>        versionWhenLoaded = user.getVersion();
>    }
> 
>    @CommitAfter
>    public Object onSuccessFromEditUserForm() {
>        user.setVersion(versionWhenLoaded);
>        return UserIndex.class;
>    }
> 
> Again, changes get overwritten. I really would expect the last case to work
> - maybe I need to do something special in Hibernate to set the version
> field?
> 
> I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so Hibernate
> 3.6.0-Final).
> 
> I've confirmed that Hibernate does throw a
> StaleObjectStateExceptionexception when it tries to make changes to
> the user at the same time, by
> having another page which does, essentially:
> User user = userDAO.findById(1);
> timeProvider.sleep(10000);
> user.setFirstName("something different");
> sessionManager.commit();
> I load it twice, and the second page throws StaleObjectStateException.
> 
> Any ideas?


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: BeanEditForm for hibernate entity with version field

Posted by Donny Nadolny <do...@gmail.com>.
Hi Taha,

I've tried it having the application update it instead: I opened my "Edit
user" page, I hit a page that updated that user, and then I hit save in the
"Edit user" page and it overwrote the changes. When I tried just hitting two
pages that update the user (grab user, sleep for a bit to make it easy to
reproduce the race condition, then commit), I correctly get the
StaleObjectStateException for the second pageview.

Donny

On Sun, May 29, 2011 at 11:06 AM, Taha Hafeez <ta...@gmail.com>wrote:

> Updating the database directly is not advisable when working with hibernate
> and might be the culprit here. Can you test it by updating the instance
> using hibernate instead.
>
> regards
> Taha
>
>
> On Sun, May 29, 2011 at 8:04 PM, Donny Nadolny <donny.nadolny@gmail.com
> >wrote:
>
> > I've got a BeanEditForm for my User entity which has a version field:
> >
> >    @Version
> >    public long getVersion() {
> >        return version;
> >    }
> >    public void setVersion(long version) {
> >        this.version = version;
> >    }
> >
> > I've got an admin screen to edit a user, and I would like to make sure I
> > don't overwrite changes made by the user (they can change their password,
> > for example) or by the application, while I'm on the edit screen. I've
> > tried
> > a few things, but I always see the same behavior: any changes in the
> > database get overwritten when I hit "save" in the BeanEditForm.
> >
> > Test 1:
> > EditUser.tml:
> > <t:BeanEditForm object="user" t:id="editUserForm"/>
> >
> > EditUser.java:
> >    @CommitAfter
> >    public Object onSuccessFromEditUserForm() {
> >        return UserIndex.class;
> >    }
> >
> > I open the EditUser page in the browser, I change the user in the
> database
> > (increasing the version field by one), then I hit save in the browser,
> > expecting Hibernate to throw an exception. Instead, it saves the changes,
> > increasing the version again. Eg I start at version 0, open the page,
> edit
> > the db to change a field and set version to 1, then I hit save in the
> > browser, it clobbers my changes and sets version to be 2.
> >
> >
> > Test 2:
> > I tried out the code from JumpStart
> >
> >
> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> > says it handles versioning. My code now looks like this:
> > tml:
> > <t:BeanEditForm object="user" t:id="editUserForm">
> > <p:version>
> > <t:hidden value="user.version"/>
> > </p:version>
> > </t:BeanEditForm>
> >
> > The java code is the same as Test 1.
> >
> > Again, the changes get clobbered.
> >
> > Test 3:
> > I noticed that the hidden field didn't have an ID set, so I tried:
> > <t:hidden value="user.version" t:id="version"/>
> > Same thing, changes get overwritten.
> >
> > Test 4:
> > Managing the version myself. In the tml I have:
> >    <t:BeanEditForm object="user" t:id="editUserForm">
> >        <p:version>
> >            <t:hidden t:id="versionWhenLoaded"/>
> >        </p:version>
> >    </t:BeanEditForm>
> >
> > In java, I have:
> >    @PageActivationContext
> >    private User user;
> >
> >    @Property
> >    private long versionWhenLoaded;
> >
> >    public void setupRender() {
> >        versionWhenLoaded = user.getVersion();
> >    }
> >
> >    @CommitAfter
> >    public Object onSuccessFromEditUserForm() {
> >        user.setVersion(versionWhenLoaded);
> >        return UserIndex.class;
> >    }
> >
> > Again, changes get overwritten. I really would expect the last case to
> work
> > - maybe I need to do something special in Hibernate to set the version
> > field?
> >
> > I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so Hibernate
> > 3.6.0-Final).
> >
> > I've confirmed that Hibernate does throw a
> > StaleObjectStateExceptionexception when it tries to make changes to
> > the user at the same time, by
> > having another page which does, essentially:
> > User user = userDAO.findById(1);
> > timeProvider.sleep(10000);
> > user.setFirstName("something different");
> > sessionManager.commit();
> > I load it twice, and the second page throws StaleObjectStateException.
> >
> > Any ideas?
> >
>

Re: BeanEditForm for hibernate entity with version field

Posted by Taha Hafeez <ta...@gmail.com>.
Updating the database directly is not advisable when working with hibernate
and might be the culprit here. Can you test it by updating the instance
using hibernate instead.

regards
Taha


On Sun, May 29, 2011 at 8:04 PM, Donny Nadolny <do...@gmail.com>wrote:

> I've got a BeanEditForm for my User entity which has a version field:
>
>    @Version
>    public long getVersion() {
>        return version;
>    }
>    public void setVersion(long version) {
>        this.version = version;
>    }
>
> I've got an admin screen to edit a user, and I would like to make sure I
> don't overwrite changes made by the user (they can change their password,
> for example) or by the application, while I'm on the edit screen. I've
> tried
> a few things, but I always see the same behavior: any changes in the
> database get overwritten when I hit "save" in the BeanEditForm.
>
> Test 1:
> EditUser.tml:
> <t:BeanEditForm object="user" t:id="editUserForm"/>
>
> EditUser.java:
>    @CommitAfter
>    public Object onSuccessFromEditUserForm() {
>        return UserIndex.class;
>    }
>
> I open the EditUser page in the browser, I change the user in the database
> (increasing the version field by one), then I hit save in the browser,
> expecting Hibernate to throw an exception. Instead, it saves the changes,
> increasing the version again. Eg I start at version 0, open the page, edit
> the db to change a field and set version to 1, then I hit save in the
> browser, it clobbers my changes and sets version to be 2.
>
>
> Test 2:
> I tried out the code from JumpStart
>
> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> says it handles versioning. My code now looks like this:
> tml:
> <t:BeanEditForm object="user" t:id="editUserForm">
> <p:version>
> <t:hidden value="user.version"/>
> </p:version>
> </t:BeanEditForm>
>
> The java code is the same as Test 1.
>
> Again, the changes get clobbered.
>
> Test 3:
> I noticed that the hidden field didn't have an ID set, so I tried:
> <t:hidden value="user.version" t:id="version"/>
> Same thing, changes get overwritten.
>
> Test 4:
> Managing the version myself. In the tml I have:
>    <t:BeanEditForm object="user" t:id="editUserForm">
>        <p:version>
>            <t:hidden t:id="versionWhenLoaded"/>
>        </p:version>
>    </t:BeanEditForm>
>
> In java, I have:
>    @PageActivationContext
>    private User user;
>
>    @Property
>    private long versionWhenLoaded;
>
>    public void setupRender() {
>        versionWhenLoaded = user.getVersion();
>    }
>
>    @CommitAfter
>    public Object onSuccessFromEditUserForm() {
>        user.setVersion(versionWhenLoaded);
>        return UserIndex.class;
>    }
>
> Again, changes get overwritten. I really would expect the last case to work
> - maybe I need to do something special in Hibernate to set the version
> field?
>
> I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so Hibernate
> 3.6.0-Final).
>
> I've confirmed that Hibernate does throw a
> StaleObjectStateExceptionexception when it tries to make changes to
> the user at the same time, by
> having another page which does, essentially:
> User user = userDAO.findById(1);
> timeProvider.sleep(10000);
> user.setFirstName("something different");
> sessionManager.commit();
> I load it twice, and the second page throws StaleObjectStateException.
>
> Any ideas?
>

Re: BeanEditForm for hibernate entity with version field

Posted by Geoff Callender <ge...@gmail.com>.
I've just re-tested the JumpStart page and it does what you want.  Just be sure to use two different browsers applications for the two users so you're absolutely sure they're not sharing one user session.

Are you retrieving the user from the DB in onPrepare()? In debug you would expect to see it has the most recent user.version.

Have you tried adding method onValidateFormFromEditUserForm() and seeing whether user.version is correct in there? You would expect it to have been overwritten from the form.

If the answers are no and yes, then I guess it comes down to whether @CommitAfter somehow re-populates user.version, ignoring the form's hidden field, before invoking onSuccessFromEditUserForm()?

Cheers,

Geoff

On 30/05/2011, at 3:31 AM, Taha Tapestry wrote:

> I  am guessing the version field updates are ignored by hibernate so the solution that I suggested is more suitable.
> 
> Regards
> Taha
> Sent from my iPhone
> 
> On May 29, 2011, at 10:51 PM, Donny Nadolny <do...@gmail.com> wrote:
> 
>> Hi Taha,
>> 
>> Nice find, that's exactly the problem I have. Unfortunately it didn't seem
>> to work. I've tried:
>> tml:
>>   <t:BeanEditForm object="user" t:id="editUserForm">
>>       <p:version>
>>           <t:hidden t:id="versionWhenLoaded"/>
>>       </p:version>
>>   </t:BeanEditForm>
>> java:
>>   public void setupRender() {
>>       versionWhenLoaded = user.getVersion();
>>   }
>>   public void onPrepareEditUserForm() {
>>       session.clear();
>>   }
>>   @CommitAfter
>>   public Object onSuccessFromEditUserForm() {
>>       user.setVersion(versionWhenLoaded);
>>       return UserIndex.class;
>>   }
>> 
>> Didn't work. also tried merge:
>> tml: same as above
>>   @CommitAfter
>>   public Object onSuccessFromEditUserForm() {
>>       user.setVersion(versionWhenLoaded);
>>       session.merge(user);
>>       return UserIndex.class;
>>   }
>> 
>> Again, it just overwrites the changes.
>> 
>> This is a hibernate issue, but it would be nice if Tapestry's BeanEditForm
>> had an option (maybe even the default?) for proper handling of columns
>> marked with @Version. I think I'll open an issue for it.
>> 
>> Donny
>> 
>> On Sun, May 29, 2011 at 12:59 PM, Taha Tapestry <ta...@gmail.com>wrote:
>> 
>>> Check this out
>>> 
>>> https://forum.hibernate.org/viewtopic.php?f=1&t=957807
>>> 
>>> Sent from my iPhone
>>> 
>>> On May 29, 2011, at 10:06 PM, Donny Nadolny <do...@gmail.com>
>>> wrote:
>>> 
>>>> Hi Taha,
>>>> 
>>>> That would be a reasonable place to hook it in. However, I'd like to make
>>>> sure that it would work first, and it seems like in principle it's the
>>> same
>>>> as the 4th way I tried (which didn't work): store the current version
>>> when
>>>> the form is rendered, then when you save you grab the latest from the
>>>> database but first set the version to be the version when the form was
>>>> rendered. I still don't understand why that didn't work.
>>>> 
>>>> Donny
>>>> 
>>>> On Sun, May 29, 2011 at 12:24 PM, Taha Hafeez <tawus.tapestry@gmail.com
>>>> wrote:
>>>> 
>>>>> Hi Donny
>>>>> 
>>>>> One way I can think of is extend AbstractSessionPersistentFieldStrategy
>>> as
>>>>> is done by EntityPersistentFieldStrategy(tapestry-hibernate)  and store
>>>>> version in addition to id and type in PersistedEntity and later
>>>>> while retrieving the value, check the version too
>>>>> 
>>>>> Take a lot at
>>>>> 
>>>>> 
>>> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
>>>>> <
>>>>> 
>>> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
>>>>>> 
>>>>> 
>>>>> regards
>>>>> Taha
>>>>> 
>>>>> 
>>>>> On Sun, May 29, 2011 at 9:48 PM, Donny Nadolny <donny.nadolny@gmail.com
>>>>>> wrote:
>>>>> 
>>>>>> Hi Josh,
>>>>>> 
>>>>>> Yup, it must be. The question is, how do I stop that? I tried following
>>>>> the
>>>>>> example from the jumpstart demo but it didn't work, and I tried setting
>>>>> the
>>>>>> version field manually, and it still didn't work (the exact code I used
>>>>> is
>>>>>> in the initial email).
>>>>>> 
>>>>>> On Sun, May 29, 2011 at 12:11 PM, Josh Canfield <
>>> joshcanfield@gmail.com
>>>>>>> wrote:
>>>>>> 
>>>>>>> I would guess that you are pulling the object from the database when
>>>>> you
>>>>>>> post the form, and thus editing the current version.
>>>>>>> 
>>>>>>> I believe is the default behaviour with the tapestry persistent object
>>>>>>> translator, it stores the type and id in the form.
>>>>>>> 
>>>>>>> Josh
>>>>>>> On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com>
>>>>>> wrote:
>>>>>>>> I've got a BeanEditForm for my User entity which has a version field:
>>>>>>>> 
>>>>>>>> @Version
>>>>>>>> public long getVersion() {
>>>>>>>> return version;
>>>>>>>> }
>>>>>>>> public void setVersion(long version) {
>>>>>>>> this.version = version;
>>>>>>>> }
>>>>>>>> 
>>>>>>>> I've got an admin screen to edit a user, and I would like to make
>>>>> sure
>>>>>> I
>>>>>>>> don't overwrite changes made by the user (they can change their
>>>>>> password,
>>>>>>>> for example) or by the application, while I'm on the edit screen.
>>>>> I've
>>>>>>> tried
>>>>>>>> a few things, but I always see the same behavior: any changes in the
>>>>>>>> database get overwritten when I hit "save" in the BeanEditForm.
>>>>>>>> 
>>>>>>>> Test 1:
>>>>>>>> EditUser.tml:
>>>>>>>> <t:BeanEditForm object="user" t:id="editUserForm"/>
>>>>>>>> 
>>>>>>>> EditUser.java:
>>>>>>>> @CommitAfter
>>>>>>>> public Object onSuccessFromEditUserForm() {
>>>>>>>> return UserIndex.class;
>>>>>>>> }
>>>>>>>> 
>>>>>>>> I open the EditUser page in the browser, I change the user in the
>>>>>>> database
>>>>>>>> (increasing the version field by one), then I hit save in the
>>>>> browser,
>>>>>>>> expecting Hibernate to throw an exception. Instead, it saves the
>>>>>> changes,
>>>>>>>> increasing the version again. Eg I start at version 0, open the page,
>>>>>>> edit
>>>>>>>> the db to change a field and set version to 1, then I hit save in the
>>>>>>>> browser, it clobbers my changes and sets version to be 2.
>>>>>>>> 
>>>>>>>> 
>>>>>>>> Test 2:
>>>>>>>> I tried out the code from JumpStart
>>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>> 
>>> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
>>>>>>>> says it handles versioning. My code now looks like this:
>>>>>>>> tml:
>>>>>>>> <t:BeanEditForm object="user" t:id="editUserForm">
>>>>>>>> <p:version>
>>>>>>>> <t:hidden value="user.version"/>
>>>>>>>> </p:version>
>>>>>>>> </t:BeanEditForm>
>>>>>>>> 
>>>>>>>> The java code is the same as Test 1.
>>>>>>>> 
>>>>>>>> Again, the changes get clobbered.
>>>>>>>> 
>>>>>>>> Test 3:
>>>>>>>> I noticed that the hidden field didn't have an ID set, so I tried:
>>>>>>>> <t:hidden value="user.version" t:id="version"/>
>>>>>>>> Same thing, changes get overwritten.
>>>>>>>> 
>>>>>>>> Test 4:
>>>>>>>> Managing the version myself. In the tml I have:
>>>>>>>> <t:BeanEditForm object="user" t:id="editUserForm">
>>>>>>>> <p:version>
>>>>>>>> <t:hidden t:id="versionWhenLoaded"/>
>>>>>>>> </p:version>
>>>>>>>> </t:BeanEditForm>
>>>>>>>> 
>>>>>>>> In java, I have:
>>>>>>>> @PageActivationContext
>>>>>>>> private User user;
>>>>>>>> 
>>>>>>>> @Property
>>>>>>>> private long versionWhenLoaded;
>>>>>>>> 
>>>>>>>> public void setupRender() {
>>>>>>>> versionWhenLoaded = user.getVersion();
>>>>>>>> }
>>>>>>>> 
>>>>>>>> @CommitAfter
>>>>>>>> public Object onSuccessFromEditUserForm() {
>>>>>>>> user.setVersion(versionWhenLoaded);
>>>>>>>> return UserIndex.class;
>>>>>>>> }
>>>>>>>> 
>>>>>>>> Again, changes get overwritten. I really would expect the last case
>>>>> to
>>>>>>> work
>>>>>>>> - maybe I need to do something special in Hibernate to set the
>>>>> version
>>>>>>>> field?
>>>>>>>> 
>>>>>>>> I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so
>>>>>> Hibernate
>>>>>>>> 3.6.0-Final).
>>>>>>>> 
>>>>>>>> I've confirmed that Hibernate does throw a
>>>>>>>> StaleObjectStateExceptionexception when it tries to make changes to
>>>>>>>> the user at the same time, by
>>>>>>>> having another page which does, essentially:
>>>>>>>> User user = userDAO.findById(1);
>>>>>>>> timeProvider.sleep(10000);
>>>>>>>> user.setFirstName("something different");
>>>>>>>> sessionManager.commit();
>>>>>>>> I load it twice, and the second page throws
>>>>> StaleObjectStateException.
>>>>>>>> 
>>>>>>>> Any ideas?
>>>>>>> 
>>>>>> 
>>>>> 
>>> 
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>>> For additional commands, e-mail: users-help@tapestry.apache.org
>>> 
>>> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: BeanEditForm for hibernate entity with version field

Posted by Taha Tapestry <ta...@gmail.com>.
I  am guessing the version field updates are ignored by hibernate so the solution that I suggested is more suitable.

Regards
Taha
Sent from my iPhone

On May 29, 2011, at 10:51 PM, Donny Nadolny <do...@gmail.com> wrote:

> Hi Taha,
> 
> Nice find, that's exactly the problem I have. Unfortunately it didn't seem
> to work. I've tried:
> tml:
>    <t:BeanEditForm object="user" t:id="editUserForm">
>        <p:version>
>            <t:hidden t:id="versionWhenLoaded"/>
>        </p:version>
>    </t:BeanEditForm>
> java:
>    public void setupRender() {
>        versionWhenLoaded = user.getVersion();
>    }
>    public void onPrepareEditUserForm() {
>        session.clear();
>    }
>    @CommitAfter
>    public Object onSuccessFromEditUserForm() {
>        user.setVersion(versionWhenLoaded);
>        return UserIndex.class;
>    }
> 
> Didn't work. also tried merge:
> tml: same as above
>    @CommitAfter
>    public Object onSuccessFromEditUserForm() {
>        user.setVersion(versionWhenLoaded);
>        session.merge(user);
>        return UserIndex.class;
>    }
> 
> Again, it just overwrites the changes.
> 
> This is a hibernate issue, but it would be nice if Tapestry's BeanEditForm
> had an option (maybe even the default?) for proper handling of columns
> marked with @Version. I think I'll open an issue for it.
> 
> Donny
> 
> On Sun, May 29, 2011 at 12:59 PM, Taha Tapestry <ta...@gmail.com>wrote:
> 
>> Check this out
>> 
>> https://forum.hibernate.org/viewtopic.php?f=1&t=957807
>> 
>> Sent from my iPhone
>> 
>> On May 29, 2011, at 10:06 PM, Donny Nadolny <do...@gmail.com>
>> wrote:
>> 
>>> Hi Taha,
>>> 
>>> That would be a reasonable place to hook it in. However, I'd like to make
>>> sure that it would work first, and it seems like in principle it's the
>> same
>>> as the 4th way I tried (which didn't work): store the current version
>> when
>>> the form is rendered, then when you save you grab the latest from the
>>> database but first set the version to be the version when the form was
>>> rendered. I still don't understand why that didn't work.
>>> 
>>> Donny
>>> 
>>> On Sun, May 29, 2011 at 12:24 PM, Taha Hafeez <tawus.tapestry@gmail.com
>>> wrote:
>>> 
>>>> Hi Donny
>>>> 
>>>> One way I can think of is extend AbstractSessionPersistentFieldStrategy
>> as
>>>> is done by EntityPersistentFieldStrategy(tapestry-hibernate)  and store
>>>> version in addition to id and type in PersistedEntity and later
>>>> while retrieving the value, check the version too
>>>> 
>>>> Take a lot at
>>>> 
>>>> 
>> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
>>>> <
>>>> 
>> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
>>>>> 
>>>> 
>>>> regards
>>>> Taha
>>>> 
>>>> 
>>>> On Sun, May 29, 2011 at 9:48 PM, Donny Nadolny <donny.nadolny@gmail.com
>>>>> wrote:
>>>> 
>>>>> Hi Josh,
>>>>> 
>>>>> Yup, it must be. The question is, how do I stop that? I tried following
>>>> the
>>>>> example from the jumpstart demo but it didn't work, and I tried setting
>>>> the
>>>>> version field manually, and it still didn't work (the exact code I used
>>>> is
>>>>> in the initial email).
>>>>> 
>>>>> On Sun, May 29, 2011 at 12:11 PM, Josh Canfield <
>> joshcanfield@gmail.com
>>>>>> wrote:
>>>>> 
>>>>>> I would guess that you are pulling the object from the database when
>>>> you
>>>>>> post the form, and thus editing the current version.
>>>>>> 
>>>>>> I believe is the default behaviour with the tapestry persistent object
>>>>>> translator, it stores the type and id in the form.
>>>>>> 
>>>>>> Josh
>>>>>> On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com>
>>>>> wrote:
>>>>>>> I've got a BeanEditForm for my User entity which has a version field:
>>>>>>> 
>>>>>>> @Version
>>>>>>> public long getVersion() {
>>>>>>> return version;
>>>>>>> }
>>>>>>> public void setVersion(long version) {
>>>>>>> this.version = version;
>>>>>>> }
>>>>>>> 
>>>>>>> I've got an admin screen to edit a user, and I would like to make
>>>> sure
>>>>> I
>>>>>>> don't overwrite changes made by the user (they can change their
>>>>> password,
>>>>>>> for example) or by the application, while I'm on the edit screen.
>>>> I've
>>>>>> tried
>>>>>>> a few things, but I always see the same behavior: any changes in the
>>>>>>> database get overwritten when I hit "save" in the BeanEditForm.
>>>>>>> 
>>>>>>> Test 1:
>>>>>>> EditUser.tml:
>>>>>>> <t:BeanEditForm object="user" t:id="editUserForm"/>
>>>>>>> 
>>>>>>> EditUser.java:
>>>>>>> @CommitAfter
>>>>>>> public Object onSuccessFromEditUserForm() {
>>>>>>> return UserIndex.class;
>>>>>>> }
>>>>>>> 
>>>>>>> I open the EditUser page in the browser, I change the user in the
>>>>>> database
>>>>>>> (increasing the version field by one), then I hit save in the
>>>> browser,
>>>>>>> expecting Hibernate to throw an exception. Instead, it saves the
>>>>> changes,
>>>>>>> increasing the version again. Eg I start at version 0, open the page,
>>>>>> edit
>>>>>>> the db to change a field and set version to 1, then I hit save in the
>>>>>>> browser, it clobbers my changes and sets version to be 2.
>>>>>>> 
>>>>>>> 
>>>>>>> Test 2:
>>>>>>> I tried out the code from JumpStart
>>>>>>> 
>>>>>> 
>>>>>> 
>>>>> 
>>>> 
>> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
>>>>>>> says it handles versioning. My code now looks like this:
>>>>>>> tml:
>>>>>>> <t:BeanEditForm object="user" t:id="editUserForm">
>>>>>>> <p:version>
>>>>>>> <t:hidden value="user.version"/>
>>>>>>> </p:version>
>>>>>>> </t:BeanEditForm>
>>>>>>> 
>>>>>>> The java code is the same as Test 1.
>>>>>>> 
>>>>>>> Again, the changes get clobbered.
>>>>>>> 
>>>>>>> Test 3:
>>>>>>> I noticed that the hidden field didn't have an ID set, so I tried:
>>>>>>> <t:hidden value="user.version" t:id="version"/>
>>>>>>> Same thing, changes get overwritten.
>>>>>>> 
>>>>>>> Test 4:
>>>>>>> Managing the version myself. In the tml I have:
>>>>>>> <t:BeanEditForm object="user" t:id="editUserForm">
>>>>>>> <p:version>
>>>>>>> <t:hidden t:id="versionWhenLoaded"/>
>>>>>>> </p:version>
>>>>>>> </t:BeanEditForm>
>>>>>>> 
>>>>>>> In java, I have:
>>>>>>> @PageActivationContext
>>>>>>> private User user;
>>>>>>> 
>>>>>>> @Property
>>>>>>> private long versionWhenLoaded;
>>>>>>> 
>>>>>>> public void setupRender() {
>>>>>>> versionWhenLoaded = user.getVersion();
>>>>>>> }
>>>>>>> 
>>>>>>> @CommitAfter
>>>>>>> public Object onSuccessFromEditUserForm() {
>>>>>>> user.setVersion(versionWhenLoaded);
>>>>>>> return UserIndex.class;
>>>>>>> }
>>>>>>> 
>>>>>>> Again, changes get overwritten. I really would expect the last case
>>>> to
>>>>>> work
>>>>>>> - maybe I need to do something special in Hibernate to set the
>>>> version
>>>>>>> field?
>>>>>>> 
>>>>>>> I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so
>>>>> Hibernate
>>>>>>> 3.6.0-Final).
>>>>>>> 
>>>>>>> I've confirmed that Hibernate does throw a
>>>>>>> StaleObjectStateExceptionexception when it tries to make changes to
>>>>>>> the user at the same time, by
>>>>>>> having another page which does, essentially:
>>>>>>> User user = userDAO.findById(1);
>>>>>>> timeProvider.sleep(10000);
>>>>>>> user.setFirstName("something different");
>>>>>>> sessionManager.commit();
>>>>>>> I load it twice, and the second page throws
>>>> StaleObjectStateException.
>>>>>>> 
>>>>>>> Any ideas?
>>>>>> 
>>>>> 
>>>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>> 
>> 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: BeanEditForm for hibernate entity with version field

Posted by Donny Nadolny <do...@gmail.com>.
Hi Taha,

Nice find, that's exactly the problem I have. Unfortunately it didn't seem
to work. I've tried:
tml:
    <t:BeanEditForm object="user" t:id="editUserForm">
        <p:version>
            <t:hidden t:id="versionWhenLoaded"/>
        </p:version>
    </t:BeanEditForm>
java:
    public void setupRender() {
        versionWhenLoaded = user.getVersion();
    }
    public void onPrepareEditUserForm() {
        session.clear();
    }
    @CommitAfter
    public Object onSuccessFromEditUserForm() {
        user.setVersion(versionWhenLoaded);
        return UserIndex.class;
    }

Didn't work. also tried merge:
tml: same as above
    @CommitAfter
    public Object onSuccessFromEditUserForm() {
        user.setVersion(versionWhenLoaded);
        session.merge(user);
        return UserIndex.class;
    }

Again, it just overwrites the changes.

This is a hibernate issue, but it would be nice if Tapestry's BeanEditForm
had an option (maybe even the default?) for proper handling of columns
marked with @Version. I think I'll open an issue for it.

Donny

On Sun, May 29, 2011 at 12:59 PM, Taha Tapestry <ta...@gmail.com>wrote:

> Check this out
>
> https://forum.hibernate.org/viewtopic.php?f=1&t=957807
>
> Sent from my iPhone
>
> On May 29, 2011, at 10:06 PM, Donny Nadolny <do...@gmail.com>
> wrote:
>
> > Hi Taha,
> >
> > That would be a reasonable place to hook it in. However, I'd like to make
> > sure that it would work first, and it seems like in principle it's the
> same
> > as the 4th way I tried (which didn't work): store the current version
> when
> > the form is rendered, then when you save you grab the latest from the
> > database but first set the version to be the version when the form was
> > rendered. I still don't understand why that didn't work.
> >
> > Donny
> >
> > On Sun, May 29, 2011 at 12:24 PM, Taha Hafeez <tawus.tapestry@gmail.com
> >wrote:
> >
> >> Hi Donny
> >>
> >> One way I can think of is extend AbstractSessionPersistentFieldStrategy
> as
> >> is done by EntityPersistentFieldStrategy(tapestry-hibernate)  and store
> >> version in addition to id and type in PersistedEntity and later
> >> while retrieving the value, check the version too
> >>
> >> Take a lot at
> >>
> >>
> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
> >> <
> >>
> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
> >>>
> >>
> >> regards
> >> Taha
> >>
> >>
> >> On Sun, May 29, 2011 at 9:48 PM, Donny Nadolny <donny.nadolny@gmail.com
> >>> wrote:
> >>
> >>> Hi Josh,
> >>>
> >>> Yup, it must be. The question is, how do I stop that? I tried following
> >> the
> >>> example from the jumpstart demo but it didn't work, and I tried setting
> >> the
> >>> version field manually, and it still didn't work (the exact code I used
> >> is
> >>> in the initial email).
> >>>
> >>> On Sun, May 29, 2011 at 12:11 PM, Josh Canfield <
> joshcanfield@gmail.com
> >>>> wrote:
> >>>
> >>>> I would guess that you are pulling the object from the database when
> >> you
> >>>> post the form, and thus editing the current version.
> >>>>
> >>>> I believe is the default behaviour with the tapestry persistent object
> >>>> translator, it stores the type and id in the form.
> >>>>
> >>>> Josh
> >>>> On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com>
> >>> wrote:
> >>>>> I've got a BeanEditForm for my User entity which has a version field:
> >>>>>
> >>>>> @Version
> >>>>> public long getVersion() {
> >>>>> return version;
> >>>>> }
> >>>>> public void setVersion(long version) {
> >>>>> this.version = version;
> >>>>> }
> >>>>>
> >>>>> I've got an admin screen to edit a user, and I would like to make
> >> sure
> >>> I
> >>>>> don't overwrite changes made by the user (they can change their
> >>> password,
> >>>>> for example) or by the application, while I'm on the edit screen.
> >> I've
> >>>> tried
> >>>>> a few things, but I always see the same behavior: any changes in the
> >>>>> database get overwritten when I hit "save" in the BeanEditForm.
> >>>>>
> >>>>> Test 1:
> >>>>> EditUser.tml:
> >>>>> <t:BeanEditForm object="user" t:id="editUserForm"/>
> >>>>>
> >>>>> EditUser.java:
> >>>>> @CommitAfter
> >>>>> public Object onSuccessFromEditUserForm() {
> >>>>> return UserIndex.class;
> >>>>> }
> >>>>>
> >>>>> I open the EditUser page in the browser, I change the user in the
> >>>> database
> >>>>> (increasing the version field by one), then I hit save in the
> >> browser,
> >>>>> expecting Hibernate to throw an exception. Instead, it saves the
> >>> changes,
> >>>>> increasing the version again. Eg I start at version 0, open the page,
> >>>> edit
> >>>>> the db to change a field and set version to 1, then I hit save in the
> >>>>> browser, it clobbers my changes and sets version to be 2.
> >>>>>
> >>>>>
> >>>>> Test 2:
> >>>>> I tried out the code from JumpStart
> >>>>>
> >>>>
> >>>>
> >>>
> >>
> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> >>>>> says it handles versioning. My code now looks like this:
> >>>>> tml:
> >>>>> <t:BeanEditForm object="user" t:id="editUserForm">
> >>>>> <p:version>
> >>>>> <t:hidden value="user.version"/>
> >>>>> </p:version>
> >>>>> </t:BeanEditForm>
> >>>>>
> >>>>> The java code is the same as Test 1.
> >>>>>
> >>>>> Again, the changes get clobbered.
> >>>>>
> >>>>> Test 3:
> >>>>> I noticed that the hidden field didn't have an ID set, so I tried:
> >>>>> <t:hidden value="user.version" t:id="version"/>
> >>>>> Same thing, changes get overwritten.
> >>>>>
> >>>>> Test 4:
> >>>>> Managing the version myself. In the tml I have:
> >>>>> <t:BeanEditForm object="user" t:id="editUserForm">
> >>>>> <p:version>
> >>>>> <t:hidden t:id="versionWhenLoaded"/>
> >>>>> </p:version>
> >>>>> </t:BeanEditForm>
> >>>>>
> >>>>> In java, I have:
> >>>>> @PageActivationContext
> >>>>> private User user;
> >>>>>
> >>>>> @Property
> >>>>> private long versionWhenLoaded;
> >>>>>
> >>>>> public void setupRender() {
> >>>>> versionWhenLoaded = user.getVersion();
> >>>>> }
> >>>>>
> >>>>> @CommitAfter
> >>>>> public Object onSuccessFromEditUserForm() {
> >>>>> user.setVersion(versionWhenLoaded);
> >>>>> return UserIndex.class;
> >>>>> }
> >>>>>
> >>>>> Again, changes get overwritten. I really would expect the last case
> >> to
> >>>> work
> >>>>> - maybe I need to do something special in Hibernate to set the
> >> version
> >>>>> field?
> >>>>>
> >>>>> I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so
> >>> Hibernate
> >>>>> 3.6.0-Final).
> >>>>>
> >>>>> I've confirmed that Hibernate does throw a
> >>>>> StaleObjectStateExceptionexception when it tries to make changes to
> >>>>> the user at the same time, by
> >>>>> having another page which does, essentially:
> >>>>> User user = userDAO.findById(1);
> >>>>> timeProvider.sleep(10000);
> >>>>> user.setFirstName("something different");
> >>>>> sessionManager.commit();
> >>>>> I load it twice, and the second page throws
> >> StaleObjectStateException.
> >>>>>
> >>>>> Any ideas?
> >>>>
> >>>
> >>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: BeanEditForm for hibernate entity with version field

Posted by Taha Tapestry <ta...@gmail.com>.
Check this out

https://forum.hibernate.org/viewtopic.php?f=1&t=957807

Sent from my iPhone

On May 29, 2011, at 10:06 PM, Donny Nadolny <do...@gmail.com> wrote:

> Hi Taha,
> 
> That would be a reasonable place to hook it in. However, I'd like to make
> sure that it would work first, and it seems like in principle it's the same
> as the 4th way I tried (which didn't work): store the current version when
> the form is rendered, then when you save you grab the latest from the
> database but first set the version to be the version when the form was
> rendered. I still don't understand why that didn't work.
> 
> Donny
> 
> On Sun, May 29, 2011 at 12:24 PM, Taha Hafeez <ta...@gmail.com>wrote:
> 
>> Hi Donny
>> 
>> One way I can think of is extend AbstractSessionPersistentFieldStrategy as
>> is done by EntityPersistentFieldStrategy(tapestry-hibernate)  and store
>> version in addition to id and type in PersistedEntity and later
>> while retrieving the value, check the version too
>> 
>> Take a lot at
>> 
>> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
>> <
>> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
>>> 
>> 
>> regards
>> Taha
>> 
>> 
>> On Sun, May 29, 2011 at 9:48 PM, Donny Nadolny <donny.nadolny@gmail.com
>>> wrote:
>> 
>>> Hi Josh,
>>> 
>>> Yup, it must be. The question is, how do I stop that? I tried following
>> the
>>> example from the jumpstart demo but it didn't work, and I tried setting
>> the
>>> version field manually, and it still didn't work (the exact code I used
>> is
>>> in the initial email).
>>> 
>>> On Sun, May 29, 2011 at 12:11 PM, Josh Canfield <joshcanfield@gmail.com
>>>> wrote:
>>> 
>>>> I would guess that you are pulling the object from the database when
>> you
>>>> post the form, and thus editing the current version.
>>>> 
>>>> I believe is the default behaviour with the tapestry persistent object
>>>> translator, it stores the type and id in the form.
>>>> 
>>>> Josh
>>>> On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com>
>>> wrote:
>>>>> I've got a BeanEditForm for my User entity which has a version field:
>>>>> 
>>>>> @Version
>>>>> public long getVersion() {
>>>>> return version;
>>>>> }
>>>>> public void setVersion(long version) {
>>>>> this.version = version;
>>>>> }
>>>>> 
>>>>> I've got an admin screen to edit a user, and I would like to make
>> sure
>>> I
>>>>> don't overwrite changes made by the user (they can change their
>>> password,
>>>>> for example) or by the application, while I'm on the edit screen.
>> I've
>>>> tried
>>>>> a few things, but I always see the same behavior: any changes in the
>>>>> database get overwritten when I hit "save" in the BeanEditForm.
>>>>> 
>>>>> Test 1:
>>>>> EditUser.tml:
>>>>> <t:BeanEditForm object="user" t:id="editUserForm"/>
>>>>> 
>>>>> EditUser.java:
>>>>> @CommitAfter
>>>>> public Object onSuccessFromEditUserForm() {
>>>>> return UserIndex.class;
>>>>> }
>>>>> 
>>>>> I open the EditUser page in the browser, I change the user in the
>>>> database
>>>>> (increasing the version field by one), then I hit save in the
>> browser,
>>>>> expecting Hibernate to throw an exception. Instead, it saves the
>>> changes,
>>>>> increasing the version again. Eg I start at version 0, open the page,
>>>> edit
>>>>> the db to change a field and set version to 1, then I hit save in the
>>>>> browser, it clobbers my changes and sets version to be 2.
>>>>> 
>>>>> 
>>>>> Test 2:
>>>>> I tried out the code from JumpStart
>>>>> 
>>>> 
>>>> 
>>> 
>> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
>>>>> says it handles versioning. My code now looks like this:
>>>>> tml:
>>>>> <t:BeanEditForm object="user" t:id="editUserForm">
>>>>> <p:version>
>>>>> <t:hidden value="user.version"/>
>>>>> </p:version>
>>>>> </t:BeanEditForm>
>>>>> 
>>>>> The java code is the same as Test 1.
>>>>> 
>>>>> Again, the changes get clobbered.
>>>>> 
>>>>> Test 3:
>>>>> I noticed that the hidden field didn't have an ID set, so I tried:
>>>>> <t:hidden value="user.version" t:id="version"/>
>>>>> Same thing, changes get overwritten.
>>>>> 
>>>>> Test 4:
>>>>> Managing the version myself. In the tml I have:
>>>>> <t:BeanEditForm object="user" t:id="editUserForm">
>>>>> <p:version>
>>>>> <t:hidden t:id="versionWhenLoaded"/>
>>>>> </p:version>
>>>>> </t:BeanEditForm>
>>>>> 
>>>>> In java, I have:
>>>>> @PageActivationContext
>>>>> private User user;
>>>>> 
>>>>> @Property
>>>>> private long versionWhenLoaded;
>>>>> 
>>>>> public void setupRender() {
>>>>> versionWhenLoaded = user.getVersion();
>>>>> }
>>>>> 
>>>>> @CommitAfter
>>>>> public Object onSuccessFromEditUserForm() {
>>>>> user.setVersion(versionWhenLoaded);
>>>>> return UserIndex.class;
>>>>> }
>>>>> 
>>>>> Again, changes get overwritten. I really would expect the last case
>> to
>>>> work
>>>>> - maybe I need to do something special in Hibernate to set the
>> version
>>>>> field?
>>>>> 
>>>>> I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so
>>> Hibernate
>>>>> 3.6.0-Final).
>>>>> 
>>>>> I've confirmed that Hibernate does throw a
>>>>> StaleObjectStateExceptionexception when it tries to make changes to
>>>>> the user at the same time, by
>>>>> having another page which does, essentially:
>>>>> User user = userDAO.findById(1);
>>>>> timeProvider.sleep(10000);
>>>>> user.setFirstName("something different");
>>>>> sessionManager.commit();
>>>>> I load it twice, and the second page throws
>> StaleObjectStateException.
>>>>> 
>>>>> Any ideas?
>>>> 
>>> 
>> 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: BeanEditForm for hibernate entity with version field

Posted by Donny Nadolny <do...@gmail.com>.
Hi Taha,

That would be a reasonable place to hook it in. However, I'd like to make
sure that it would work first, and it seems like in principle it's the same
as the 4th way I tried (which didn't work): store the current version when
the form is rendered, then when you save you grab the latest from the
database but first set the version to be the version when the form was
rendered. I still don't understand why that didn't work.

Donny

On Sun, May 29, 2011 at 12:24 PM, Taha Hafeez <ta...@gmail.com>wrote:

> Hi Donny
>
> One way I can think of is extend AbstractSessionPersistentFieldStrategy as
> is done by EntityPersistentFieldStrategy(tapestry-hibernate)  and store
> version in addition to id and type in PersistedEntity and later
> while retrieving the value, check the version too
>
> Take a lot at
>
> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
> <
> https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
> >
>
> regards
> Taha
>
>
> On Sun, May 29, 2011 at 9:48 PM, Donny Nadolny <donny.nadolny@gmail.com
> >wrote:
>
> > Hi Josh,
> >
> > Yup, it must be. The question is, how do I stop that? I tried following
> the
> > example from the jumpstart demo but it didn't work, and I tried setting
> the
> > version field manually, and it still didn't work (the exact code I used
> is
> > in the initial email).
> >
> > On Sun, May 29, 2011 at 12:11 PM, Josh Canfield <joshcanfield@gmail.com
> > >wrote:
> >
> > > I would guess that you are pulling the object from the database when
> you
> > > post the form, and thus editing the current version.
> > >
> > > I believe is the default behaviour with the tapestry persistent object
> > > translator, it stores the type and id in the form.
> > >
> > > Josh
> > > On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com>
> > wrote:
> > > > I've got a BeanEditForm for my User entity which has a version field:
> > > >
> > > > @Version
> > > > public long getVersion() {
> > > > return version;
> > > > }
> > > > public void setVersion(long version) {
> > > > this.version = version;
> > > > }
> > > >
> > > > I've got an admin screen to edit a user, and I would like to make
> sure
> > I
> > > > don't overwrite changes made by the user (they can change their
> > password,
> > > > for example) or by the application, while I'm on the edit screen.
> I've
> > > tried
> > > > a few things, but I always see the same behavior: any changes in the
> > > > database get overwritten when I hit "save" in the BeanEditForm.
> > > >
> > > > Test 1:
> > > > EditUser.tml:
> > > > <t:BeanEditForm object="user" t:id="editUserForm"/>
> > > >
> > > > EditUser.java:
> > > > @CommitAfter
> > > > public Object onSuccessFromEditUserForm() {
> > > > return UserIndex.class;
> > > > }
> > > >
> > > > I open the EditUser page in the browser, I change the user in the
> > > database
> > > > (increasing the version field by one), then I hit save in the
> browser,
> > > > expecting Hibernate to throw an exception. Instead, it saves the
> > changes,
> > > > increasing the version again. Eg I start at version 0, open the page,
> > > edit
> > > > the db to change a field and set version to 1, then I hit save in the
> > > > browser, it clobbers my changes and sets version to be 2.
> > > >
> > > >
> > > > Test 2:
> > > > I tried out the code from JumpStart
> > > >
> > >
> > >
> >
> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> > > > says it handles versioning. My code now looks like this:
> > > > tml:
> > > > <t:BeanEditForm object="user" t:id="editUserForm">
> > > > <p:version>
> > > > <t:hidden value="user.version"/>
> > > > </p:version>
> > > > </t:BeanEditForm>
> > > >
> > > > The java code is the same as Test 1.
> > > >
> > > > Again, the changes get clobbered.
> > > >
> > > > Test 3:
> > > > I noticed that the hidden field didn't have an ID set, so I tried:
> > > > <t:hidden value="user.version" t:id="version"/>
> > > > Same thing, changes get overwritten.
> > > >
> > > > Test 4:
> > > > Managing the version myself. In the tml I have:
> > > > <t:BeanEditForm object="user" t:id="editUserForm">
> > > > <p:version>
> > > > <t:hidden t:id="versionWhenLoaded"/>
> > > > </p:version>
> > > > </t:BeanEditForm>
> > > >
> > > > In java, I have:
> > > > @PageActivationContext
> > > > private User user;
> > > >
> > > > @Property
> > > > private long versionWhenLoaded;
> > > >
> > > > public void setupRender() {
> > > > versionWhenLoaded = user.getVersion();
> > > > }
> > > >
> > > > @CommitAfter
> > > > public Object onSuccessFromEditUserForm() {
> > > > user.setVersion(versionWhenLoaded);
> > > > return UserIndex.class;
> > > > }
> > > >
> > > > Again, changes get overwritten. I really would expect the last case
> to
> > > work
> > > > - maybe I need to do something special in Hibernate to set the
> version
> > > > field?
> > > >
> > > > I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so
> > Hibernate
> > > > 3.6.0-Final).
> > > >
> > > > I've confirmed that Hibernate does throw a
> > > > StaleObjectStateExceptionexception when it tries to make changes to
> > > > the user at the same time, by
> > > > having another page which does, essentially:
> > > > User user = userDAO.findById(1);
> > > > timeProvider.sleep(10000);
> > > > user.setFirstName("something different");
> > > > sessionManager.commit();
> > > > I load it twice, and the second page throws
> StaleObjectStateException.
> > > >
> > > > Any ideas?
> > >
> >
>

Re: BeanEditForm for hibernate entity with version field

Posted by Taha Hafeez <ta...@gmail.com>.
Hi Donny

One way I can think of is extend AbstractSessionPersistentFieldStrategy as
is done by EntityPersistentFieldStrategy(tapestry-hibernate)  and store
version in addition to id and type in PersistedEntity and later
while retrieving the value, check the version too

Take a lot at
https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java
<https://svn.apache.org/repos/asf/tapestry/tapestry5/tags/releases/5.2.5/tapestry-hibernate/src/main/java/org/apache/tapestry5/internal/hibernate/EntityPersistentFieldStrategy.java>

regards
Taha


On Sun, May 29, 2011 at 9:48 PM, Donny Nadolny <do...@gmail.com>wrote:

> Hi Josh,
>
> Yup, it must be. The question is, how do I stop that? I tried following the
> example from the jumpstart demo but it didn't work, and I tried setting the
> version field manually, and it still didn't work (the exact code I used is
> in the initial email).
>
> On Sun, May 29, 2011 at 12:11 PM, Josh Canfield <joshcanfield@gmail.com
> >wrote:
>
> > I would guess that you are pulling the object from the database when you
> > post the form, and thus editing the current version.
> >
> > I believe is the default behaviour with the tapestry persistent object
> > translator, it stores the type and id in the form.
> >
> > Josh
> > On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com>
> wrote:
> > > I've got a BeanEditForm for my User entity which has a version field:
> > >
> > > @Version
> > > public long getVersion() {
> > > return version;
> > > }
> > > public void setVersion(long version) {
> > > this.version = version;
> > > }
> > >
> > > I've got an admin screen to edit a user, and I would like to make sure
> I
> > > don't overwrite changes made by the user (they can change their
> password,
> > > for example) or by the application, while I'm on the edit screen. I've
> > tried
> > > a few things, but I always see the same behavior: any changes in the
> > > database get overwritten when I hit "save" in the BeanEditForm.
> > >
> > > Test 1:
> > > EditUser.tml:
> > > <t:BeanEditForm object="user" t:id="editUserForm"/>
> > >
> > > EditUser.java:
> > > @CommitAfter
> > > public Object onSuccessFromEditUserForm() {
> > > return UserIndex.class;
> > > }
> > >
> > > I open the EditUser page in the browser, I change the user in the
> > database
> > > (increasing the version field by one), then I hit save in the browser,
> > > expecting Hibernate to throw an exception. Instead, it saves the
> changes,
> > > increasing the version again. Eg I start at version 0, open the page,
> > edit
> > > the db to change a field and set version to 1, then I hit save in the
> > > browser, it clobbers my changes and sets version to be 2.
> > >
> > >
> > > Test 2:
> > > I tried out the code from JumpStart
> > >
> >
> >
> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> > > says it handles versioning. My code now looks like this:
> > > tml:
> > > <t:BeanEditForm object="user" t:id="editUserForm">
> > > <p:version>
> > > <t:hidden value="user.version"/>
> > > </p:version>
> > > </t:BeanEditForm>
> > >
> > > The java code is the same as Test 1.
> > >
> > > Again, the changes get clobbered.
> > >
> > > Test 3:
> > > I noticed that the hidden field didn't have an ID set, so I tried:
> > > <t:hidden value="user.version" t:id="version"/>
> > > Same thing, changes get overwritten.
> > >
> > > Test 4:
> > > Managing the version myself. In the tml I have:
> > > <t:BeanEditForm object="user" t:id="editUserForm">
> > > <p:version>
> > > <t:hidden t:id="versionWhenLoaded"/>
> > > </p:version>
> > > </t:BeanEditForm>
> > >
> > > In java, I have:
> > > @PageActivationContext
> > > private User user;
> > >
> > > @Property
> > > private long versionWhenLoaded;
> > >
> > > public void setupRender() {
> > > versionWhenLoaded = user.getVersion();
> > > }
> > >
> > > @CommitAfter
> > > public Object onSuccessFromEditUserForm() {
> > > user.setVersion(versionWhenLoaded);
> > > return UserIndex.class;
> > > }
> > >
> > > Again, changes get overwritten. I really would expect the last case to
> > work
> > > - maybe I need to do something special in Hibernate to set the version
> > > field?
> > >
> > > I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so
> Hibernate
> > > 3.6.0-Final).
> > >
> > > I've confirmed that Hibernate does throw a
> > > StaleObjectStateExceptionexception when it tries to make changes to
> > > the user at the same time, by
> > > having another page which does, essentially:
> > > User user = userDAO.findById(1);
> > > timeProvider.sleep(10000);
> > > user.setFirstName("something different");
> > > sessionManager.commit();
> > > I load it twice, and the second page throws StaleObjectStateException.
> > >
> > > Any ideas?
> >
>

Re: BeanEditForm for hibernate entity with version field

Posted by Donny Nadolny <do...@gmail.com>.
Hi Josh,

Yup, it must be. The question is, how do I stop that? I tried following the
example from the jumpstart demo but it didn't work, and I tried setting the
version field manually, and it still didn't work (the exact code I used is
in the initial email).

On Sun, May 29, 2011 at 12:11 PM, Josh Canfield <jo...@gmail.com>wrote:

> I would guess that you are pulling the object from the database when you
> post the form, and thus editing the current version.
>
> I believe is the default behaviour with the tapestry persistent object
> translator, it stores the type and id in the form.
>
> Josh
> On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com> wrote:
> > I've got a BeanEditForm for my User entity which has a version field:
> >
> > @Version
> > public long getVersion() {
> > return version;
> > }
> > public void setVersion(long version) {
> > this.version = version;
> > }
> >
> > I've got an admin screen to edit a user, and I would like to make sure I
> > don't overwrite changes made by the user (they can change their password,
> > for example) or by the application, while I'm on the edit screen. I've
> tried
> > a few things, but I always see the same behavior: any changes in the
> > database get overwritten when I hit "save" in the BeanEditForm.
> >
> > Test 1:
> > EditUser.tml:
> > <t:BeanEditForm object="user" t:id="editUserForm"/>
> >
> > EditUser.java:
> > @CommitAfter
> > public Object onSuccessFromEditUserForm() {
> > return UserIndex.class;
> > }
> >
> > I open the EditUser page in the browser, I change the user in the
> database
> > (increasing the version field by one), then I hit save in the browser,
> > expecting Hibernate to throw an exception. Instead, it saves the changes,
> > increasing the version again. Eg I start at version 0, open the page,
> edit
> > the db to change a field and set version to 1, then I hit save in the
> > browser, it clobbers my changes and sets version to be 2.
> >
> >
> > Test 2:
> > I tried out the code from JumpStart
> >
>
> http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> > says it handles versioning. My code now looks like this:
> > tml:
> > <t:BeanEditForm object="user" t:id="editUserForm">
> > <p:version>
> > <t:hidden value="user.version"/>
> > </p:version>
> > </t:BeanEditForm>
> >
> > The java code is the same as Test 1.
> >
> > Again, the changes get clobbered.
> >
> > Test 3:
> > I noticed that the hidden field didn't have an ID set, so I tried:
> > <t:hidden value="user.version" t:id="version"/>
> > Same thing, changes get overwritten.
> >
> > Test 4:
> > Managing the version myself. In the tml I have:
> > <t:BeanEditForm object="user" t:id="editUserForm">
> > <p:version>
> > <t:hidden t:id="versionWhenLoaded"/>
> > </p:version>
> > </t:BeanEditForm>
> >
> > In java, I have:
> > @PageActivationContext
> > private User user;
> >
> > @Property
> > private long versionWhenLoaded;
> >
> > public void setupRender() {
> > versionWhenLoaded = user.getVersion();
> > }
> >
> > @CommitAfter
> > public Object onSuccessFromEditUserForm() {
> > user.setVersion(versionWhenLoaded);
> > return UserIndex.class;
> > }
> >
> > Again, changes get overwritten. I really would expect the last case to
> work
> > - maybe I need to do something special in Hibernate to set the version
> > field?
> >
> > I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so Hibernate
> > 3.6.0-Final).
> >
> > I've confirmed that Hibernate does throw a
> > StaleObjectStateExceptionexception when it tries to make changes to
> > the user at the same time, by
> > having another page which does, essentially:
> > User user = userDAO.findById(1);
> > timeProvider.sleep(10000);
> > user.setFirstName("something different");
> > sessionManager.commit();
> > I load it twice, and the second page throws StaleObjectStateException.
> >
> > Any ideas?
>

Re: BeanEditForm for hibernate entity with version field

Posted by Josh Canfield <jo...@gmail.com>.
I would guess that you are pulling the object from the database when you
post the form, and thus editing the current version.

I believe is the default behaviour with the tapestry persistent object
translator, it stores the type and id in the form.

Josh
On May 29, 2011 7:34 AM, "Donny Nadolny" <do...@gmail.com> wrote:
> I've got a BeanEditForm for my User entity which has a version field:
>
> @Version
> public long getVersion() {
> return version;
> }
> public void setVersion(long version) {
> this.version = version;
> }
>
> I've got an admin screen to edit a user, and I would like to make sure I
> don't overwrite changes made by the user (they can change their password,
> for example) or by the application, while I'm on the edit screen. I've
tried
> a few things, but I always see the same behavior: any changes in the
> database get overwritten when I hit "save" in the BeanEditForm.
>
> Test 1:
> EditUser.tml:
> <t:BeanEditForm object="user" t:id="editUserForm"/>
>
> EditUser.java:
> @CommitAfter
> public Object onSuccessFromEditUserForm() {
> return UserIndex.class;
> }
>
> I open the EditUser page in the browser, I change the user in the database
> (increasing the version field by one), then I hit save in the browser,
> expecting Hibernate to throw an exception. Instead, it saves the changes,
> increasing the version again. Eg I start at version 0, open the page, edit
> the db to change a field and set version to 1, then I hit save in the
> browser, it clobbers my changes and sets version to be 2.
>
>
> Test 2:
> I tried out the code from JumpStart
>
http://jumpstart.doublenegative.com.au/jumpstart/examples/easycrud/update/2which
> says it handles versioning. My code now looks like this:
> tml:
> <t:BeanEditForm object="user" t:id="editUserForm">
> <p:version>
> <t:hidden value="user.version"/>
> </p:version>
> </t:BeanEditForm>
>
> The java code is the same as Test 1.
>
> Again, the changes get clobbered.
>
> Test 3:
> I noticed that the hidden field didn't have an ID set, so I tried:
> <t:hidden value="user.version" t:id="version"/>
> Same thing, changes get overwritten.
>
> Test 4:
> Managing the version myself. In the tml I have:
> <t:BeanEditForm object="user" t:id="editUserForm">
> <p:version>
> <t:hidden t:id="versionWhenLoaded"/>
> </p:version>
> </t:BeanEditForm>
>
> In java, I have:
> @PageActivationContext
> private User user;
>
> @Property
> private long versionWhenLoaded;
>
> public void setupRender() {
> versionWhenLoaded = user.getVersion();
> }
>
> @CommitAfter
> public Object onSuccessFromEditUserForm() {
> user.setVersion(versionWhenLoaded);
> return UserIndex.class;
> }
>
> Again, changes get overwritten. I really would expect the last case to
work
> - maybe I need to do something special in Hibernate to set the version
> field?
>
> I'm using tapestry 5.2.4, the tapestry-hibernate dependency (so Hibernate
> 3.6.0-Final).
>
> I've confirmed that Hibernate does throw a
> StaleObjectStateExceptionexception when it tries to make changes to
> the user at the same time, by
> having another page which does, essentially:
> User user = userDAO.findById(1);
> timeProvider.sleep(10000);
> user.setFirstName("something different");
> sessionManager.commit();
> I load it twice, and the second page throws StaleObjectStateException.
>
> Any ideas?