1 2 3 Previous Next 41 Replies Latest reply on Aug 27, 2009 8:36 PM by asookazian Go to original post
      • 15. Re: Transactional propagation types

        Arbi Sookazian wrote on Aug 26, 2009 18:15:


        I have a functional requirement as follows:

        insert record into remote db via web service call

        insert record into local db

        Do not treat as a distribute tx (i.e. if one or the other fails if SQLServerException is thrown or network error, etc. do not rollback the other one)



        Alright, so far no need for XA Datasource or any other sluggish EJB/JEE stuff...




        So if there is already a tx running, then this business method is called,


        Interesting fragment of sentence... lets analyze it: If there is already a tx running.. if? First thing we should be sure is that there is going to be one, if not, all this discussion is pointless (Imagine switching to an EAR, giving your project the sluggish death, only to realize later that you are never going to call this method when a transaction is running!) Or am I understanding this wrong an the sentence you wanted to write is: WHEN there is a tx running, this business method is called (as in I am 100% sure it is going to happen, remember we are talking about bringing in a technology with a long history of being a cumbersome disadvantage (JEE) so, if you are not sure you are going to need one of its features, avoid it like the plage)



        I need to suspend the tx, execute the method with both inserts, then continue tx.


        Well, the insert record into remote db via web service call couldn't care less about a transaction running, so there is no problem there. On the other insert, we go back to my previous comment... why is there a transaction already running? what is the transactional context you want your insert to be running at? do you want it to succeed even if the already running transaction fails?




        I could probably create two methods instead of one, but I am considering this one logical unit of work w/o tx.


        Interesting that you considere it a logical unit of work when it seems to me that since one operation can succeed or fail independently of the other, they are actually not a single logical unit of work... (BTW what is you definition of unit of work? This is the definition I like the most, and so far the only ORM I have found that actually follows it is EOF (Hibernate is almost there, but it can not properly track of new objects))

        • 16. Re: Transactional propagation types
          asookazian


          regarding the above figure from SiA, how can I dynamically (programmatically) see a list of business methods that are available to the caller in the proxy object?


          This way I will know which methods in my JavaBean component Seam is making available for clients to call.

          • 17. Re: Transactional propagation types
            asookazian

            Here is a pertinent email to Ken Saks regarding tx attributes on private methods and public methods not invoked via the EJB container:


            Hello,
            
            I would like to draw attention to this specific part of JSR 318, proposed final draft dated Feb 24, 2009, which is the same as in JSR 220, section 13.3.7.1:
            
            Specifying the TransactionAttribute annotation on the bean class means that it applies to all applicable business interface methods of the class.
            
            
            
            In EJB 3.1 (or later), I’m wondering if it will be possible to demarcate transaction attribute value (e.g. REQUIRED, REQUIRES_NEW, etc.) on private, protected, or package-private in a SFSB or SLSB (i.e. any method with less than public visibility).  The current behavior in EJB 3.0 seems to be that the EJB container (in my case JBoss AS) ignores the transaction demarcation annotation on a private method and there is no warning from Eclipse, or exception/warning during deployment or runtime exception.  
            
            I ran into this problem recently and it took me over *two days* to determine the root cause of the behavior in terms of transaction semantics and CMT in my SFSB.  My workaround to this problem was to refactor the private method to a public method defined in the local interface implemented by a new SFSB.  The REQUIRES_NEW transaction demarcation for the public method in the new SFSB is now “honored” by the ejb container.  
            
            Why is it necessary to do this?  We should be able to demarcate non-local interface methods or non-remote interface methods with transaction demarcation when using CMT.
            
            
            
            Hi Arbi,
            
            
            The behavior you're seeing is not specific to transaction attributes.  All the special semantics associated with an EJB component invocation (method authorization, container exception handling, threading guarantees, container-managed transactions, etc.) only apply to invocations made through an EJB reference.  When code already running within a business method invocation calls another method on the same class through the "this" pointer, the EJB container isn't involved.  Such a method invocation is just a plain Java SE method call.  
            
            
            If you want to invoke a business method on your bean from another business method on the same bean, you'll need to acquire an EJB reference to yourself.  The easiest way is to call SessionContext.getBusinessObject().  
            
            
            
            
            TestTransactionsLocal ejbRefToMyself =  sessionCtx.getBusinessObject(TestTransactionsLocal.class)
            ejbRefToMyself.otherMethod();
            
            
            Regards,
            
            
            Ken
            



            So now I'm thinking I need to make the private method (insertStatusAndErsNote()) public and call it from the apply() method.  How can I do this in the context of a JavaBean (i.e. how does the JavaBean get a reference to itself)?  I basically need to simulate the Seam container calling the newly public method, how do I do that from within this JavaBean?


            What a pain for a seemingly simple problem...

            • 18. Re: Transactional propagation types

              Arbi Sookazian wrote on Aug 26, 2009 18:55:



              If you refer to persist() method in EntityManager.java you can see the javadocs clearly mention that persist throws javax.persistence.TransactionRequiredException if there is no transaction.
              source: http://weblogs.java.net/blog/ss141213/archive/2005/12/entitymanagerpe_1.html


              Of course, the entityManager requires a transaction.



              That's interesting, I did not know that.  Pretty much means that JPA cannot operate in auto-commit mode I guess if you want to save data to db.  Seems to have nothing to do with the flushMode either.


              Well, it is important to remember here that auto-commit is not equal not no transaction, auto-commit only means that you are saying JDBC driver, deal with transactions automatically they way you want (generally statement by statement), I do not care, a pretty dangerous thing to say, in my opinion. I NEVER use auto commit mode (and you shouldn't)



              Anyways, in EJB, a business method is typically defined as a public method that is exposed in a local/remote interface.  Seam JavaBean components do not have to implement any interfaces, so how does the Seam container know which methods in the JavaBean component are business methods (wild guess: those marked public?)  So that means private methods join the tx of their parent public method.


              AFAIK, yes.



              So this is getting overly-complicated and messy.  I want to keep the hot deploy with JavaBeans but also need the tx flexibility for my functional requirement.

              Am I missing something here or what?  And out of curiosity, how would you implement this, from a tx-al perspective, for this requirement if you used session beans?



              Well, since I am using Seam with Spring, this is all very different (and easier) for me ;-). And please believe me, adding Spring to your project is far far less problematic than making it an EAR. I would probably use Spring TransactionCallback to deal with this in simple way (Declarative stuff is also nice, but I prefer the programmatic way when I want tight control).


              Now... without Spring... and without EJBs that is a really good question...

              • 19. Re: Transactional propagation types
                asookazian

                I tried this in the apply() method:


                public void apply() {
                ...
                    EquipmentProcessingViewAction equipmentProcessingView = (EquipmentProcessingViewAction)        Component.getInstance("equipmentProcessingView");
                          
                          equipmentProcessingView.insertStatusAndErsNote();
                }



                and this:


                @Transactional
                public void insertStatusAndErsNote(){...}



                and still getting:



                Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress

                Is it even possible to force a Seam proxy call from a current JavaBean method?

                • 20. Re: Transactional propagation types
                  asookazian

                  Francisco, I appreciate your responses, they were helpful.


                  Let me clarify a few things:


                  1) It's probably not a logical unit of work if a tx is not required.  However, they do execute at the same time (when user clicks Apply button), so that's why I referred to it as such.  But you're right.


                  2) I don't know how or what initiated the existing tx when my public method (apply()) is called.  I turned off global tx's like this:

                  <core:init debug="@debug@" jndi-pattern="@jndiPattern@" transaction-management-enabled="false"/>



                  3) I just converted my POJO to SFSB and used Ken Saks code above, but then realized that I must now convert my project from WAR to EAR which I do not want to do honestly right now.  I also cannot integrate Spring into the project.


                  I was trying to do this as a SFSB:


                  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                  public void apply() {...}
                  
                  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
                  public void insertStatusAndErsNote(){





                  So how do I determine what tx is running when my apply() method is called from JSF EL (I believe Seam creates a proxy when the action is invoked from the JSF page)?  Obviously there must be a tx already running otherwise the @Transactional(TransactionPropagationType.NEVER) would not cause the exception to be thrown.  And it's not the Seam global tx's as I have that disabled now (unless there's a bug and it's not disabling properly).


                  This is pretty bad if I want to keep doing hot deployments with WAR...

                  • 21. Re: Transactional propagation types
                    israel.bgf

                    Hmm about the performance boost, i don't know if it's big thing either Francisco, I'm just telling what the books tells, and well supposedly that would be a reason to suspend a transaction, if it REALLY makes difference, I dunno. 

                    • 22. Re: Transactional propagation types
                      asookazian

                      Well I just tried this:


                      @In 
                      private UTTransaction utx;



                      and this:


                      @In 
                      private UserTransaction utx;



                      and I get for both:


                      Caused by: org.jboss.seam.RequiredException: @In attribute requires non-null value: equipmentProcessingView.utx



                      I am trying to do BMT style around the EntityManager persist() call to satisfy JPA/Hibernate.


                      Has anybody done BMT using Seam's Transacation API?  will this solution work using this and JavaBean?

                      • 23. Re: Transactional propagation types

                        Arbi Sookazian wrote on Aug 26, 2009 20:18:


                        Francisco, I appreciate your responses, they were helpful.

                        Let me clarify a few things:


                        And I appreciate your questions ;-).



                        1) It's probably not a logical unit of work if a tx is not required.  However, they do execute at the same time (when user clicks Apply button), so that's why I referred to it as such.  But you're right.


                        Well, that means you could just start a transaction, do your inserts, commit, and then start another transaction, and do something else. You only need suspension because you want to do one thing inside another thing, but if you do them sequentially...



                        2) I don't know how or what initiated the existing tx when my public method (apply()) is called.  I turned off global tx's like this:
                        <core:init debug="@debug@" jndi-pattern="@jndiPattern@" transaction-management-enabled="false"/>



                        3) I just converted my POJO to SFSB and used Ken Saks code above, but then realized that I must now convert my project from WAR to EAR which I do not want to do honestly right now. 


                        Wise decision to avoid the EAR is. ;-)



                        I also cannot integrate Spring into the project.



                        Why not?



                        I was trying to do this as a SFSB:

                        @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                        public void apply() {...}
                        
                        @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
                        public void insertStatusAndErsNote(){




                        So how do I determine what tx is running when my apply() method is called from JSF EL (I believe Seam creates a proxy when the action is invoked from the JSF page)?  Obviously there must be a tx already running otherwise the @Transactional(TransactionPropagationType.NEVER) would not cause the exception to be thrown.  And it's not the Seam global tx's as I have that disabled now (unless there's a bug and it's not disabling properly).

                        This is pretty bad if I want to keep doing hot deployments with WAR...


                        Maybe you should look at the code in org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke to see how does it determine that a tx is running...?

                        • 24. Re: Transactional propagation types

                          Arbi Sookazian wrote on Aug 26, 2009 20:44:


                          Has anybody done BMT using Seam's Transacation API?  will this solution work using this and JavaBean?


                          I think I once tried the same thing, found someone asking the same question here, asked if he had solved it, and somone else told me how to do it, but since I did not start that thread and I do not know to find all the threads I have participated in

                          • 25. Re: Transactional propagation types

                            Nop, I guess I confused myself, I did used EJBs to use BMT back then

                            • 26. Re: Transactional propagation types
                              asookazian

                              Francisco Peredo wrote on Aug 26, 2009 21:05:


                              Well, that means you could just start a transaction, do your inserts, commit, and then start another transaction, and do something else. You only need suspension because you want to do one thing inside another thing, but if you do them sequentially...



                              That sounds like a possible solution.  How would I start the 2nd tx?  The key here is I have two operations resulting from one JSF action (click apply button).  I guess it would be ok if each operation was in its own tx, just as long as both operations were not wrapped in the same tx.


                              I don't care so much what order they are executed in.  And they do not necessarily need to be executed in the same public (or non-public) method.


                              It would have been nice if REQUIRES_NEW was an option with @Transactional but even that requires the Seam container to call a public business method.  And I cannot get Seam to call the method as a proxy from itself using the Component.getInstance("foo") that was similar to what Ken Saks recommended for EJB component.


                              I can't use Spring due to standards limitations in our stack here at the company I work for.  So that means it's not impossible just not best practice from our headquarter's perspective perhaps.

                              • 27. Re: Transactional propagation types
                                swd847

                                Component.getInstance() approach should work however you are probably creating the entityManager outside the scope of the transaction. Try calling entityManager.joinTransaction().


                                I think it would be pretty neat to be able to control the global transaction management on a page by page basis using .pages.xml. Most of the time they are great, but for some pages they are just not appropriate.

                                • 28. Re: Transactional propagation types
                                  asookazian

                                  Stuart Douglas wrote on Aug 27, 2009 00:15:


                                  Component.getInstance() approach should work however you are probably creating the entityManager outside the scope of the transaction. Try calling entityManager.joinTransaction().



                                  Could you plz elaborate on this?  What do you mean by you are probably ... of the transaction.  I've never actually called entityManager.joinTransaction() before.  Which tx would it be joining?

                                  • 29. Re: Transactional propagation types
                                    swd847

                                    If the em is created when no transaction is active then it is not associated with a transaction. When you create a JTA transaction you need to call entityManager.joinTransaction() to associate it with the transaction (this is only for jta, resource local is different).