Announcement Announcement Module
Collapse
No announcement yet.
Problem with <tx:advice /> after XmlWebApplicationContext.refresh() Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with <tx:advice /> after XmlWebApplicationContext.refresh()

    Hello,

    I am having a problem with Spring 3.1.2.RELEASE and it looks like it may be a bug. I tried to debug it, but it's just getting too deep into the Spring AOP proxy code for me to understand, so I'd appreciate some advice.

    Everything works correctly before the context refresh, but after strange things happen.

    Here is the relevant declarations:
    PHP Code:
        <aop:config proxy-target-class="true">
            <!-- 
    Trace logging -->
            <
    aop:advisor pointcut="ca.gc.agr.agrirecovery.SystemArchitecture.businessService()" advice-ref="serviceTraceLoggingAdvice" order="1" />
        
            <!-- 
    Transaction Management -->
            <
    aop:advisor pointcut="ca.gc.agr.agrirecovery.SystemArchitecture.businessService()" advice-ref="txAdvice" order="2"/>

            <!-- 
    Ref Data Transaction Management -->
            <
    aop:advisor pointcut="ca.gc.agr.agrirecovery.SystemArchitecture.referenceDataManagement()" advice-ref="refDataTxAdvice" order="3"/>
     
        </
    aop:config>
                 
        <!--
            
    Transaction advice definitionbased on method name patterns.  Defaults to PROPAGATION_REQUIRED.
        -->
        <
    tx:advice id="txAdvice">
            <
    tx:attributes>
                <
    tx:method name="*" propagation="REQUIRED" />
                <
    tx:method name="find*" propagation="REQUIRED" read-only="true"/>        
                <
    tx:method name="validate*" propagation="REQUIRED" read-only="true"/>
                <
    tx:method name="is*" propagation="REQUIRED" read-only="true"/>
                <
    tx:method name="calculate*" propagation="REQUIRED" read-only="true"/>
                <
    tx:method name="setup*" propagation="REQUIRED" read-only="true"/>
            </
    tx:attributes>
        </
    tx:advice>
         
        <
    tx:advice id="refDataTxAdvice">
            <
    tx:attributes>
                <
    tx:method name="*" propagation="REQUIRED" read-only="true" />
            </
    tx:attributes>
        </
    tx:advice
    I have observed the instantiation of two TransactionInterceptors with the corresponding HibernateTransactionManager for each advice when the program starts:

    Code:
    org.springframework.transaction.interceptor.TransactionInterceptor@121157c9, id=125 <- txAdvice
    		[email protected]ad61d3, id=112
    
    org.springframework.transaction.interceptor.TransactionInterceptor@b89b904, id=193  <- refDataTxAdvice
    		[email protected]ad61d3, id=112
    After the refresh I can see two new TransactionInterceptors beeing created. Here they are:

    Code:
    org.springframework.transaction.interceptor.TransactionInterceptor@6d441cce, id=334
    		[email protected]ca61f9, id=335
    
    org.springframework.transaction.interceptor.TransactionInterceptor@6feb2ae7, id=492
    		[email protected]ca61f9, id=335
    ok, two new TransactionInterceptors with one new HibernateTransactionManager. So far so good.

    However, the next request after the refresh uses the following TransactionInterceptors:

    Code:
    org.springframework.transaction.interceptor.TransactionInterceptor@121157c9, id=125
    		[email protected]ad61d3, id=112
    
    org.springframework.transaction.interceptor.TransactionInterceptor@6feb2ae7, 492
    		[email protected]ca61f9, id=335
    Note that txAdvice is being serviced by the wrong TransactionInterceptor! It is using the pre-refresh one, so HibernateTransactionManager in it is no longer valid.

    As a result, everything that goes through refDataTxAdvice works, but calls that are advised by txAdvice fail.

    So my questions is this - how/why is Spring using an old TransactionInterceptor, even though it has correctly created two new ones? Is this a bug?

    Any ideas would be appreciated.

    Thanks.

  • #2
    I have further reduced the usecase and it still fails:

    PHP Code:
           <aop:config proxy-target-class="true">
            <!-- 
    Transaction Management -->
            <
    aop:advisor pointcut="execution(public * *..*ManagementImpl.*(..))" advice-ref="txAdvice" order="1"/>
           </
    aop:config>
                 
        <
    tx:advice id="txAdvice">
            <
    tx:attributes>
                <
    tx:method name="*" propagation="REQUIRED" />
                <
    tx:method name="find*" propagation="REQUIRED" read-only="true"/>        
                <
    tx:method name="get*" propagation="REQUIRED" read-only="true"/>        
                <
    tx:method name="validate*" propagation="REQUIRED" read-only="true"/>
                <
    tx:method name="is*" propagation="REQUIRED" read-only="true"/>
                <
    tx:method name="calculate*" propagation="REQUIRED" read-only="true"/>
                <
    tx:method name="setup*" propagation="REQUIRED" read-only="true"/>
            </
    tx:attributes>
        </
    tx:advice
    On application start all services are being advised by one TransactionInterceptor:
    Code:
    org.springframework.transaction.interceptor.TransactionInterceptor@28b6483, id=126
    		[email protected]d56c22, id=152
    After the refresh, most service calls are advised by the stale TransactionInterceptor:
    Code:
    org.springframework.transaction.interceptor.TransactionInterceptor@28b6483, id=126
    		[email protected]d56c22, id=152
    but at least one service is advised by the correct TransactionInterceptor:
    Code:
    org.springframework.transaction.interceptor.TransactionInterceptor@47dce809, id=301
    		[email protected]db5fac, id=308
    This is even more mysterious. How can there be a difference between these services, when they are selected by the same pointcut and there is only one advise declared? Well, the one that works was explicitly declared in applicationContext.xml, whereas the ones that don't are annotated with @Service. So I tried to explicitly declare some beans, but it made no difference, so it's not annotations.

    Not sure what else to try...
    Last edited by vace117; Feb 15th, 2013, 06:57 PM.

    Comment

    Working...
    X