-->
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.  [ 1 post ] 
Author Message
 Post subject: FYI: Handling concurrency errors (StaleObjectStateException)
PostPosted: Fri Mar 26, 2004 9:39 am 
Beginner
Beginner

Joined: Wed Nov 26, 2003 11:53 am
Posts: 26
Location: Netherlands
Hello all,

I thought I'd share my experiences with the community: for a lot of issues there are only questions, but few answers in the forums...

A StaleObjectStateException does not mean that there is something "wrong", it is a logical extension of optimistic locking. When a version check fails becaiuse somebody else updated an object, you'll get this error. So all you need to do is handle StaleObjectStateException? Well, yes, but there are one or two things that you'll need to think of.

Here's an example of handling code in a Struts action. Note that a better solution is to have the handling code somewhere in a more general location. I've commented the code for your convenience...

Code:
   public ActionForward save(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception
   {
      if (!isCancelled(request))
      {
         ActionErrors errors = new ActionErrors();
         SubscriptionDataForm form = (SubscriptionDataForm) actionForm;

         // Facade uses a stateless session bean behind the scenes.
         // Each call to the facade means one transaction.
         // The Hibernate session lives as long as the facade.
         ServerAdminFacade facade = new ServerAdminFacade();

         Subscription subscription = facade.findSubscriptionByNumber(form.getNumber());
   
         if (subscription == null)
         {
            subscription = new Subscription();
         }

         // Inspired by Cocoon Woody: a Binding is a class for copying data to and from a form from a model object.   
         SubscriptionDataFormBinding binding = new SubscriptionDataFormBinding();
         // Load reference data
         binding.loadLicenseTypes(facade, form);
         // Copy form values into the model object
         binding.saveFormToModel(form, subscription);
         try
         {
            // Passing the subscription back through the return value has to do with an EJB thing: changes
            // to parameters are lost.
            // This is a call that may lead to a StaleObjectStateException!
            subscription = facade.saveSubscription(subscription);
            facade.flush();

            // Second step: add some more data.
            Set duplicates = facade.checkIButtons(subscription, form.getIButtons());
            Set syntaxErrors = facade.validateIButtons(subscription, form.getIButtons());
            Set lengthErrors = facade.validateIButtonLengths(subscription, form.getIButtons());
            
            binding.setIButtons(subscription, form.filterIButtons(duplicates, syntaxErrors));
            binding.setIButtons(subscription, form.filterIButtons(null, lengthErrors));
            
            // This is another call that may lead to a StaleObjectStateException!
            subscription = facade.saveSubscription(subscription);
         }
         catch (ApplicationException ex)
         {
            if (ex.getCause() instanceof StaleObjectStateException)
            {
               // Tell user to try again
               errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("errors.concurrency"));
               saveErrors(request, errors);
               
               // THIS IS IMPORTANT: in case of an error, your "old" session will not be used anymore,
               // and you'll get a net.sf.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
               // because the "old" object will somehow be associated with the "old" and the "new" session...
               subscription = facade.findSubscriptionByNumber(form.getNumber());
            }
            else
            {
               throw ex;
            }
         }
         
         // Would lead to net.sf.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
         // with a StaleObjectStateException (or any Hibernate exception for that matter) and NO call to reload a new subscription object.
         binding.loadFormFromModel(form, subscription);
         binding.loadLicenseTypes(facade, form);
   
         return mapping.findForward(ServerAdminConstants.FORWARD_SUCCESS);
      }
      else
      {
         return mapping.findForward(ServerAdminConstants.FORWARD_START);
      }
   }


HTH!


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

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.