2 Replies Latest reply on Jun 20, 2007 9:02 AM by beligum

    the never ending flow of optimistic locking questions

    beligum

      Hi all,

      This question must be getting boresome to some of you experts here,
      but please help an intermediate developer along with some answers to a few simple questions regarding the subject.

      I use the @Version annotation in my EJB3 entity bean (Seam, JTA), and, while a user edits the bean-contents, it's possible the info is updated through a JMS-callback from an external source.

      Now, I would like to select a few (modified-behind-the-scenes) fields from the database, and let them precede the user-input whatsoever.

      So, when I call my entityManager.flush() method (Seam-managed em), it throws a StaleObjectStateException, because of the JMS-update. In this post (http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3919517#3919517), Gavin points out that it's possible to present the user with the changes made in the DB, by starting up a new context/transaction. He even points out how to do it, but in his own expert-style, the explanation is still quite cryptic to me.

      Can anyone elaborate on the:

      To "get" a new PC/txn to work with, call a session bean in the context of a REQUIRES_NEW transaction (if it is stateful, it needs to be a newly instantiated SFSB).


      This is my relevant code (a conversation-scoped SFSB in a long-running conversation/transaction):
      public String updateEntity()
      {
       ...
       try {
       entityManager.merge(getSelectedInode());
       entityManager.flush();
      
       return "success";
       }
       catch (OptimisticLockException e) {
       VersionConflictManager conflictManager = (VersionConflictManager)Component.getInstance("versionConflictManager");
       File dbFile = (File)conflictManager.getConflictingDbObject(File.class, getSelectedInode().getFileSystemEntity().getId());
       System.out.println("test");
       }
      }
      


      And here's my VersionConflictManager
      @Stateful
      @Scope(CONVERSATION)
      @Name("versionConflictManager")
      public class VersionConflictManager implements Serializable
      {
      
       //-----VARIABLES-----
       @In(create=true)
       EntityManager entityManager;
      
       //-----CONSTRUCTORS-----
       public VersionConflictManager()
       {
       }
      
       //-----GETTERS/SETTERS------
       @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
       public Object getConflictingDbObject(Class entityClass, int id)
       {
       return entityManager.find(entityClass, id);
       }
      
       @Remove
       @Destroy
       public void destroy()
       {
       }
      }
      


      Apparently, I'm missing something, because I get a StaleObjectStateException when I try to instantiate the VersionConflictManager in the catch-code.

      Any help is appreciated,

      bram

        • 1. Re: the never ending flow of optimistic locking questions
          fernando_jmt

          I dealt with this time ago.

          Here you can find a topic related (whether it's of your interest):
          http://forum.hibernate.org/viewtopic.php?t=969898

          After several tries I figured out that the only way (at least for me) to have this working is to have a POJO action and a SFSB DAO.
          POJO action and SFSB DAO are conversational, but the things that makes the difference are:
          * Action must not have the SMPC.
          * The SMPC must be in the SFSB and your update method must be marked (as you did) with TransactionAttributeType.REQUIRES_NEW. With this when the update fails you can read with the same EM (SFSB is requires).


          This works for me, and I think it is a good approach.

          Example of use:
          I start a, at the same conversation trying to edit a contact in its formtime (wherever located) other user opens to edit the same contact, user A saves fine its changes, but when user B tries to save, he is notified (in the same form) that someone else changes its data, and of course such data is displayed in the form.



          HTH.

          • 2. Re: the never ending flow of optimistic locking questions
            beligum

            Hi Fernando, thanks for your response.

            Please let me recapitulate to check if I understand everything correctly.

            So I have a JSF form with a submit-button, linked to the POJO action method.
            This action has an (TransactionAttributeType.REQUIRES_NEW) annotation, so it will start a new transaction. If it's fired, it must get the entity-bean from the SFSB DAO. This will possibly fail, catching the OptimisticLockException when it does.

            Then, the SFSB DAO is (how?) contacted to load the changes from the DB and merge them into the stale object?

            Last paragraph is a bit unclear to me, can you elaborate on this?

            Bram