5 Replies Latest reply on Nov 10, 2005 11:53 PM by gavin.king

    Long Application transactions and Seam

    dtabuenc

      I was looking at the hibernate docs regarding long application transactions here:

      http://www.hibernate.org/42.html#A9

      I am wondering how this is accomplished in Seam? I need to be able to write an application where it takes several request/response cycles to gather enough data to persists a consistent set of objects. Currently the examples show how to use one long-running conversation-scoped EntityManager or Hibernate Session, yet transactions are begun/committed on every request. What seems to be missing is an example of how to configure the flushing so it is done either explicitly, or perhaps automatically at the end of the conversation.

      Can anyone enlighten me what the best way to accomplish something like this would be?

        • 1. Re: Long Application transactions and Seam
          patrick_ibg

          I assume you're talking about a wizard-type behavior where the user enters data, clicks "next", enters more data, etcetera then clicks "confirm".

          In your conversation scoped backing bean, just inject/outject your JSF model beans to take in the model data. You will need to declare @PersistenceContext (EXTENDED). Then for the "confirm" action, just map one of the conversational bean's method as "@End" and do your persisting there.

          You also have to annotate your action listener methods with FlushMode.NEVER (except for the "confirm" action listener) to keep hibernate from auto-flushing until the conversation is ended.

          Keep in mind that conversations time out. If you want data to persist automatically when a conversation times out, you could probably persist in your method annotated @Remove @Destroy (disclaimer: I haven't tried this personally).

          • 2. Re: Long Application transactions and Seam
            rwallace

            On a somewhat similar note, I've noticed that if the conversation times out it is destroyed. One thing I'm not clear on with the extended persistence context and conversations is when transactions are committed and rolled back.

            I'm guessing it's committed when the method annotated with @End exits successfully. But, what if you want to provide a cancel button in the conversation? Would the backing bean action handler for that be a method that calls the method annotated with @Destroy @Remove? Would this cause the transaction to be rolled back and not committed?

            Thanks,
            Rich

            • 3. Re: Long Application transactions and Seam
              rwallace

              On a somewhat similar note, I've noticed that if the conversation times out it is destroyed. One thing I'm not clear on with the extended persistence context and conversations is when transactions are committed and rolled back.

              I'm guessing it's committed when the method annotated with @End exits successfully. But, what if you want to provide a cancel button in the conversation? Would the backing bean action handler for that be a method that calls the method annotated with @Destroy @Remove? Would this cause the transaction to be rolled back and not committed?

              Thanks,
              Rich

              • 4. Re: Long Application transactions and Seam
                gavin.king

                 

                "patrick_ibg" wrote:
                In your conversation scoped backing bean, just inject/outject your JSF model beans to take in the model data. You will need to declare @PersistenceContext (EXTENDED). Then for the "confirm" action, just map one of the conversational bean's method as "@End" and do your persisting there.


                Alternatively, you can use a Seam-managed persistence context, injected using @In. Depends whether you require that the persistence context be open during the view-rendering phase.

                "patrick_ibg" wrote:
                You also have to annotate your action listener methods with FlushMode.NEVER (except for the "confirm" action listener) to keep hibernate from auto-flushing until the conversation is ended.


                This may or may not be necessary, depending upon your requirements. Sometimes you *want* it to flush :-)

                • 5. Re: Long Application transactions and Seam
                  gavin.king

                   

                  "rwallace" wrote:
                  On a somewhat similar note, I've noticed that if the conversation times out it is destroyed.


                  Right, that is the definition of time out ;-)

                  "rwallace" wrote:
                  One thing I'm not clear on with the extended persistence context and conversations is when transactions are committed and rolled back.


                  It depends. If you are using Seam-managed transactions/persistence contexts, Seam commits the transaction at the end of the INVOKE_APPLICATION phase, and again at the end of the RESTORE_VIEW phase. This stuff is described in the docs. This ensures that

                  (a) All changes are committed to the database before sending a response to the user
                  (b) You have an open and working PC/txn while rendering the view, so you don't get LazyInitializationExceptions

                  Otherwise, transaction demarcation follows the usual rules of EJB3.

                  "rwallace" wrote:
                  I'm guessing it's committed when the method annotated with @End exits successfully.


                  Nope. Conversations are destoryed at the end of requests, not when @End methods execute. And TX demarcation is not done using the conversation management machinery.

                  "rwallace" wrote:
                  But, what if you want to provide a cancel button in the conversation? Would the backing bean action handler for that be a method that calls the method annotated with @Destroy @Remove? Would this cause the transaction to be rolled back and not committed?


                  If you want to roll back a transaction, you need to call setRollbackOnly(), or propagate a (non-application) exception out of an EJB call. However, you do not usually need to roll back the database transaction in order to abort a conversation. You just need to end the conversation.

                  When using Seam-managed PC/txn:

                  persistence context scope == conversation
                  transaction scope == request (approximately)

                  When using container-managed PC/txn:

                  persistence context scope == SFSB instance (probably == conversation)
                  transaction scope == SFSB method invocation (<request)

                  Does that make sense?