Announcement Announcement Module
Collapse
No announcement yet.
Ordering Transactional aspect with custom aspects Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Ordering Transactional aspect with custom aspects

    Hello,

    I have a problem with ordering transactions and custom aspects in my application. What I'm trying to use aspect ordering for is:

    When some service method is called, I want to have following order of actions:
    1. code which have to be run before transaction creation runs
    2. transaction is created
    3. code which have to be run after transaction creation runs
    4. service method code runs
    5. code which have to be run before transaction commit runs
    6. transaction is commited
    7. code which have to be run after transaction commit runs

    I'm trying to use <tx:annotation-driven order="2" /> tag in applicationContext.xml with order attribute to declare that the transaction should run as a number two in aspect execution chain.
    For before- and after- transaction code I use order value 1 and 3.

    For all transaction and aspect declarations, I use annotation style.

    When I try to run the method, the transaction is always being created first in execution chain and commited last in execution chain.


    The service method looks like this:

    Code:
    ....
    @SuppressWarnings("unchecked")    
    @Transactional
        @Override        
        public <T extends AbstractPartnerVO> T savePartner(T abstractPartnerVO) {
            Logger logger = LoggerFactory.getLogger(this.getClass());
            logger.debug("Save partner on adapter called");
            final AbstractPartner abstractPartner = super.convert(abstractPartnerVO, AbstractPartner.class);
            final AbstractPartner savedPartner = this.partnerService.savePartner(abstractPartner);       
            final T result = (T) this.convert(savedPartner, AbstractPartnerVO.class);
            return result;
        }
    ...

    I use two aspects for actions before and after transaction code.

    Code:
    //Before aspect
    package net.homecredit.hl.core.adapter.common;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.DeclarePrecedence;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.annotation.Order;
     
    @Aspect
    @Order(1)
    public class BeforeTxUCAspect {
            
        
        @Before("execution(* net.homecredit.hl.core.adapter.partner.PartnerServiceAdapter.savePartner(..))")    
        public void beforeUseCase(JoinPoint joinPoint) {   
            Logger logger = LoggerFactory.getLogger(this.getClass());
            logger.debug("Going to start adapter method with signature: " + joinPoint.getSignature().toShortString());
        }
        
        @After("execution(* net.homecredit.hl.core.adapter.partner.PartnerServiceAdapter.savePartner(..))")
        public void afterUseCase(JoinPoint joinPoint) {
            Logger logger = LoggerFactory.getLogger(this.getClass());
            logger.debug("Use case just processed and commited. Signature: " + joinPoint.getSignature().toShortString());
        }
    }
    
    
    
    
    
    
    
    //After aspect
    
    package net.homecredit.hl.core.adapter.common;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.DeclarePrecedence;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.annotation.Order;
     
    @Aspect
    @Order(3)
    public class AfterTxUCAspect {              
        
        @Before("execution(* net.homecredit.hl.core.adapter.partner.PartnerServiceAdapter.savePartner(..))")  
        public void beforeUseCase(JoinPoint joinPoint) {               
            Logger logger = LoggerFactory.getLogger(this.getClass());
            logger.debug("New UC started ... transaction created. Signature: " + joinPoint.getSignature().toShortString());
            
        }
        
        @After("execution(* net.homecredit.hl.core.adapter.partner.PartnerServiceAdapter.savePartner(..))")
        public void afterUseCase(JoinPoint joinPoint) {
            Logger logger = LoggerFactory.getLogger(this.getClass());
            logger.debug("UC processed, transaction is about to be commited. Signature: " + joinPoint.getSignature().toShortString());
        }
    }

    My applicationContext.xml fragment:


    Code:
    ....
    <context:annotation-config />      
        <aop:aspectj-autoproxy/>    
        <tx:annotation-driven order="2" />
    
    ....
    
    
    	<bean id = "beforeTxUCAspect" class = "net.homecredit.hl.core.adapter.common.BeforeTxUCAspect" />
    	<bean id = "afterTxUCAspect" class = "net.homecredit.hl.core.adapter.common.AfterTxUCAspect" />
    
    ....
    
    
        <bean id="transactionManager"
    		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <constructor-arg ref="sessionFactory" />
        </bean>
    
    
    ....


    When I run the method, this messages appear in log - you can see, that the order is not as expected


    2011-04-28 12:56:22,240 [19008539@qtp-17507279-3] DEBUG o.s.o.h.HibernateTransactionManager [] Opened new Session [org.hibernate.impl.SessionImpl@f036de] for Hibernate transaction []
    2011-04-28 12:56:22,240 [19008539@qtp-17507279-3] DEBUG o.s.o.h.HibernateTransactionManager [] Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@f036de] []
    2011-04-28 12:56:22,240 [19008539@qtp-17507279-3] DEBUG o.h.transaction.JDBCTransaction [] begin []
    2011-04-28 12:56:22,240 [19008539@qtp-17507279-3] DEBUG org.hibernate.jdbc.ConnectionManager [] opening JDBC connection []
    2011-04-28 12:56:22,240 [19008539@qtp-17507279-3] DEBUG o.h.transaction.JDBCTransaction [] current autocommit status: true []
    2011-04-28 12:56:22,242 [19008539@qtp-17507279-3] DEBUG o.h.transaction.JDBCTransaction [] disabling autocommit []
    2011-04-28 12:56:22,242 [19008539@qtp-17507279-3] DEBUG o.s.o.h.HibernateTransactionManager [] Exposing Hibernate transaction as JDBC transaction [jdbc:hsqldb:mem:z, UserName=SA, HSQL Database Engine Driver] []
    2011-04-28 12:56:22,247 [19008539@qtp-17507279-3] DEBUG n.h.h.c.a.common.AfterTxUCAspect [] New UC started ... transaction created. Signature: PartnerServiceAdapter.savePartner(..) []
    2011-04-28 12:56:22,248 [19008539@qtp-17507279-3] DEBUG n.h.h.c.a.common.BeforeTxUCAspect [] Going to start adapter method with signature: PartnerServiceAdapter.savePartner(..) []
    2011-04-28 12:56:22,248 [19008539@qtp-17507279-3] DEBUG n.h.h.c.a.p.PartnerServiceAdapter [] Save partner on adapter called []


    Can somebody tell me what I am doing wrong?

    Thanks.

    Koudelka
Working...
X