-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: version field not handled properly if you manually change it
PostPosted: Thu Apr 06, 2006 5:56 pm 
Newbie

Joined: Mon Mar 27, 2006 7:46 pm
Posts: 17
Apparently this must be a really stupid question because no one seems to want to answer it. Maybe someone can take pity on my inferior brain and explain why this this doesn't work as i expect?
please, thank you in advance, hugs, kisses, my first born child; whatever it takes...here is my problem:


I am working on a client/server app with a rich client, using spring/hibernate. I have to deal with concurrent data access and am trying to do so with optimistic locking using hibernate versions. Because I am using a thick client i use a DTOs to pass data back and forth between the server and client. I record the version id in the DTO. To perform an update I:
1)pass the dto back to the server
2) retrieve the hibernate domain object I am updating
3)update the hibernate domain object fields with the new values
4)update the version of the domain object to the original one i recorded in the dto
5)process the update

However when you update the domain object's version manually optimistic locking ceases to work. It is as if it ignores that value entirely, i am guessing it maybe just uses the cached version instead. This causes optimistic locking to fail.

I am really hoping someone can explain to me why this doesn't work. I have searched the bug database and forums and found this question brought up several times, although there is no clear explination as to why this works like this.

It seems like changes to the version field are just ignored for the version check and the cached version is used. I don't understand why this would be, I would think this version field should be treated as a special field and manual changes to it would be considered on the version check. The pattern of having a DTO/view object layer is pretty common in rich clients and so I don't really see why this can be disregarded and I don't see an easy way to work around this.

Clearly, I must be misunderstanding something and I would really appreciate a little help.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 16, 2006 9:20 pm 
Beginner
Beginner

Joined: Fri Aug 05, 2005 3:36 am
Posts: 28
I just read your question. I'm starting on a similar project, with a rich (Eclipse RCP) client and back end data access with Hibernate & Spring.

I don't have an answer, and in fact, I'm a little confused - I'm not sure what you mean when you say that optimistic locking "fails". Maybe because I haven't had to delve deeply into locking issues, or use versioning, I don't understand exactly what is going wrong with your app.

Can you elaborate? I'd like to help, and I have an interest in talking to other folks building apps like yours and the one we're starting on.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 7:22 pm 
Newbie

Joined: Mon Mar 27, 2006 7:46 pm
Posts: 17
ledelste wrote:
I just read your question. I'm starting on a similar project, with a rich (Eclipse RCP) client and back end data access with Hibernate & Spring.

I don't have an answer, and in fact, I'm a little confused - I'm not sure what you mean when you say that optimistic locking "fails". Maybe because I haven't had to delve deeply into locking issues, or use versioning, I don't understand exactly what is going wrong with your app.

Can you elaborate? I'd like to help, and I have an interest in talking to other folks building apps like yours and the one we're starting on.


Well it isn't like the concept of optimistic locking fails it is hibernates implementation of it. i guess what happens is hibernate versioning is automatically done and manually changes to the version field are ignored. Well specifically when hibernate applies the version check it only pays attention to the value of the object in question that is in cache. However when the update is performed it will update the value to the new value you set. Makes no sense at all if you ask me. If hibernate wanted to automate versioning compeltely then they should do so using a proxy and not even have us add a version field to our classes. But since you are required to create a version field i just don't understand why we can't actually use it. Very odd.

The problem is a lot of these java tools like this only pay attention to webapps. In a webapp using the DTO pattern doesn't make much sense except in very odd cases. But with a remote rich client the Transfer Object pattern is sensible. Quite frankly i just don't know how other people handle concurrency issues when using the TO pattern in a rich client. Do you have any insight into general best practices for managing concurrency in a rich client where an update requires 2 transactions really. One to go to the server and get the data the client wants to update. And then eventually a new one has to be created when the client decides they want to update the data?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 11:40 pm 
Regular
Regular

Joined: Wed Jul 07, 2004 2:00 pm
Posts: 64
For our rich client app, we are actually passing the entire entity to the client. Since our client & server communicate using web services (Axis), the Hibernate-specific collection types get converted to plain java.util... types on the client, and stay that way when sent back to the server. In our DAO, we then don't need a session.get. We just do a session.merge(obj). The problem with the version number that you found appears that it is getting the version number from the version that is in the session cache. Two unpleasant ways I know to resolve this - use session.evict(obj) after you do the session.get (but this would have to be done for each object loaded by Hibernate - I don't know if an interceptor would help or if Hibernate would hate the fact that a loaded object is not found in the cache. Probably the later, especially in the case of bidirectional relationships or other circular relationships). Of course, if you're using DTOs, you are probably explicitly going a get for each object to update anyways. Another way is with session.clear after you do all of your session.gets.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 18, 2006 1:19 am 
Newbie

Joined: Mon Mar 27, 2006 7:46 pm
Posts: 17
DWright wrote:
For our rich client app, we are actually passing the entire entity to the client. Since our client & server communicate using web services (Axis), the Hibernate-specific collection types get converted to plain java.util... types on the client, and stay that way when sent back to the server. In our DAO, we then don't need a session.get. We just do a session.merge(obj). The problem with the version number that you found appears that it is getting the version number from the version that is in the session cache. Two unpleasant ways I know to resolve this - use session.evict(obj) after you do the session.get (but this would have to be done for each object loaded by Hibernate - I don't know if an interceptor would help or if Hibernate would hate the fact that a loaded object is not found in the cache. Probably the later, especially in the case of bidirectional relationships or other circular relationships). Of course, if you're using DTOs, you are probably explicitly going a get for each object to update anyways. Another way is with session.clear after you do all of your session.gets.


Thanks for your reply. i have gone with the Transfer Object pattern because of the performance we gain from them and also i love hibernate in it's pure sense which i think from the web perspective is the opensessionview or can be clearly seen in a standalone app. What i mean is the lazy loading is seamless and you don't have to deal with all this helper code to manage objects in and out of sessions. This helper code seems to be quite messy and one of the reasons i chose dtos was to avoid having to get my hands dirty with it. I like DTOs because there is no question about what you get. When you get an evicted hibernate object you have to always be on your guard as some methods that would normally load say collections or do some logic with child relationships won't work. With these truly detached remote applciations this just doesn't seem right to me to give the view an object that has publicly available methods that just won't work. Of course this is my first real hibernate project so i am still very inexperienced and naive to all it's options.

Anyways your suggestions are good ones, they do bring some messiness into the code but they also are practical and possible so it might be worth it. So from your suggestions, i do get the sense that you believe the technique of storing the version in the DTO and reassembling the domain with it when i do an update isn't a horrible idea?

Cause while i am very unhappy with this, i do consider it to be a bug in hibernate, as i continue to analyze the situation i wonder if there is a better overall approach to handle this concurrency issue when using the dto/transfer object pattern. I have asked this question in every possible outlet i can think of but i haven't gotten much back in terms of best practices, probably cause most people, generally coming from a webapp perspective think the Transfer Object pattern is evil. ANwyays anymore feedback would be greatly appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 17, 2006 5:37 pm 
Newbie

Joined: Wed May 17, 2006 5:31 pm
Posts: 1
I changed the access of the version attribute to field, and added a check in the setVersion method to check if the new version is not the same as the old version:

Code:
    public void setVersion(long version)
    {
        if ( this.version != INITIAL_VERSION && this.version != version)
        {
            throw new StaleDataException();
        }
        this.version = version;
    }


This works fine, and I didn't have to change anything but the mapping file and this one method on my base data object. Hope this helps.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.