1 2 Previous Next 17 Replies Latest reply on May 5, 2007 5:07 AM by fabboco

    Nested conversations and transaction management

    fabboco

      Hi,

      I have a couple of SFSB:

      
      @Stateful
      @Name("A")
      @Scope(ScopeType.CONVERSATION)
      @Transactional
      public class ABean implements Serializable, A
      {
       @PersistenceContext(type = PersistenceContextType.EXTENDED)
       private EntityManager em;
      
       @End(beforeRedirect=true)
       @Rollback
       public String cancel()
       {
       return "/AList.xhtml";
       }
      
      
       @Begin(nested=true)
       public String initCreate()
       {
       ....
      
       return "/A.xhtml";
       }
      
       @End(beforeRedirect=true)
       public String initCreate()
       {
       ....
      
       return "/ListA.xhtml";
       }
      }
      
      @Stateful
      @Name("B")
      @Scope(ScopeType.CONVERSATION)
      @Transactional
      public class BBean implements Serializable, B
      {
       @PersistenceContext(type = PersistenceContextType.EXTENDED)
       private EntityManager em;
      
       @End(beforeRedirect=true)
       @Rollback
       public String cancel()
       {
       return "/BList.xhtml";
       }
      
      
       @Begin(nested=true)
       public String initCreate()
       {
       ....
      
       return "/B.xhtml";
       }
      
       @End(beforeRedirect=true)
       public String initCreate()
       {
       ....
      
       return "/ListB.xhtml";
       }
      }
      
      


      I do the following actions:

      1) I call a.initCreate(); (a is an instance of A, a long running conversation is still active before this call, say #1)
      1.a) The page A.xhtml is shown
      1.b) a new nested conversation is created, say #2

      2) from inside the A page I call b.initCreate() (it is opened in a popup)
      2.a) The page B.xhtml is shown
      2.b) a new nested conversation is created, say #3

      3) from inside the B page I call b.processCreate
      3.a) conversation #3 is closed
      3.b) a new B object is create and stored into the database

      4) from inside the A page I call a.cancell
      4.a) conversation #2 is rolled back
      4.b) no new a object is create but the b object is present into the database

      From this behavior I presume that the parent conversation and the nested conversation have two different database transaction and that the transaction related to the nested conversation is always committed on nested conversation closure even thought the parent conversation (and the related database transaction) could be rolled back.

      Am I right ?

      Can I change this behavior in some way ?

      I wonder why the nested conversation doesn't nest the database transaction too.

      Thank you to everybody for his help.

      Regards

      Fab.

        • 1. Re: Nested conversations and transaction management
          christian.bauer

          If you use TransactionalSeamPhaseListener, the transaction demarcation is decoupled from conversations and bean calls, it's simply bound to the JSF lifecycle. You should use it if you don't.

          • 2. Re: Nested conversations and transaction management
            fabboco

            Christian,

            thank you very much for your promptly reply.

            I am using TransactionalSeamPhaseListener.

            I can't understand what you mean saying:


            If you use TransactionalSeamPhaseListener, the transaction demarcation is decoupled from conversations and bean calls, it's simply bound to the JSF lifecycle


            Can you give me more details ?

            Fab.

            • 3. Re: Nested conversations and transaction management
              christian.bauer

              Read the documentation about TransactionalSeamPhaseListener in the reference to get more details, here is the Javadoc:

              * Transaction management for extended persistence contexts.
              * A transaction spans the restore view, apply request values, process validations,
              * update model values and invoke application phases. It is committed when
              * invoke application is complete, or renderResponse() or responseComplete() is
              * called. A second transaction spans the render response phase.

              And something is not right with your code: @Transactional is for JavaBeans, you are using EJBs. If you want to change the transaction assembly, use @TransactionAttribute for EJBs. If you just want to say "I want a transaction when a method is called", you don't need any annotation, that's the job of the TSPL.

              Finally, I would not use @Stateful EJBs and extended persistence contexts, unless you really understand all the implications of the persistence propagation rules - which is quite complex. I recommend you either read my book or that you read the Seam reference docs and use a Seam-managed persistence context. I've described the differences a few times in the past in detail, search the forum.

              • 4. Re: Nested conversations and transaction management
                fabboco

                Christian,

                thank you again, but I can't solve the problem.

                1) @Transactional - My mistake, it was there for a previous experiment. Removed

                2) Switched to Seam-managed persistence context, nothing changed

                3) Now, each method has @TransactionAttribute(TransactionAttributeType.REQUIRED), nothing changed. TransactionAttributeType.REQUIRED should mean 'if a transaction exists join it' and then 'if the transaction you joined is rolled back, your changes are rolled back'. TransactionAttributeType.REQUIRED should be the default so the annotation should not have any effect.

                Relation between conversation and transaction is a main topic for developing real applications. I have been reading seam documentation for long time but ....

                Could you please answer to these questions ?

                a) Is the database transaction started when the conversation starts, committed when the conversation is ended (@End) and rolled back if the conversation is rolled back (@Rollback) ?
                This should be true, since if I call a.cancel() from the A page, the database is not changed

                b) When a nested conversation is started, the database transaction is nested ?
                If not so (a new database transaction is started) when the nested transaction is closed, the database transaction is committed and there is no way to have changes undone

                Thank you for your patience

                Fab.

                • 5. Re: Nested conversations and transaction management
                  fabboco

                  Now I am really confused.

                  First of all let me update the sample code.

                  @Stateful
                  @Name("A")
                  @Scope(ScopeType.CONVERSATION)
                  public class ABean implements Serializable, A
                  {
                   @In
                   private EntityManager em;
                  
                   @In(create = true)
                   @Out(required = false)
                   A a; // A entity bean
                  
                   @End(beforeRedirect=true)
                   @Rollback
                   public String cancel()
                   {
                   return "/AList.xhtml";
                   }
                  
                  
                   @Begin(nested=true)
                   @TransactionAttribute(TransactionAttributeType.REQUIRED)
                   public String initCreate()
                   {
                   ....
                  
                   a = new A();
                  
                   return "/A.xhtml";
                   }
                  
                   @End(beforeRedirect=true)
                   @TransactionAttribute(TransactionAttributeType.REQUIRED)
                   public String processCreate()
                   {
                   ....
                  
                   a = em.merge(a);
                  
                   return "/ListA.xhtml";
                   }
                  }
                  



                  I have traced what happens at database level and I discovered that the database transaction is started at the merge statement and committed after that the method is ended. I presumed at the end of the conversation.

                  SURPRISE - SURPRISE !!!

                  I removed @End(beforeRedirect=true) from the processCreate() method.
                  The database transaction is STILL started at the merge statement and STILL committed after that the method is ended.

                  What is going on ? I thought that using a long-running conversation I was able to manage more http requests before actually write to the database and I thought that the database transaction was committed only at the end of the method annotated with @End.

                  Probably I am wrong !

                  Please, can anyone explain to me which is the relationship between conversation and transaction ? Is this stuff documented somewhere ?

                  Thanks

                  Regards

                  Fab.


                  • 6. Re: Nested conversations and transaction management
                    christian.bauer

                    OK, I really have no idea what you are doing, your code does not match your description. Stop using stuff like nested conversations until you have the basics working.


                    a) Is the database transaction started when the conversation starts, committed when the conversation is ended (@End) and rolled back if the conversation is rolled back (@Rollback) ?
                    This should be true, since if I call a.cancel() from the A page, the database is not changed


                    No, this is not true. Read my first two replies: if you use TransactionalSeamPhaseListener your conversation demarcation does not influence transactions in any way. It does not matter that there is a long-running conversation. A JSF requests is wrapped in a system transaction (in two transactions, in fact). @Rollback does a rollback of the transaction, again, not related to conversations.


                    b) When a nested conversation is started, the database transaction is nested ?
                    If not so (a new database transaction is started) when the nested transaction is closed, the database transaction is committed and there is no way to have changes undone


                    There are no nested transactions in Java EE.



                    • 7. Re: Nested conversations and transaction management
                      fabboco

                      Christian,

                      tank you very much for your answers. Now everything is clearer.

                      Since every call to a SFSB method is performed into a different database transaction, my final question is how can I manage transactions so that two or more SFSB methods are executed into the same transaction ?


                      What I am trying to do is very simple:

                      1) I start an input form for the Entity Bean A

                      2) From the input form I open a pop up window in which I can choose items from EB B or I can create new items

                      3) When I close the pop up the A form is update (so that the back entity bean)

                      4) If I cancel the operation I would like that the B items would not be saved to the database

                      I though that a long-running conversation would be the solution. It is not.

                      Now, I still think that I have to execute A and B methods into a single (user) transaction but where I can open and commit it ?

                      Any other solution that doesn't involve an explicit transaction management ?


                      Regards

                      Fab.

                      • 8. Re: Nested conversations and transaction management
                        christian.bauer

                         

                        Since every call to a SFSB method is performed into a different database transaction, my final question is how can I manage transactions so that two or more SFSB methods are executed into the same transaction ?


                        If I tell you again to use TransactionalSeamPhaseListener, to do exactly that, will you use it now? :)


                        • 9. Re: Nested conversations and transaction management
                          fabboco

                          Christian,

                          if you tell me to use TransactionalSeamPhaseListener again, I say you again that I am using it :)

                          Nevertheless, each method call issue a begin/commit transaction to the database. To me this means that each method is called into a different transaction. Isn't it ?

                          Probably, I had to be more clear:

                          my final question is how can I manage transactions so that two or more SFSB methods, coming from different http requests (either in the same conversation or in nested conversations), are executed into the same transaction ?


                          Thank you again for your help.

                          Regards

                          Fab

                          • 10. Re: Nested conversations and transaction management
                            christian.bauer

                             


                            Nevertheless, each method call issue a begin/commit transaction to the database. To me this means that each method is called into a different transaction. Isn't it ?


                            This can't be the case if you use TSPL. EJB method calls with no transaction annotation will just join the existing transaction(s) controlled by the TSPL.


                            • 11. Re: Nested conversations and transaction management
                              christian.bauer

                              System transactions do not (this is not 100% but I'm not going to explain the special cases) span HTTP requests. TSPL uses two transactions for each JSF request.

                              • 12. Re: Nested conversations and transaction management
                                fabboco

                                Christian,

                                thank you for your explanations.

                                I have some more questions:

                                1) Can you give me some reference to learn more about transactions that span HTTP requests ?

                                2) Can @Begin(flushMode=MANUAL) help me ?

                                3) Why seam has not options that let user manage the transactions as needed ? Am I using seam in the wrong way ?

                                Regards

                                Fab.

                                • 13. Re: Nested conversations and transaction management
                                  christian.bauer

                                   


                                  1) Can you give me some reference to learn more about transactions that span HTTP requests ?


                                  This is extremely rare, it involves suspension of the transaction on a Java EE server. I'd rather not give you any references on this because you will certainly try it - without understanding why you (don't) need it. Forget that I even mentioned it :)


                                  2) Can @Begin(flushMode=MANUAL) help me ?


                                  Of course, the unflushed persistence context can be held for several requests and is then flushed in the last request of a conversation. This is the basic conversational programming model in Seam, widely documented.


                                  3) Why seam has not options that let user manage the transactions as needed ? Am I using seam in the wrong way ?


                                  Yes, you have a fuzzy picture about what system transactions are and now look for the wrong solutions. Seam and Java EE have _all_ options you need to handle transactions. Don't jump into the middle trying to use nested conversations, long-running persistence contexts, and complex EJB/transaction assemblies, without understanding the basics first.


                                  • 14. Re: Nested conversations and transaction management
                                    fabboco

                                    Christian,


                                    Yes, you have a fuzzy picture about what system transactions are and now look for the wrong solutions. Seam and Java EE have _all_ options you need to handle transactions. Don't jump into the middle trying to use nested conversations, long-running persistence contexts, and complex EJB/transaction assemblies, without understanding the basics first.


                                    let me say that it is too strong !!

                                    You say, don't, don't, don't ....

                                    This is what I am trying to do


                                    What I am trying to do is very simple:

                                    1) I start an input form for the Entity Bean A

                                    2) From the input form I open a pop up window in which I can choose items from EB B or I can create new items

                                    3) When I close the pop up the A form is update (so that the back entity bean)

                                    4) If I cancel the operation I would like that the B items would not be saved to the database


                                    It's fuzzy ?

                                    In my fuzzy understanding of transactions I know that, if all the previous operations are performed into ONE SINGLE transaction (system, database, whatever you like to call) I can cancel the operation and have the database in a consistent state.

                                    Nothing more, nothing less.


                                    Seam and Java EE have _all_ options you need to handle transactions.



                                    Regards

                                    Fab

                                    1 2 Previous Next