5 Replies Latest reply on Jul 10, 2006 1:09 PM by Gavin King

    Long running transaction - multiple save points?

    Andrew Apprentice

      I am doing something that doesn't seem to fit too well with the framework. I have a set of user edit pages. I wanted to let the user go to a few popup windows to edit certain areas of the user's data. Then when the user decides the changes are good, commit them all at the same time.

      That basic premise is working, what I am running into is a problem with trying to have multiple "save points". I was trying to make it so in each popup, the user would be able to click apply or cancel. The apply would apply all the changes on the popup to the object, and the cancel to rollback the changes for that popup only. Each popup controls not only single properties (username, first name, etc.), but may also contain lists (phone numbers, etc.). So when canceling the dialog, it may be adds and deletes of children that I want to undo.

      I tried using a clone via object i/o stream to implement this, but the clones were not happy with hibernate/ejb3:
      org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: mypackage.User.emails, no session or session was closed

      Is there a "clean" way of doing this? I wanted to have these multiple save points as the user may be new and cannot be saved until all the information is complete.

      Is there some way to nest transactions, create save points in a transaction, or somehow clone objects with the EntityManager that I missed (I can't use refresh as that would rollback all my changes, not just one popup's worth)?

      If I can't get this to work, I will just remove the popup cancel/rollback functionality, but it would be great for my users if I can manage it.

      BTW, all my functionality for editing the user is in one EJB (it handles all the back-end functionality for each popup, so I don't think I can nest conversations as there only seems to be one per bean allowed).

      Thanks,
      Andrew

        • 1. Re: Long running transaction - multiple save points?
          Andrew Apprentice

          Just some more information,

          I tried using merge to re-associate the object with the manager. The problem is that I have no active transaction, because I don't want the data committed yet (I using SeamExtendedManagedPersistencePhaseListener)

          So when I called my method with NOT_SUPPORTED transaction type, I got an error. Method:

          private void beginEditProperties()
           {
           if (clone != null)
           {
           if (editingUser.getId() != null)
           editingUser = entityManager.merge(clone);
           clone = null;
           }
          
           try
           {
           clone = ObjectUtils.deepClone(editingUser);
           }
           catch (Exception ex)
           {
           handleActionError(ex);
           }
           }
          


          Exception:
          Caused by: java.lang.IllegalStateException: No transaction.
           at org.jboss.tm.TxManager.setRollbackOnly(TxManager.java:751)
           at org.hibernate.ejb.AbstractEntityManagerImpl.markAsRollback(AbstractEntityManagerImpl.java:392)
           at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:545)
           at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:567)
           at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:210)
          ...
          


          So I seem to be stuck as I can't start a transaction, as EntityManager has no way of saying not to flush on this JSF action and I need the transaction to re-associate my clone with the entity manager in order to lazy load my children objects that may not have been loaded yet.

          • 2. Re: Long running transaction - multiple save points?
            Pete Muir Master

            Do the popups share entitiy beans or are entities attached to only one popup?

            • 3. Re: Long running transaction - multiple save points?
              Andrew Apprentice

              The User class is shared across popups. The child objects are only used in one popup.

              I think I have an easier solution though after some thought. I think I will make editing user changes immediately saved (save per page) and new users, just queue all the changes to the end and have one save, but no cancel button.

              That will fit in the web-page style editing much easier.

              • 4. Re: Long running transaction - multiple save points?
                Pete Muir Master

                I think I understand what you're trying to design (perhaps I don't thought ;)

                I do something similar: For new users/whatever I have a wizard that includes the relevant detail page for that step. For editing I use a tabbed panel (tomahawk atm) and include the detail page (same as included for wizard) for each tab.

                I persist the new user when the finish button is clicked, canel is easy here - just abandon the conversation.

                I set the FlushMode to never for the edit, and only flush when apply or save is clicked (so cancel is just a navigation).

                I use cascade so you don't need to choose whether to persist or not objects associations.

                BUT I never worked out a way to do popups elegantly!

                • 5. Re: Long running transaction - multiple save points?
                  Gavin King Master

                  I think your approach with merge() in a non-transactional method is the correct one. HEM should _not_ throw an exception if the PC is an extended PC. So either (a) your PC is not an extended PC and it should be or (b) this is a bug in HEM.