-
1. Re: Rollback exceptions without ending the conversation
gavin.king Mar 7, 2007 12:10 PM (in response to enazareno)JPA does not support recovery of the persistence context when a txn fails.
You should always end the conversation after you fail to access the database. Otherwise you can be left with inconsistent state b/w memory and the database. -
2. Re: Rollback exceptions without ending the conversation
enazareno Mar 7, 2007 7:00 PM (in response to enazareno)Hi Gavin,
Thanks for the reply. Common database errors like constraints, uniqueness etc. So what is your recommended approach in this case?
1. Provide custom validation interceptor to handle chcking of the constraints. One needs to anticipate all the possible database errors though.
Or
2. Make the error happen, end the current conversation and provide a way to recreate back the conversation and position to where you left off (Sounds like jbpm doesn't it?). But its a normal CRUD and not a worfklow app so I think a business process is an overkill. Is there a way we can re-create the conversation? Is this what propagation does?
Regards,
Elmo -
3. Re: Rollback exceptions without ending the conversation
cja987 Mar 7, 2007 7:22 PM (in response to enazareno)Propagation won't recreate the conversation, and your conversation is still active if you didn't end it yourself. However, your entityManager is toast, so you need a new one, and that's usually done with a new conversation. It should be possible to recreate the entityManager within the current conversation and merge any detached instances into the new one, but the details elude me (hell, I can't even manage to use merge() correctly).
I do number 1, and yeah I find it a maddening reminder of both JPA and JTA's inadequacies (JTA because it doesn't support nested transactions, which would more or less fix this problem). -
4. Re: Rollback exceptions without ending the conversation
enazareno Mar 7, 2007 9:37 PM (in response to enazareno)Hi,
Thanks for pointing that out. Here is my sample code@In EntityManager em; @In UserList userList; boolean isnew; @Out User user; @Begin( id="#{user.id}" ) public void edit() { user = em.merge(userList.getSelectedUser()); isnew = false; } @End public void save() { if(isnew) em.persist( user ); else em.merge( user ); userList.refresh(); //can also use event for this isnew = false; }
The conversation actually ends when I press save. However it is my understanding that you cant put a try catch inside the save because the entity manager is flushed only when it ends so at this point there is no error yet? Is this correct? Let's say I'll just accept that limitation and I want to create another conversation instead. I've already specified the conversation id, can't I just use that as a reference to my new conversation that I will create? Or is there no chance to get back to that conversation?
I agree with you, this seems like a complex solution and I'd prefer number one too. It just kinda reminds me of the old days developing Clipper applications where you manage this kind of validation yourself. With client-server development, you are encouraged to let the database handle this. Now its back. Life's a cycle isnt it? so retro :)
Regards,
Elmo
-
5. Re: Rollback exceptions without ending the conversation
cja987 Mar 8, 2007 1:23 AM (in response to enazareno)A conversation isn't normally destroyed when an exception is thrown out of an @End method, so you should be able to redirect to an error page that lets you get back into your edit screen.
If you prefer to catch inside the save method, you should have save() return a String for the outcome, and return null if you don't want it to actually end. It's in the docs for the @End annotation, at http://docs.jboss.com/seam/latest/reference/en/html/annotations.html
Of course if you catch the exception in the save method, you still have to do the recovery bits. If you make it actually work, I'd love to see what the solution was.