/**
* Copyright 2014-2016 yangming.liu<bytefox@126.com>.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
package org.bytesoft.bytetcc.supports.rpc;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;
import org.bytesoft.bytejta.supports.rpc.TransactionRequestImpl;
import org.bytesoft.bytejta.supports.rpc.TransactionResponseImpl;
import org.bytesoft.bytejta.supports.wire.RemoteCoordinator;
import org.bytesoft.compensable.CompensableBeanFactory;
import org.bytesoft.compensable.CompensableManager;
import org.bytesoft.compensable.CompensableTransaction;
import org.bytesoft.compensable.aware.CompensableBeanFactoryAware;
import org.bytesoft.transaction.TransactionContext;
import org.bytesoft.transaction.supports.rpc.TransactionInterceptor;
import org.bytesoft.transaction.supports.rpc.TransactionRequest;
import org.bytesoft.transaction.supports.rpc.TransactionResponse;
import org.bytesoft.transaction.xa.TransactionXid;
import org.bytesoft.transaction.xa.XidFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CompensableInterceptorImpl implements TransactionInterceptor, CompensableBeanFactoryAware {
static final Logger logger = LoggerFactory.getLogger(CompensableInterceptorImpl.class);
private CompensableBeanFactory beanFactory;
public void beforeSendRequest(TransactionRequest request) throws IllegalStateException {
CompensableManager compensableManager = this.beanFactory.getCompensableManager();
XidFactory xidFactory = this.beanFactory.getCompensableXidFactory();
CompensableTransaction transaction = compensableManager.getCompensableTransactionQuietly();
if (transaction == null) {
return;
}
TransactionContext srcTransactionContext = transaction.getTransactionContext();
TransactionContext transactionContext = srcTransactionContext.clone();
TransactionXid currentXid = srcTransactionContext.getXid();
TransactionXid globalXid = xidFactory.createGlobalXid(currentXid.getGlobalTransactionId());
transactionContext.setXid(globalXid);
request.setTransactionContext(transactionContext);
try {
RemoteCoordinator resource = request.getTargetTransactionCoordinator();
RemoteResourceDescriptor descriptor = new RemoteResourceDescriptor();
descriptor.setDelegate(resource);
descriptor.setIdentifier(resource.getIdentifier());
boolean participantEnlisted = transaction.enlistResource(descriptor);
((TransactionRequestImpl) request).setParticipantEnlistFlag(participantEnlisted);
} catch (IllegalStateException ex) {
logger.error("CompensableInterceptorImpl.beforeSendRequest({})", request, ex);
throw ex;
} catch (RollbackException ex) {
transaction.setRollbackOnlyQuietly();
logger.error("CompensableInterceptorImpl.beforeSendRequest({})", request, ex);
throw new IllegalStateException(ex);
} catch (SystemException ex) {
logger.error("CompensableInterceptorImpl.beforeSendRequest({})", request, ex);
throw new IllegalStateException(ex);
}
}
public void afterReceiveRequest(TransactionRequest request) throws IllegalStateException {
TransactionContext srcTransactionContext = request.getTransactionContext();
if (srcTransactionContext == null) {
return;
}
RemoteCoordinator compensableCoordinator = this.beanFactory.getCompensableCoordinator();
TransactionContext transactionContext = srcTransactionContext.clone();
transactionContext.setPropagatedBy(srcTransactionContext.getPropagatedBy());
try {
compensableCoordinator.start(transactionContext, XAResource.TMNOFLAGS);
} catch (XAException ex) {
logger.error("CompensableInterceptorImpl.afterReceiveRequest({})", request, ex);
IllegalStateException exception = new IllegalStateException();
exception.initCause(ex);
throw exception;
}
}
public void beforeSendResponse(TransactionResponse response) throws IllegalStateException {
CompensableManager compensableManager = this.beanFactory.getCompensableManager();
CompensableTransaction transaction = compensableManager.getCompensableTransactionQuietly();
if (transaction == null) {
return;
}
RemoteCoordinator compensableCoordinator = this.beanFactory.getCompensableCoordinator();
TransactionContext srcTransactionContext = transaction.getTransactionContext();
TransactionContext transactionContext = srcTransactionContext.clone();
transactionContext.setPropagatedBy(srcTransactionContext.getPropagatedBy());
response.setTransactionContext(transactionContext);
try {
compensableCoordinator.end(transactionContext, XAResource.TMSUCCESS);
} catch (XAException ex) {
logger.error("CompensableInterceptorImpl.beforeSendResponse({})", response, ex);
IllegalStateException exception = new IllegalStateException();
exception.initCause(ex);
throw exception;
}
}
public void afterReceiveResponse(TransactionResponse response) throws IllegalStateException {
CompensableManager compensableManager = this.beanFactory.getCompensableManager();
TransactionContext remoteTransactionContext = response.getTransactionContext();
CompensableTransaction transaction = compensableManager.getCompensableTransactionQuietly();
boolean participantEnlistFlag = ((TransactionResponseImpl) response).isParticipantEnlistFlag();
boolean participantDelistFlag = ((TransactionResponseImpl) response).isParticipantDelistFlag();
if (transaction == null || remoteTransactionContext == null) {
return;
} else if (participantEnlistFlag == false) {
return;
}
try {
RemoteCoordinator resource = response.getSourceTransactionCoordinator();
RemoteResourceDescriptor descriptor = new RemoteResourceDescriptor();
descriptor.setDelegate(resource);
descriptor.setIdentifier(resource.getIdentifier());
transaction.delistResource(descriptor, participantDelistFlag ? XAResource.TMFAIL : XAResource.TMSUCCESS);
} catch (IllegalStateException ex) {
logger.error("CompensableInterceptorImpl.afterReceiveResponse({})", response, ex);
throw ex;
} catch (SystemException ex) {
logger.error("CompensableInterceptorImpl.afterReceiveResponse({})", response, ex);
throw new IllegalStateException(ex);
}
}
public void setBeanFactory(CompensableBeanFactory tbf) {
this.beanFactory = tbf;
}
public CompensableBeanFactory getBeanFactory() {
return beanFactory;
}
}