Announcement Announcement Module
Collapse
No announcement yet.
@Transactional annotations on internal methods Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @Transactional annotations on internal methods

    Hello!

    I encountered a problem with @Transactional annotation on internal methods. I tested to cases:

    1. <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> (cglib proxies)

    If &#64;Transactional annotation is present on method called from outside of the service class (here action(...) method), everything works as expected. But when I put this annotation on internal method (here doAction(...) method) called by some other method in service then transactions do not work (transaction is not opened).
    I am using spring 2.0.7 and 2.5.4. Is there any possibility to get it working?

    Code:
    public interface TestService {
    
    	void action(String str);
    	
    }
    
    public class TestServiceImpl implements TestService {
    
    	&#64;Override
    	public void action(String str) {
    		doAction(str);
    	}
    	
    	&#64;Transactional
    	protected void doAction(String str) {
    		some dataaccess operations....
    	}
    
    }
    2. <tx:annotation-driven transaction-manager="transactionManager"/> (JDK proxies)

    Everything seems works fine, but in reality spring cheats ;-) and advises action() method instead of doAction() method. When I throw a RuntimeException from action() method after invoking doAction() method the whole transaction is rolled back, but it shouldn't because it should be already commited:

    Code:
    	&#64;Override
    	public void action(String str) {
    		doAction(str);
    		throw new RuntimeException();
    	}
    Do you have any ideas how to solve this problem?

    Regards
    Jarek

  • #2
    I suggest you read chapte 6.6.3 about aop proxies and how proxy based aop works. In short you can only advice stuff that passes through the proxy, method inside the method obviously don't pass through the proxy.

    If you want to solve this you will need to switch to a full blown aop solution like AspectJ and use load or compile time weaving.

    Comment


    • #3
      In meantime I made some tests involving JDK proxies and cglib proxies. In JDK proxies it seems that indeed it is impossible to intercept selfinvocations. But in cglib proxies it can be made, but for unknown reasons spring does not use this possibility.

      If proxy interceptor uses invokeSuper method it can intercept selfinvocations. Like here:
      Code:
      public class TestInterceptor implements MethodInterceptor {
      
      	public Object intercept(Object proxy, Method method, Object[] args,
      			MethodProxy methodProxy) throws Throwable {
      		System.out.println("CGLIB Intercepting: " + method.toString());
      		return methodProxy.invokeSuper(proxy, args);
      	}
      
      }
      But spring uses different approach. Instead of calling invokeSuper with proxy as first parameter it calls invoke with target object (somehow retrieved from AdvisedSupport helper object) as first parameter. I don't understand why. With such approach it is unable to intercept selfinvocations which is a serious flaw for me.

      Regards
      Jarek

      Comment

      Working...
      X