views:

244

answers:

2

We are using Wicket with Hibernate in the background.

As part of out UI we have quite long running conversations spanning multiple requests before the updated information is written back to the database.

To avoid getting hibernate errors with detached objects we are now using value objects to transfer info from the service layer to Wicket.

However we now end up with an explosion of almost the same objects :

e.g.

  • Answer (mapped entity saved in hibernate)
  • AnswerVO (immutable value object)
  • AnswerModel (A mutable bean in the session domain)
  • IModel wrapped Wicket Model
  • and usually this gets wrapped in a CompoundPropertyModel

This plumbing becomes exponentially worse when collections to other objects are involved in the objects.

There has to be a better way to organize this.

Can anyone share tips to make this less onerous?

Maybe make the value objects mutable so we can remove the need for a seaprate backing bean in Wicket?

Use the entity beans but absolutely make dead-certain they are detached from hibernate. (easier said than done)?

Some other tricks or patterns?

+1  A: 

the usual solution would be the open session in view "pattern", see e.g. osiv with wicket

i have no good experiences with OSIV, so i rather advise to set transaction boundaries below the GUI layer and solve the infamous lazyInitializationException with clever planned data retrieval in business or service layer

Michael Lange
This confirms my current gut feeling to create a "robust" service layer which lets no hibernate influences escape.
Peter Tillemans
+1  A: 

Use OpenSessionInViewFilter from Spring. This will help you in creating a hibernate session per-request. However, it only opens a read-only session. To perform any write operation to your entity beans, I would recommend to start a hibernate transaction (you can use TransactionTemplate from Spring for this). There are other methods to perform a write operation, but I found this was easiest for me.

Now, to clean up your beans, here's what I tend to do

  1. Only have entity beans
  2. If you want to go stateless, only save the entity bean's key into the session and reload the bean on every single request in your multi-request conversation
  3. To remain stateful is a little tricker. You need to detach your entity bean before the beans are persisted into your session store, and you'll need to re-attach it back when the subsequent requests are performed. Naturally, if someone had updated the entity in the background, your will have to deal with it in your application (i.e. informing the user that "the database has been modifed externally, etc").

I would go with (2) above as it is pretty simple and would work on most cases. Its not recommended when your persistent beans are modified by two separate sessions as you'll end up overriding the previous updates.

Hibernate do have some documentation on dealing with detached objects.

Roopinder
Thanks, for your detailed answer. I did not think to use the TransactionTemplate, and I am quite sure this is going to help in a particularly pesky and always returning problem.Unfortunately we ended up in option 3 where data entry happens over multiple request which can be 'saved' or 'cancelled'. The worst part is that this way of working is not what the users need (although they ask for it) because its used with mutiple people from different locations on the same entities at the same time and NEED real-time updates, not the state at the beginning of the conversation.
Peter Tillemans