12 Replies Latest reply on Apr 27, 2009 6:24 PM by brandonsimpson

    Confused with conversation and transaction demarcation

    frer

      Hello,


      Please bare with me as I know this might be a redundant question but I have been looking over books and documentation and can't seem to understand the basics of transaction demarcation with seam.


      Here is my use case: I have a web page on which I have a report template (where users can define which query fields they want, which output fields they want.  They then have 2 actions: Save and Generate.  The save will allow the user to save the report in the database to be loaded at a future time.  The generate button will simply generate the report on click.


      I am using rich faces so the user never actually leaves the page.


      Here are my questions:


      1) What scope should I use?  I was thinking a conversation because I want the user to be able to have many tabs loading a different report.  Is it a long running conversation or not (keeping in mind that I use richfaces)?


      2) When I use a conversation with a @Begin and a @End, the transaction is committed even though I have not yet called the @End.  Why is that? I thought the commit was only called if the @End is specified.  Is there something I misunderstood?


      3) If I don't use the @Begin and @End (long running conversation) in a Conversation scope, how is the transaction handled? 


      3.1) For instance, if I use a Stateful EJB, can I simply use the @TransactionAttribute(TransactionAttributeType.REQUIRED) annotation to control when the commit will be called (on which method). 


      3.2) If not using a Stateful EJB I have seen the @Transactional annotation but I read it does not work on method demarcation...so how can I specify which methods commits the transaction?


      I know these are a lot of questions but I think you figured out by now that I'm quite confused.  I've been trying multiple different things but always get unexpected results.


      Thanks a lot,


      Francois

        • 1. Re: Confused with conversation and transaction demarcation

          I'd love to know the answers to all your questions.


          I can say that:



          1. If it is all in the same page, use ScopeType.PAGE you will save yourself a lot of conversation headaches.

          2. The entityManager, transactions and @Begin and @End are all subtly related, but not completely, ending a Conversation will not commit your transaction, but it could rollback it, and it may, or may not affect you entityManager. (Please do not ask me how are they related, I do not really get it, and it gets even worse with nested transactions and the @PerNestedConversation annotation, please don't event go there)

          3. Too complicated. Don't really get it too... You can use @TransactionAttribute to control transactions, that I know.



          I am confused too, just remember, the conversation the entitymanager and transactions are subtly but incomprehensibly related, if one day you really get it, please explain it here. ;-)


          • 2. Re: Confused with conversation and transaction demarcation
            frer

            Hey Francisco


            Thanks for your input.  I'm happy to see I'm not the only one having trouble with this.


            Here is a little more info we were able to gather:


            1- We are currently using the long-running conversation.


            2- On the @Begin we put FlushMode:Manual so that the objects don't automatically get persisted to the database.  In the save method we have put a getSession().flush() in order to persist the data (no commit necessary).  THe @End seems to have no incidence though (at least for the conversation). For now I just omit it so that the objects are always alive on my page...but I find this very counter intuitive.


            3- I wish I could use that instead of using the getSession().flush().  To me that would be great.  I would be in a manual flush (by my annotation) and would annotate the method that would commit the code.  It is unfortunately not how it works...


            Anybody have any explanation for all this? I would really like to understand it better because we are currently doing some trial and error and not understanding the bottom of it.


            Thanks a lot,


            François

            • 3. Re: Confused with conversation and transaction demarcation
              gonorrhea

              After 2 yrs of professional Seam dev, I have learned that understanding transactions, conversations, and bijection is extremely crucial to your success as a Seam dev (among a long list of other technologies/details/concepts).


              For example, consider this excerpt from Seam in Action:



              Hibernate’s MANUAL flush mode ensures that the persistence context is only flushed
              when a call is made to the flush() method on the persistence manager API (beanmanaged
              flushing). This mode gives you the flexibility to take your persistence context
              in and out of transactions as you please without risking a premature flush.



              WARNING: If the entity identifier is generated during an insertion (i.e., auto-increment
              column), then even with manual flushing, a flush occurs after a call
              to persist(). This is necessary since each managed entity in the persistence
              context must be assigned an identifier. To avoid the flush, you
              need to set the id-generation strategy to sequence (not identity).


              We use MSSQL, not Oracle, so I'm not even sure if we can use sequences...


              1) if you're using SFSB, beware: Caused by: java.lang.IllegalArgumentException: Stateful session beans may not be bound to the PAGE context.  Conversation scope is the default for SFSB, typically it's recommended to use that to model a conversation.


              2) In EJB3, the default TransactionAttributeType is REQUIRED.  If you're using CMT, the tx begins when the method begins and commits if the method completes successfully.  This happens automatically with CMT.  The alternative is BMT and you get fine-grained, programmatic control of your tx's but it's more code.


              3) I'm pretty sure that @Begin/@End don't have anything to do (AFAIK) with tx semantics, they just demarcate the promotion (@Begin) of a temporary conversation to a LRC, and the end (demotion to temp conversation) of a LRC.  Watch out for the beforeRedirect=true with @End (default is false so FacesMessages will display when page redirects).  Also, the method annotated with @Destroy in your SFSB will execute after the @End method completes.


              IMHO, you need to read the conversation and tx sections of Seam in Action, it goes into very great depth and will likely answer most of your questions.

              • 4. Re: Confused with conversation and transaction demarcation

                Arbi Sookazian wrote on Apr 24, 2009 17:59:


                WARNING: If the entity identifier is generated during an insertion (i.e., auto-increment
                column), then even with manual flushing, a flush occurs after a call
                to persist(). This is necessary since each managed entity in the persistence
                context must be assigned an identifier. To avoid the flush, you
                need to set the id-generation strategy to sequence (not identity)






                Or you can switch to another JPA provider ;-), I remember reading somewhere that EclipseLink does not have this restriction, but maybe I am wrong. Anyway this each managed entity in the persistence context must be assigned an identifier is very limiting. Maybe we should vote on Hibernate JIRA to remove this restriction.




                We use MSSQL, not Oracle, so I'm not even sure if we can use sequences...

                1) if you're using SFSB, beware: Caused by: java.lang.IllegalArgumentException: Stateful session beans may not be bound to the PAGE context.  Conversation scope is the default for SFSB, typically it's recommended to use that to model a conversation.


                Could you elaborate on what causes such exception?



                2) In EJB3, the default TransactionAttributeType is REQUIRED.  If you're using CMT, the tx begins when the method begins and commits if the method completes successfully.



                So, what do you do if you want your transaction to span many method calls?



                  This happens automatically with CMT.  The alternative is BMT and you get fine-grained, programmatic control of your tx's but it's more code.



                So BMT is the answer to: what do you do if you want your transaction to span many method calls?. Am I right?




                3) I'm pretty sure that @Begin/@End don't have anything to do (AFAIK) with tx semantics, they just demarcate the promotion (@Begin) of a temporary conversation to a LRC, and the end (demotion to temp conversation) of a LRC.



                But... isn't the current entityManager since AFAIK it is a conversation scope component, somehow, in a i do not really get how affected by conversations ending and beginning? And, since the entityManager  is affected, therefore, tx semantics are affected too? (or perhaps the problem is that they are not affected, and the resulting behavior is counter intuitive?





                • 5. Re: Confused with conversation and transaction demarcation
                  brandonsimpson
                  I'm still new to Seam, Persistence, etc. so take what I say with a grain of salt. Here's what I've found...the behavior of persistence and transactions can vary a lot depending on your particular setup. For example if you use @PersistenceContext instead of @In with your EntityManager, you get different results. In the @PersistenceContext way, the EntityManager is managed by the EJB container and it does it differently than the Seam managed @In EntityManager way.

                  I'm only using POJOs in my app so my experience mostly stems from that, but as far as I know the flushType.MANUAL mode is only useful with the @In EntityManager way. In this case the EntityManager is stored in the conversation context, so if you are using a LRC it will be available during the whole conversation across multiple requests. If I recall, if you don't use flushType.MANUAL everything gets flushed out during each request because Seam controls the transactions (at least in the way that I have it set up) and closes the EntityManager with the transactions on each request.

                  As far as ScopeType.PAGE, it didn't seam useful to me even though that's what I started with for something similar to what you are doing. Reason being, it didn't appear to get cleaned up until the session ended (so it might as well be session scope in a way). You can test this yourself by adding @Create and @Destroy methods to track it's coming and going...really I'd recommend doing that for starters just to get a good idea of what is going on in your app. So that said, I also am using a LRC even for a single page.

                  Now since you are using EJB some things will probably be different (especially if you are using @PersistenceContext). Probably in that case, your transactions are ending with each method call. I would think that you could use @In EntityManager and flushType.MANUAL with EJBs in which case you'll have the same type of control as with POJOs but I haven't tried it.

                  I hope I've helped more than I've provided misinformation! =)
                  • 6. Re: Confused with conversation and transaction demarcation
                    gonorrhea

                    I don't think EclipseLink provides MANUAL flushMode, that mode is Hibernate-specific.


                    There are tx propagation semantics involved with EJB3 (read the spec or Bauer/King book).


                    BMT is not necessarily the answer, you should only use BMT if you need fine-grained, programmtic control of tx demarcation (begin/commit).


                    This stuff is very complex, esp. if you need to use XA/2PC for distributed tx's.  I really miss my Powerbuilder days sometimes!!


                    • 7. Re: Confused with conversation and transaction demarcation
                      frer

                      I'm not sure about the that @Begin and @End not having anything to do with the tx semantics. You do need to specify in the @Begin if the flush mode is manual or not (which is kind of tx specific).  But I do agree that the @End does not commit a transaction (at least I haven't observed such a thing).


                      As for the CMT and BMT my understanding is that if a method is annotated with the transaction required attribute, it will start the conversation if not started or continue the existing one.  This way, I believe you can call methods one after the other and propagate the transaction.  By default, Seam uses CMT?  I'm kind of confused (yet again ;))


                      I'll keep posting my progress with my trials and errors.  In the meantime I really appreciate both your inputs on the subject.

                      • 8. Re: Confused with conversation and transaction demarcation
                        frer

                        Thanks Brandon for the answer.  In my case I inject a hibernate session. I don't use the entityManager directly.  I'm starting to think I should switch since everybody uses the entityManager rather than the hibernate session.  Especially since I recently read that I can get the hibernate session from the entity manager and therefore have the best of both worlds.


                        Anyways, back to our subject, I do seem to experience what you are explaining by injecting my session.  If I don't use the manual flush mode my transaction gets completed on every request.


                        One thing I'm having trouble coping with is when I have many components using the same conversation. Its not necessarily obvious to understand how they all sync up on each request.  For now, my best solution is to use the manual flush mode and to flush my session when I want certain objects to be persisted.   But then again, if I have some objects that I don't want to be persisted, I'm not sure how to do it


                        Ex: I have 2 actions running at the same time.  One action is modifying a reportTemplate and the other lists my reportTemplates (both on the same page).  If I modify my reportTemplate and then click on delete on the list of report templates (on a different reportTemplate than the one I am editing), I would like only the selected reportTemplate to be deleted but not my reportTemplate to be saved. But the fact that they are in the same conversation (and therefore the same session), if I delete one, the other gets saved. 


                        If I don't use the manual flush mode, same problem occurs.  As soon as my request is made to delete a reportTemplate.


                        Does anybody know what I should do in this case?

                        • 9. Re: Confused with conversation and transaction demarcation
                          gonorrhea

                          show your xhtml and backing bean code...


                          i think you're saying a delete and update tx is occurring and you only want a delete tx to occur for that particular scenario, correct?

                          • 10. Re: Confused with conversation and transaction demarcation
                            frer

                            Yes indeed.  I'll post the code on monday morning (I don't have access to it right now)


                            Thanks

                            • 11. Re: Confused with conversation and transaction demarcation

                              Arbi Sookazian wrote on Apr 24, 2009 21:46:


                              I don't think EclipseLink provides MANUAL flushMode, that mode is Hibernate-specific.



                              Yes, I know that, MANUAL  is hibernate specific, but the rule If the entity identifier is generated during an insertion (i.e., auto-increment column), then even with manual flushing, a flush occurs after a call to persist(). is (AFAIK) hibernate specific too, in EclipseLink if you use the COMMIT mode, you can call entityManager.persist() and it will not go fetch and id until the transaction is finally commited. So I guess I want the best of both worlds, the delayed fectching of Ids of EclipseLink, with the MANUAL mode of Hibernate.



                              There are tx propagation semantics involved with EJB3 (read the spec or Bauer/King book).

                              BMT is not necessarily the answer, you should only use BMT if you need fine-grained, programmatic control of tx demarcation (begin/commit).

                              This stuff is very complex, esp. if you need to use XA/2PC for distributed tx's.  I really miss my Powerbuilder days sometimes!!



                              I know the feeling, I miss EOF and its transparent way of dealing with transactions... and nested transactions (something AFAIK unavailable in JPA).  I guess each day I get more inclined to make the switch into Cayenne






                              Click HELP for text formatting instructions. Then edit this text and check the preview.

                              • 12. Re: Confused with conversation and transaction demarcation
                                brandonsimpson

                                I've only used EntityManager and not Session so far so I can't say for sure if they behave pretty much the same way or if each has their own little idiosynchracies. But really I think EntityManager is just a wrapper around Session functionality-wise. I went with EntityManager just to try to stay more standards-based and like you said you can get at the underlying Session or Hibernate APIs if you really need them (even though I haven't needed them yet).


                                Ok...on your situation. You'll have to translate whatever I say from EntityManagers to Sessions wherever the terminology is different, but basically, your persistance context is going to be synched up with the database when you do your flush so whatever is attached to that persistence context when you do the flush is what you're going to get if you have cascading and what not between your entities. That whole tree will be persisted. So if you are editing one of those entities that is attached, and you delete another entity that's also attached and flush it out, your edited entity will also be flushed out at the same time. So I think what you would need to do to keep that edited one separate would be to create a new entity instance and set its properties to match the entity from your persistence context (if one existed). Then you only want to merge or otherwise copy the edited properties back to the attached entity once you are really ready to save the changes. I hope that makes sense...I'm pretty new to persistence myself but recently ran into a similar situation.