Package com.blazebit.cdi.transaction

Source Code of com.blazebit.cdi.transaction.TransactionalInterceptor

/*
* Copyright 2011 Blazebit
*/
package com.blazebit.cdi.transaction;

import java.io.Serializable;
import java.lang.reflect.Method;

import javax.annotation.Resource;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import javax.transaction.Status;
import javax.transaction.UserTransaction;

import com.blazebit.annotation.AnnotationUtil;
import com.blazebit.cdi.transaction.annotation.Transactional;
import com.blazebit.exception.ExceptionUtil;

/**
* This interceptor executes a intercepted method within a JTA trasaction. When
* requires new is set to true, a nested transaction should be started, but JTA
* does not support nested transactions. Methods that are called from within the
* method, which are also annotated with @Transactional will join the parent
* transaction. The most outer interceptor that started the transaction is
* responsible for commiting and rollback.
*
* A commit is always done when the most outer intercepted method exits, but a
* rollback only if it throws a Throwable.
*
* Setting the requiresNew attribute to true will throw an
* UnsupportedOperationException
*
* <code>
* public class Bean implements Serializable {
*
* @Transactional public void example() { // code } } </code>
*
*                The code of the example method will be invoked between,
*                UserTransaction.begin() and UserTransaction.commit() or
*                UserTransaction.rollback().
*
* @author Christian Beikov
* @since 0.1.2
* @see Transactional
*/
@Transactional
@Interceptor
public class TransactionalInterceptor implements Serializable {

  private static final long serialVersionUID = 1L;
  @Resource
  private UserTransaction utx;

  @SuppressWarnings("unused")
  @AroundInvoke
  public Object applyTransaction(InvocationContext ic) throws Exception {
    Method m = ic.getMethod();
    Object targetObject = ic.getTarget();
    Class<?> targetClass = targetObject == null ? m.getDeclaringClass()
        : targetObject.getClass();
    Transactional transactionalAnnotation = AnnotationUtil.findAnnotation(
        m, targetClass, Transactional.class);
    Object ret;

    if (transactionalAnnotation == null) {
      throw new IllegalStateException(
          "The interceptor annotation can not be determined!");
    }

    if (transactionalAnnotation != null) {
      if (!transactionalAnnotation.requiresNew()) {
        boolean startedTransaction = false;

        if (utx.getStatus() != Status.STATUS_ACTIVE) {
          utx.begin();
          startedTransaction = true;
        }

        try {
          ret = ic.proceed();

          if (startedTransaction) {
            utx.commit();

          }
        } catch (Throwable t) {
          if (startedTransaction) {
            utx.rollback();
          }

          // Check if the throwable is an instance of
          // InvocationTargetException
          // and if so, unwrap the cause. OWB did not unwrap
          // exceptions that
          // have been thrown in decorators in some versions so we
          // need to do
          // this to be able to log the right exception
          Throwable t1 = ExceptionUtil
              .unwrapInvocationTargetException(t);

          // Cast to or wrap the throwable into a new exception and
          // rethrow it
          if (t1 instanceof Exception) {
            throw (Exception) t1;
          }

          throw new Exception(t1);
        }
      } else {
        throw new UnsupportedOperationException("Not supported yet.");
      }
    } else {
      ret = ic.proceed();
    }

    return ret;

  }
}
TOP

Related Classes of com.blazebit.cdi.transaction.TransactionalInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.