/** * Copyright (C) 2012 Stephan Classen * Based on guice-perist (Copyright (C) 2010 Google, Inc.) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.sclassen.guicejpa; import static com.google.common.base.Preconditions.checkNotNull; import java.lang.annotation.Annotation; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import org.aopalliance.intercept.MethodInterceptor; /** * {@link MethodInterceptor} for intercepting methods of persistence units of type RESOURCE_LOCAL. * * @author Stephan Classen */ class ResourceLocalTxnInterceptor extends AbstractTxnInterceptor { // ---- Constructor /** * Constructor. * * @param emProvider the provider for {@link EntityManager}. Must not be {@code null}. * @param puAnntoation the annotation of the persistence unit this interceptor belongs to. * @param peTranslator the {@link PersistenceExceptionTranslator}. Can be {@code null}. */ public ResourceLocalTxnInterceptor(EntityManagerProviderImpl emProvider, Class<? extends Annotation> puAnntoation, PersistenceExceptionTranslator<?> peTranslator) { super(emProvider, emProvider, puAnntoation, peTranslator); checkNotNull(emProvider); } // ---- Methods /** * {@inheritDoc} */ @Override protected TransactionFacade getTransactionFacade(final EntityManager em) { final EntityTransaction txn = em.getTransaction(); if (txn.isActive()) { return new InnerTransaction(txn); } return new OuterTransaction(txn); } // ---- Inner Classes /** * TransactionFacade representing an inner (nested) transaction. * Starting and committing a transaction has no effect. * This Facade will set the rollbackOnly flag in case of a roll back. */ private static class InnerTransaction implements TransactionFacade { private final EntityTransaction txn; InnerTransaction(EntityTransaction txn) { this.txn = txn; } /** * {@inheritDoc} */ @Override public void begin() { // Do nothing } /** * {@inheritDoc} */ @Override public void commit() { // Do nothing } /** * {@inheritDoc} */ @Override public void rollback() { txn.setRollbackOnly(); } } /** * TransactionFacade representing an outer transaction. * This Facade starts and ends the transaction. * If an inner transaction has set the rollbackOnly flag the transaction will be rolled back * in any case. */ private static class OuterTransaction implements TransactionFacade { private final EntityTransaction txn; /** * {@inheritDoc} */ OuterTransaction(EntityTransaction txn) { this.txn = txn; } /** * {@inheritDoc} */ @Override public void begin() { txn.begin(); } /** * {@inheritDoc} */ @Override public void commit() { if (txn.getRollbackOnly()) { txn.rollback(); } else { txn.commit(); } } /** * {@inheritDoc} */ @Override public void rollback() { txn.rollback(); } } }