Announcement Announcement Module
Collapse
No announcement yet.
TransactionStatus is "new" in participating txn with REQUIRED attribute Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • TransactionStatus is "new" in participating txn with REQUIRED attribute

    Code:
    <aop:config>
            <aop:pointcut
                id="cacheOperationSvc"
                expression="execution(* poc.service.*.*(..))"       
            />
            <aop:advisor
                pointcut-ref="cacheOperationSvc"
                advice-ref="cacheTxAdvice"
            />
        </aop:config>
        
        <aop:config>
            <aop:pointcut
                id="cacheOperationDao"
                expression="execution(* poc.dao.*.*(..))"       
            />
            <aop:advisor
                pointcut-ref="cacheOperationDao"
                advice-ref="cacheTxAdvice"
            />
        </aop:config>
        
        <tx:advice id="cacheTxAdvice" >
            <tx:attributes>
              <tx:method
                    name="*"
                    read-only="true"
                    propagation="REQUIRED"
                    isolation="READ_COMMITTED"
                    timeout="5"
               />
            </tx:attributes>
        </tx:advice>
    Svc1.method1() calls Dao2.method2()

    Svc1.method1() has following code:
    Code:
    TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
    Dao2.method2() also has the same line of code as follows:
    Code:
    TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
    The status variable shows "new" inside Svc1.method1().

    However, the status variable in Dao2.method2() also shows "new".

    My assumption was that the status variable will NOT be "new" inside the code of Dao1.method2(), as the transaction was already being started by Svc1.method1(). As Dao2.method2() is merely participitation in the existing transaction (because of propagation REQUIRED), my assumption was that the status variable will not be "new" inside the Dao2.method2().

    Is there any way to identify that the transaction is already in progress inside dao package classes using this approach?

    Again, there may be other alternatives. However, for the scenario described above, I would like to know what changes in code, or xml needs to be made to accomplish the above.

    Regards

  • #2
    Just checked your scenario - got 'new transaction == false' at the nested transacted method calls

    Comment


    • #3
      Did Svc call Dao within the method body of Svc itself

      Could you please explain what you did to have status as NOT "new" for DAO?

      Did you code like the sample below: (Code Sample 1)
      Code:
      Svc1.method1(){
         Dao2.method2();
      }
      Using the (Code Sample 1) as shown above, will Dao2.method2() also return status as NOT "new"? While both service and DAO methods have propagation set as REQUIRED.

      Or,

      Did you have code like the following? (Code Sample 2)


      Code:
      CompositeService.myMethod(){
         Svc1.method1();
         Dao2.method2();
      }
      Using the code in (Code Sample 2), did you get transaction status as "new" in Svc1.method1(), but got transaction status as NOT "new" in Dao2.method2()? While both service and DAO methods have propagation set as REQUIRED.

      I would like to code like (Code Sample 1) where Svc calls DAO within the method body of Svc. Can I still use code similar to (Code Sample 1) and get status as Not "new" for Dao?

      If (Code Sample 1) does NOT show "new" as status for DAO, is it because I am not jumping the transaction boundary?

      My hunch is, (Code Sample 2) will show NOT "new" status for Dao.method2() as I am jumping the transaction boundary for sure. I need to try that.

      However, is there any way to make transaction status as NOT "new" for Dao2.method2 using the (Code Sample 1)?

      Comment


      • #4
        More clarification

        Let me also clarify that the svc and dao are both Spring beans and are being looked up from Spring's XML.

        As such, the code sample 1 was was similar to:
        Code:
        Svc1.method1(){
           Dao2 d2 = (Dao2) ctx.getBean("dao2");
           d2.method2();
        }
        Svc1 is also another Spring bean and is looked up from XML and method1() is called on the svc1 looked up from Spring.

        In the same way, code for Sample 2 was:
        Code:
        CompositeService.myMethod(){
           Svc1 svc1 = (Svc1) ctx.getBean("svc1");
           svc1.method1();
           Dao2 d2 = (Dao2) ctx.getBean("dao2");
           d2.method2();
        }
        CompositeService is also another Spring bean and is looked up from XML and myMethod() is called on the CompositeService looked up from Spring from a Driver class.

        Comment


        • #5
          Originally posted by sunfun View Post
          Could you please explain what you did to have status as NOT "new" for DAO?
          ...
          TransactedService.java
          Code:
          package com.spring.tx;
          
          import org.springframework.stereotype.Component;
          import org.springframework.transaction.TransactionStatus;
          import org.springframework.transaction.annotation.Propagation;
          import org.springframework.transaction.annotation.Transactional;
          import org.springframework.transaction.interceptor.TransactionAspectSupport;
          
          @Component
          public class TransactedService {
          
              @Transactional(propagation = Propagation.REQUIRED)
              public void test() {
                  TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
                  System.out.println("xx: TransactedService.test(): " + status.isNewTransaction());
              }
          }
          TransactedServiceWrapper.java
          Code:
          package com.spring.tx;
          
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Component;
          import org.springframework.transaction.annotation.Transactional;
          import org.springframework.transaction.interceptor.TransactionAspectSupport;
          
          @Component
          public class TransactedServiceWrapper {
          
              private TransactedService service;
          
              @Transactional
              public void performCall() {
          		System.out.println("xxxxx: TransactedServiceWrapper.performCall(): "
                      + TransactionAspectSupport.currentTransactionStatus().isNewTransaction());
                  service.test();
              }
          
              @Autowired
              public void setService(TransactedService service) {
                  this.service = service;
              }
          }
          SpringStart.java
          Code:
          package com.spring;
          
          import com.spring.tx.TransactedServiceWrapper;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          
          public class SpringStart {
              public static void main(String[] args) throws Exception {
                  ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
                  TransactedServiceWrapper service = (TransactedServiceWrapper)context.getBean("transactedServiceWrapper");
                  service.performCall();
              }
          }
          spring-config.xml
          HTML Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:aop="http://www.springframework.org/schema/aop"
                 xmlns:tx="http://www.springframework.org/schema/tx"
                 xmlns:context="http://www.springframework.org/schema/context"
                 xmlns:util="http://www.springframework.org/schema/util"
                 xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
          
              <context:component-scan base-package="com.spring.tx"/>
              <tx:annotation-driven transaction-manager="txManager"/>
          
              <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  <property name="dataSource">
                      <bean class="com.spring.tx.util.DummyDataSource"/>
                  </property>
              </bean>
          
          </beans>
          Output:
          xxxxx: TransactedServiceWrapper.performCall(): true
          xx: TransactedService.test(): false

          Comment

          Working...
          X