/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2007-2011, Red Hat Inc. or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.hibernate.engine.transaction.internal.jta;

import javax.transaction.SystemException;
import javax.transaction.TransactionManager;

import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.spi.AbstractTransactionImpl;
import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.JoinStatus;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;

Implements a transaction strategy for Container Managed Transaction (CMT) scenarios. All work is done in the context of the container managed transaction.

The term 'CMT' is potentially misleading; the pertinent point simply being that the transactions are being managed by something other than the Hibernate transaction mechanism.

Additionally, this strategy does *not* attempt to access or use the UserTransaction since in the actual case CMT access to the UserTransaction is explicitly disallowed. Instead we use the JTA Transaction object obtained from the TransactionManager
Author:Gavin King, Steve Ebersole
/** * Implements a transaction strategy for Container Managed Transaction (CMT) scenarios. All work is done in * the context of the container managed transaction. * <p/> * The term 'CMT' is potentially misleading; the pertinent point simply being that the transactions are being * managed by something other than the Hibernate transaction mechanism. * <p/> * Additionally, this strategy does *not* attempt to access or use the {@link javax.transaction.UserTransaction} since * in the actual case CMT access to the {@link javax.transaction.UserTransaction} is explicitly disallowed. Instead * we use the JTA {@link javax.transaction.Transaction} object obtained from the {@link TransactionManager} * * @author Gavin King * @author Steve Ebersole */
public class CMTTransaction extends AbstractTransactionImpl { private JoinStatus joinStatus = JoinStatus.NOT_JOINED; protected CMTTransaction(TransactionCoordinator transactionCoordinator) { super( transactionCoordinator ); } protected TransactionManager transactionManager() { return jtaPlatform().retrieveTransactionManager(); } private TransactionManager getTransactionManager() { return transactionManager(); } @Override protected void doBegin() { transactionCoordinator().pulse(); } @Override protected void afterTransactionBegin() { if ( ! transactionCoordinator().isSynchronizationRegistered() ) { throw new TransactionException("Could not register synchronization for container transaction"); } transactionCoordinator().sendAfterTransactionBeginNotifications( this ); transactionCoordinator().getTransactionContext().afterTransactionBegin( this ); } @Override protected void beforeTransactionCommit() { boolean flush = ! transactionCoordinator().getTransactionContext().isFlushModeNever() && ! transactionCoordinator().getTransactionContext().isFlushBeforeCompletionEnabled(); if ( flush ) { // if an exception occurs during flush, user must call rollback() transactionCoordinator().getTransactionContext().managedFlush(); } } @Override protected void doCommit() { // nothing to do } @Override protected void beforeTransactionRollBack() { // nothing to do } @Override protected void doRollback() { markRollbackOnly(); } @Override protected void afterTransactionCompletion(int status) { // nothing to do } @Override protected void afterAfterCompletion() { // nothing to do } @Override public boolean isActive() throws TransactionException { return JtaStatusHelper.isActive( getTransactionManager() ); } @Override public IsolationDelegate createIsolationDelegate() { return new JtaIsolationDelegate( transactionCoordinator() ); } @Override public boolean isInitiator() { return false; // cannot be } @Override public void markRollbackOnly() { try { getTransactionManager().setRollbackOnly(); } catch ( SystemException se ) { throw new TransactionException("Could not set transaction to rollback only", se); } } @Override public void markForJoin() { joinStatus = JoinStatus.MARKED_FOR_JOINED; } @Override public void join() { if ( joinStatus != JoinStatus.MARKED_FOR_JOINED ) { return; } if ( JtaStatusHelper.isActive( transactionManager() ) ) { // register synchronization if needed transactionCoordinator().pulse(); joinStatus = JoinStatus.JOINED; } else { joinStatus = JoinStatus.NOT_JOINED; } } @Override public void resetJoinStatus() { joinStatus = JoinStatus.NOT_JOINED; } boolean isJoinable() { return ( joinStatus == JoinStatus.JOINED || joinStatus == JoinStatus.MARKED_FOR_JOINED ) && JtaStatusHelper.isActive( transactionManager() ); } @Override public JoinStatus getJoinStatus() { return joinStatus; } }