10 Replies Latest reply on Sep 30, 2009 11:38 AM by ashiyanayoga

    Global transactions and @Transactional

    phantasmo

      I am reading Seam in Action and I have some problems understanding global transactions.
      Would anyone be so kind to confirm or correct the following statements:


      1 - Global transcations are turned on by default
      2 - @Transactional is ignored when global transactions are in use
      3 - If global transactions are in use, everything from the Restore View to the Render Response phase is executed atomically


      These are what I managed to deduce on my own, but I have no idea if there's any truth in them, so please, shed some light on the subject if you can.


      Any insight is appreciated.

        • 1. Re: Global transactions and @Transactional
          israel.bgf

          I would say that you are right.

          • 2. Re: Global transactions and @Transactional
            phantasmo

            Ok, thanks for the confirmation!


            If anyone has anything to add, please, be my guest.

            • 3. Re: Global transactions and @Transactional
              asookazian

              I don't think your 2nd statement is true.  @Transactional is used as an equivalent (CMT) for transaction mgmt with POJO components.  Its usage is un-related to global tx's AFAIK (i.e. you can use @Transactional with or w/o global tx's enabled, but don't quote me on that!).


              But yes, global tx's, atomic tx's, atomic conversations, etc. does get convoluted in Seam apps...

              • 4. Re: Global transactions and @Transactional
                clerum

                So In this case I have a component which is called from my JSF page sendTaxFile since global transactions are on by default and this an action method called from the view layer this is wrapped in a transaction. Correct?




                @Name("invoiceJobUtil")
                public class InvoiceJobUtilBean implements InvoiceJobUtil {
                     
                     @In EntityManager em;
                     
                     @In(required=false)
                     @Out(required=false)
                     InvoiceJob invoiceJob;
                
                        public void sendTaxFile()
                     {
                          Long start = System.currentTimeMillis();
                          TaxRunner taxRunner = (TaxRunner) Component.getInstance("taxRunner");
                          taxRunner.createTaxFile(invoiceJob);
                          Long end = System.currentTimeMillis();
                          float proccessTime = (float)(end - start) /1000; 
                          taxRunner.sendToBillSoft();
                          invoiceJob.setTimeToProcessTaxes(proccessTime);
                          invoiceJob.setDateTaxSent(new Date());
                          invoiceJob.setTaxSent(true);
                          taxRunner.retreiveFromTaxing(invoiceJob);          
                     }
                



                Now whats different here is that the call to taxRunner.retreiveFromTaxing(invoiceJob) is asynchronous


                @Name("taxRunner")
                public class TaxRunnerBean implements TaxRunner
                {     
                     @In EntityManager em;
                     @Logger private Log log;
                     private File rawFile;
                     private String fileName;
                
                        @Transactional
                     @TransactionTimeout(3600)
                     @Asynchronous
                     public void retreiveFromTaxing(InvoiceJob invoiceJob)
                     {
                          Thread.sleep(30000);
                
                          int filesRetreived = 0;
                          
                          while(filesRetreived == 0)
                          {
                               FTPClient client = getTaxFTPConnection();          
                               FTPFile[] list = client.list("*" + invoiceJob.getName().substring(4).toLowerCase() + ".*");
                          
                               if(list.length > 0)
                               {
                                    for(FTPFile file : list)
                                    {
                                         client.download(file.getName(), new File("C:/TMP/" + file.getName()));
                                    }
                                    filesRetreived = filesRetreived + list.length;
                                    client.disconnect(true);
                               }
                               else
                               {
                                    client.disconnect(true);
                                    Thread.sleep(30000);
                               }
                          }
                          updateInvoiceJobTaxReceivedDate(invoiceJob);
                     }
                



                I think this is correct since these are POJO's but if I threw an @Stateful on these components would this be correct?

                • 5. Re: Global transactions and @Transactional
                  clerum

                  What I see is that the action method sendTaxFile() commits after it calls the Async retreiveFromTaxing(invoiceJob) because the changes are pushed to the database right away.


                  Thus I figure I need a new transaction around the public void retreiveFromTaxing(InvoiceJob invoiceJob) method

                  • 6. Re: Global transactions and @Transactional
                    asookazian

                    IIRC from SiA, the purpose of the global tx's is to wrap the lazy-loading of object graph navigations in JSF dataTable column values, for example, in tx's rather than having them otherwise execute in AUTOCOMMIT mode.


                    But in Cody's case I think you may be over-thinking or over-complicating things.  However, I have never tried @Asynchronous and @Transactional on the same method simultaneously, however, it may work.  The best approach is to add bebug brkpts in the appropriate transaction API in JBoss core classes (sorry, don't recall the names of the classes) to see if the method is actually being wrapped in a tx when you apply @Transactional to your method.


                    You can annotate @Transactional at the class level as well and override as required at the method level.


                    It seems to me that Seam should by default invisibly add @Transactional to the class level.  This is essentially what EJB CMT does (REQUIRED is default for all public interface methods).


                    Why would you not want your POJO components' methods to be wrapped in a tx by default?


                    Here is the JavaDoc comment:



                    Specifies that the transaction propagation for a JavaBean component or method of a JavaBean component. JavaBean components have @Transactional(SUPPORTS) behavior if no @Transactional annotation is specified.

                    So by default in Seam tx's it's SUPPORTS, not REQUIRED like in EJB 3 CMT...


                    That's an important difference.....

                    • 7. Re: Global transactions and @Transactional
                      phantasmo

                      First of all, thanks for all the input!



                      Arbi Sookazian wrote on Sep 29, 2009 17:04:


                      I don't think your 2nd statement is true.  @Transactional is used as an equivalent (CMT) for transaction mgmt with POJO components.  Its usage is un-related to global tx's AFAIK (i.e. you can use @Transactional with or w/o global tx's enabled, but don't quote me on that!).


                      I was referring to the following sentence from SiA:



                      Note, however, that the @Transactional annotation is irrelevant during a JSF request when using Seam global transactions.


                      I guess it makes sense, as if there is an overarching tx, no new transactions will be spawned to encompass business methods, effectively ignoring @Transactional. Of course, an overarching tx will only be present during a JSF postback. On non-JSF calls, @Transactional will still do it's job normally.


                      All of this is, of course, my interpretation so I'm looking forward to hearing your opinion on this.

                      • 8. Re: Global transactions and @Transactional
                        clerum
                        • 9. Re: Global transactions and @Transactional
                          phantasmo

                          Ok, that confirms my theory. Thanks a lot!

                          • 10. Re: Global transactions and @Transactional
                            ashiyanayoga

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




                            Wish you all the best



                            Ashu
                            www.ashiyana-yoga-goa.com