All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mysema.rdfbean.guice.TransactionalInterceptor Maven / Gradle / Ivy

There is a newer version: 1.7.1
Show newest version
/*
 * Copyright (c) 2009 Mysema Ltd.
 * All rights reserved.
 *
 */
package com.mysema.rdfbean.guice;

import java.lang.reflect.Method;
import java.util.Map;

import javax.annotation.concurrent.ThreadSafe;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.transaction.annotation.Transactional;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.mysema.rdfbean.model.RDFBeanTransaction;
import com.mysema.rdfbean.object.FlushMode;
import com.mysema.rdfbean.object.Session;
import com.mysema.rdfbean.object.SessionFactory;
import com.mysema.rdfbean.object.SimpleSessionContext;
import com.mysema.rdfbean.object.TxException;


/**
 * TransactionalInterceptor provides a MethodInterceptor implementation for
 * transactional method interception
 *
 * @author tiwe
 * @version $Id$
 *
 */
@ThreadSafe
class TransactionalInterceptor implements MethodInterceptor{

    private final Provider> configuration;

    private SimpleSessionContext sessionContext;

    public TransactionalInterceptor(Provider> configuration) {
        this.configuration = configuration;
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable { //NOSONAR
        Transactional annotation = configuration.get().get(methodInvocation.getMethod());
        boolean inSession = false;
        boolean inTx = false;
        if (sessionContext.getCurrentSession() != null){
            inSession = true;
            Session session = sessionContext.getCurrentSession();
            inTx = session.getTransaction() != null && session.getTransaction().isActive();
        }

        boolean intercepted = isIntercepted(annotation, inTx);
        if (!intercepted){
            return methodInvocation.proceed();
        }

        Session session = sessionContext.getOrCreateSession();
        FlushMode savedFlushMode = session.getFlushMode();

        try {
            RDFBeanTransaction txn = doBegin(session, annotation);
            Object result;
            try {
                result = methodInvocation.proceed();
            } catch(Exception e) {
                if (txn.isRollbackOnly() || isRollbackNecessary(annotation, e, txn)){
                    doRollback(txn);
                }else{
                    doCommit(session, txn);
                }
                throw e;
            }
            if (!txn.isRollbackOnly()){
                doCommit(session, txn);
            }else{
                doRollback(txn);
            }
            return result;

        } finally {
            session.setFlushMode(savedFlushMode);
            sessionContext.releaseSession();
            if (!inSession){
                session.close();
            }
        }
    }

    private boolean isIntercepted(Transactional annotation, boolean inTx) {
        switch(annotation.propagation()){
        case REQUIRED:
        case REQUIRES_NEW:
        case NESTED:
            if (inTx){
                return false;
            }
            break;

        case MANDATORY:
            if (inTx){
                return false;
            }else{
                throw new TxException("Tx propagation " + annotation.propagation() + " without transaction");
            }

        case NOT_SUPPORTED:
        case NEVER:
            if (inTx){
                throw new TxException("Tx propagation " + annotation.propagation() + " in transaction");
            }else{
                return false;
            }
        }
        return true;
    }

    private RDFBeanTransaction doBegin(Session session, Transactional transactional) {
        RDFBeanTransaction txn = session.beginTransaction(
                transactional.readOnly(),
                transactional.timeout(),
                transactional.isolation().value());

        session.setFlushMode(FlushMode.COMMIT);
        return txn;
    }

    private void doCommit(Session session, RDFBeanTransaction txn) throws Exception {
        Exception commitException = null;
        try {
            session.flush();
            txn.commit();

        } catch(RuntimeException re) {
            doRollback(txn);
            commitException = re;
        }

        if (commitException != null){
            throw commitException;
        }
    }

    private void doRollback(RDFBeanTransaction txn) {
        txn.rollback();
    }

    private boolean isRollbackNecessary(Transactional transactional, Exception e, RDFBeanTransaction txn) {
        boolean rollBack = false;
        for (Class rollBackOn : transactional.rollbackFor()) {
            if (rollBackOn.isInstance(e)) {
                rollBack = true;
                for (Class exceptOn : transactional.noRollbackFor()) {
                    if (exceptOn.isInstance(e)) {
                        rollBack = false;
                        break;
                    }
                }
                break;
            }
        }
        return rollBack;
    }

    @Inject
    public void setSessionFactory(SessionFactory sessionFactory){
        this.sessionContext = new SimpleSessionContext(sessionFactory);
        sessionFactory.setSessionContext(sessionContext);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy