/**
* Copyright (C) 2000-2016 Atomikos <info@atomikos.com>
*
* LICENSE CONDITIONS
*
* See http://www.atomikos.com/Main/WhichLicenseApplies for details.
*/
package com.atomikos.datasource.xa.session;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import com.atomikos.datasource.xa.XAResourceTransaction;
import com.atomikos.datasource.xa.XATransactionalResource;
import com.atomikos.icatch.CompositeTransaction;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;
/**
*
*
* State handler for when enlisted in an XA branch.
*
*/
class BranchEnlistedStateHandler extends TransactionContextStateHandler
{
private static final Logger LOGGER = LoggerFactory.createLogger(BranchEnlistedStateHandler.class);
private CompositeTransaction ct;
private XAResourceTransaction branch;
BranchEnlistedStateHandler ( XATransactionalResource resource , CompositeTransaction ct , XAResource xaResource)
{
super ( resource , xaResource );
this.ct = ct;
this.branch = ( XAResourceTransaction ) resource.getResourceTransaction ( ct );
branch.setXAResource ( xaResource );
branch.resume();
}
public BranchEnlistedStateHandler (
XATransactionalResource resource, CompositeTransaction ct,
XAResource xaResource , XAResourceTransaction branch ) throws InvalidSessionHandleStateException
{
super ( resource , xaResource );
this.ct = ct;
this.branch = branch;
branch.setXAResource ( xaResource );
try {
branch.xaResume();
} catch ( XAException e ) {
String msg = "Failed to resume branch: " + branch;
throw new InvalidSessionHandleStateException ( msg );
}
}
TransactionContextStateHandler checkEnlistBeforeUse ( CompositeTransaction currentTx)
throws InvalidSessionHandleStateException, UnexpectedTransactionContextException
{
if ( currentTx == null || !currentTx.isSameTransaction ( ct ) ) {
//OOPS! we are being used a different tx context than the one expected...
//TODO check: what if subtransaction? Possible solution: ignore if serial_jta mode, error otherwise.
String msg = "The connection/session object is already enlisted in a (different) transaction.";
if ( LOGGER.isTraceEnabled() ) LOGGER.logTrace ( msg );
throw new UnexpectedTransactionContextException();
}
//tx context is still the same -> no change in state required
return null;
}
TransactionContextStateHandler sessionClosed()
{
return new BranchEndedStateHandler ( getXATransactionalResource() , branch , ct );
}
TransactionContextStateHandler transactionTerminated ( CompositeTransaction tx )
{
TransactionContextStateHandler ret = null;
if ( ct.isSameTransaction ( tx ) ) ret = new NotInBranchStateHandler ( getXATransactionalResource() , getXAResource() );
return ret;
}
public TransactionContextStateHandler transactionSuspended() throws InvalidSessionHandleStateException
{
try {
branch.xaSuspend();
} catch ( XAException e ) {
LOGGER.logWarning ( "Error in suspending transaction context for transaction: " + ct , e );
String msg = "Failed to suspend branch: " + branch;
throw new InvalidSessionHandleStateException ( msg , e );
}
return new BranchSuspendedStateHandler ( getXATransactionalResource() , branch , ct , getXAResource() );
}
boolean isInTransaction ( CompositeTransaction tx )
{
return ct.isSameTransaction ( tx );
}
}