Announcement Announcement Module
Collapse
No announcement yet.
Mixed AOP styles, how do I define ordering? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Mixed AOP styles, how do I define ordering?

    Hi all

    I'm kind of confused with my own setup...

    First the general question:
    how can I define the order of invocation of two around advices?

    More details follow:
    I've implemented a solution to handle transaction demarcation and session handling for non spring managed objects. Both seem to work, but I have some doubts regarding it being always sound.

    Basically I have a dao, which accepts an Hibernate Session. A dao is created by a service object ,StorageManager. Thus I inject a session into a newly created dao object by using

    Code:
        <aop:config>
            <aop:aspect id="sessionInject" ref="sessionAspect">
                <aop:pointcut id="getDomainDao"
                              expression="execution(* org.atalaya.isec.dashb.storage.StorageManager.get*Dao(..))"/>
                <aop:around
                        pointcut-ref="getDomainDao"
                        method="injectSession"/>
            </aop:aspect>
        </aop:config>
        <bean id="sessionAspect" class="org.atalaya.isec.aop.storage.SessionAspect">
            <property name="sessionProvider" ref="storageManager"/>
        </bean>
    Regarding transactions instead I'm using an aspect to inject a subclass of TransactionAspectSupport, still when creating the dao object. The configuration looks like

    Code:
        <bean id="targetAspect"
              class="org.atalaya.isec.aop.storage.TransactionAspect">
            <property name="transactionManager" ref="transactionManager"/>
            <property name="transactionAttributes">
                <props>
                    <prop key="prepare*">PROPAGATION_REQUIRED</prop>
                    <prop key="update*">PROPAGATION_REQUIRED</prop>
                    <prop key="save*">PROPAGATION_REQUIRED</prop>
                    <prop key="delete*">PROPAGATION_REQUIRED</prop>
                    <prop key="update*">PROPAGATION_REQUIRED</prop>
    
                </props>
            </property>
        </bean>
    
        <bean id="updateAspect"
              class="org.atalaya.isec.aop.update.UpdateAspect">
            <constructor-arg ref="targetAspect"/>
        </bean>
    
        <aop:config>
            <aop:aspect id="proxyThreadAspect" ref="updateAspect">
    
                <aop:pointcut id="createDao"
                              expression="execution ( * org.atalaya.isec.dashb.storage.StorageManager.get*Dao())"/>
                <aop:around
                        pointcut-ref="createDao"
                        method="proxyDao"/>
    
            </aop:aspect>
        </aop:config>
    Where UpdateAspect is

    Code:
    public class UpdateAspect {
    
        private Object aspect;
    
        public UpdateAspect(Object aspect) {
            this.aspect = aspect;
        }
    
        public Object proxyDao(ProceedingJoinPoint pjp) throws Throwable {
            Object returned = pjp.proceed();
            AspectJProxyFactory pfScanDao = new AspectJProxyFactory(returned);
            pfScanDao.addAspect(aspect);
            pfScanDao.setProxyTargetClass(true);
            pfScanDao.setTarget(returned);
            return pfScanDao.getProxy();
        }
    }

    and TransactionAspect is an @Aspect flavour of the spring TransactionAspectSupport:

    Code:
    @Aspect
    public class TransactionAspect extends TransactionAspectSupport {
    
        protected TransactionAspect() {
    
        }
    
        @Before("transactionalMethodExecution()")
        public void beforeMethodExecution(org.aspectj.lang.JoinPoint thisJoinPoint) {
            MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
            Method method = methodSignature.getMethod();
            //  Create transaction if necessary.
            TransactionInfo txInfo = createTransactionIfNecessary(method, thisJoinPoint.getTarget().getClass());
            if (logger.isDebugEnabled()) {
                logger.debug("Aspect-created transaction: " + txInfo);
            }
        }
    
        @AfterThrowing(pointcut = "transactionalMethodExecution()", throwing = "t")
        public void afterThrowing(Throwable t) {
            try {
                completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
            }
            catch (Throwable th) {
                logger.error("Failed to close transaction after throwing in a Transactional method", th);
            } finally {
                cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
            }
        }
    
        @AfterReturning("transactionalMethodExecution()")
        public void afterReturning() {
            commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
            cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
        }
    
        /*  @After("transactionalMethodExecution()")
        public void afterMethodExecution() {
            cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
        }*/
    
        @Pointcut("within(org.atalaya.isec.dao..*)")
        public void inDao() {
        }
    
        @Pointcut("inDao()")
        protected void transactionalMethodExecution() {
        }
    }
    So the whole thing works like the following:
    When someone calls StorageManager.getSomeDao() the SessionAspect is applied, injecting the session into the new object. Furthermore The UpdateAspect comes in place and proxies the dao with the TransactionAspect.
    Like this if someone calls dao.save(something) the transaction demarcation is applied.

    Now, the problem:
    Both SessionAspect and UpdateAspect work with an around advice, and tests show that the session is injected BEFORE the transaction proxy is created.

    Non-aop question follows:

    If a new session is created through SessionFactoryUtils.getSession(sessionFactory,true ) (I see the log trace of it being opened), will that session able to participate to the transaction?

    Sorry for the quite overdetailed and cross-cutting subject, maybe I should have opened two posts; sorry in that case...

    Any feedback is more than welcome
    Thanks
    Francesco
Working...
X