Announcement Announcement Module
Collapse
No announcement yet.
Transaction Behaviour Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transaction Behaviour

    Hi,

    I'm observing some strange transaction behaviour and cannot for the life of me figure out what I'm doing wrong.

    I've two methods, methodOne and methodTwo. Both have transaction attributes and methodTwo calls methodOne. It appears that the attributes on methodOne are ignored in this situation. Calling methodOne on its own appears fine.

    Looking at the log traces there is a call,

    DEBUG [org.springframework.transaction.interceptor.Transa ctionInterceptor] - Getting transaction for method 'methodTwo' in class [test.TransactionTestI]

    but this never happens for methodOne, even though as I mentioned, methodOne is called by methodTwo.

    Here is an application context from a very simple test situation I set up. In reality, I'm using source code annotations but see the same behaviour.

    Code:
    <bean id="transactionTestTarget" class="test.TransactionTest" />
    	
    	<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    		
    		<property name="transactionManager"><ref bean="transactionManager"/></property>
    		<property name="transactionAttributeSource">
            	<value>
    				test.TransactionTestI.methodOne=PROPAGATION_NEVER
    				test.TransactionTestI.methodTwo=PROPAGATION_REQUIRED
    			</value>
    			
    		</property>
    	</bean>
    	
    	<bean id="transactionTest" class="org.springframework.aop.framework.ProxyFactoryBean">
    		<property name="proxyInterfaces">
    			<value>test.TransactionTestI</value>
    		</property>
    		<property name="target"><ref local="transactionTestTarget"/></property>
    		<property name="interceptorNames">
    			<list>
    				<value>transactionInterceptor</value>
    			</list>
    		</property>
    	</bean>
    with the transactionManager being a HibernateTransactionManager, although this basic test does not access Hibernate.

    The behaviour I'd expect in the above case of attributes is that an exception would be thrown when calling methodOne due to the PROPAGATION_NEVER. It isn't thrown.

    Has anyone any ideas what maybe causing this problem, or am I wrong in my assumption about the behaviour of one transactioned method calling another?

    Here's a log trace with pertinant logging turned on:
    Code:
    INFO &#91;org.springframework.orm.hibernate.LocalSessionFactoryBean&#93; - Building new Hibernate SessionFactory
     INFO &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Using DataSource &#91;org.apache.commons.dbcp.BasicDataSource@f6f1b6&#93; from Hibernate SessionFactory for HibernateTransactionManager
    DEBUG &#91;org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource&#93; - Adding transactional method &#91;test.TransactionTestI.methodTwo&#93; with attribute &#91;PROPAGATION_REQUIRED,ISOLATION_DEFAULT&#93;
     INFO &#91;org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource&#93; - Adding transactional method &#91;public abstract void test.TransactionTestI.methodTwo&#40;&#41;&#93; with attribute &#91;PROPAGATION_REQUIRED,ISOLATION_DEFAULT&#93;
    DEBUG &#91;org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource&#93; - Adding transactional method &#91;test.TransactionTestI.methodOne&#93; with attribute &#91;PROPAGATION_NEVER,ISOLATION_DEFAULT&#93;
     INFO &#91;org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource&#93; - Adding transactional method &#91;public abstract void test.TransactionTestI.methodOne&#40;&#41;&#93; with attribute &#91;PROPAGATION_NEVER,ISOLATION_DEFAULT&#93;
    DEBUG &#91;org.springframework.transaction.interceptor.TransactionInterceptor&#93; - Getting transaction for method 'methodTwo' in class &#91;test.TransactionTestI&#93;
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Using transaction object &#91;[email protected]a7c&#93;
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Creating new transaction
    DEBUG &#91;org.springframework.orm.hibernate.SessionFactoryUtils&#93; - Opening Hibernate session
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Opened new session &#91;net.sf.hibernate.impl.SessionImpl@a010ba&#93; for Hibernate transaction
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Beginning Hibernate transaction on session &#91;net.sf.hibernate.impl.SessionImpl@a010ba&#93;
    DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - Bound value &#91;org.springframework.orm.hibernate.SessionHolder@149f041&#93; for key &#91;net.sf.hibernate.impl.SessionFactoryImpl@29d294&#93; to thread &#91;main&#93;
    DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - Bound value &#91;org.springframework.jdbc.datasource.ConnectionHolder@1984a9d&#93; for key &#91;org.apache.commons.dbcp.BasicDataSource@f6f1b6&#93; to thread &#91;main&#93;
    DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - Initializing transaction synchronization
    DEBUG &#91;test.TransactionTest&#93; - In method two
    DEBUG &#91;test.TransactionTest&#93; - In method one
    DEBUG &#91;org.springframework.transaction.interceptor.TransactionInterceptor&#93; - Invoking commit for transaction on method 'methodTwo' in class &#91;test.TransactionTestI&#93;
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Triggering beforeCommit synchronization
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Triggering beforeCompletion synchronization
     INFO &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Initiating transaction commit
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Committing Hibernate transaction on session &#91;net.sf.hibernate.impl.SessionImpl@a010ba&#93;
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Triggering afterCompletion synchronization
    DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - Clearing transaction synchronization
    DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - Removed value &#91;org.springframework.jdbc.datasource.ConnectionHolder@1984a9d&#93; for key &#91;org.apache.commons.dbcp.BasicDataSource@f6f1b6&#93; from thread &#91;main&#93;
    DEBUG &#91;org.springframework.transaction.support.TransactionSynchronizationManager&#93; - Removed value &#91;org.springframework.orm.hibernate.SessionHolder@149f041&#93; for key &#91;net.sf.hibernate.impl.SessionFactoryImpl@29d294&#93; from thread &#91;main&#93;
    DEBUG &#91;org.springframework.orm.hibernate.HibernateTransactionManager&#93; - Closing Hibernate session &#91;net.sf.hibernate.impl.SessionImpl@a010ba&#93; after transaction
    DEBUG &#91;org.springframework.orm.hibernate.SessionFactoryUtils&#93; - Closing Hibernate session

    thanks

    Jonny

  • #2
    This occurs because the call to the second method is from the target to the target, not the proxy. Hence it's not advised by default. You can set "exposeProxy" to true on your ProxyFactoryBean and do
    Code:
    &#40;&#40;MyType&#41; AopContext.currentProxy&#40;&#41;&#41;.methodOne&#40;&#41;;
    rather than simply call methodOne on this.

    Rgds
    Rod

    Comment


    • #3
      Thanks Rod, someone else also cleared this up for me in another thread.

      I'm wondering if this behaviour should be better documented? I realize, once it was pointed out to me, that this is expected behaviour based on the proxy implementation, but coming from the viewpoint of just using the AOP solution and not needing to know how they work, this isn't the expected behaviour.

      Also, I've some AspectJ experience, which probably biased me into what I should be expecting (that the second method should also be advised).

      thanks again,
      Jonny

      Originally posted by Rod Johnson
      This occurs because the call to the second method is from the target to the target, not the proxy. Hence it's not advised by default. You can set "exposeProxy" to true on your ProxyFactoryBean and do
      Code:
      &#40;&#40;MyType&#41; AopContext.currentProxy&#40;&#41;&#41;.methodOne&#40;&#41;;
      rather than simply call methodOne on this.

      Rgds
      Rod

      Comment

      Working...
      X