io.agroal.narayana.LocalXAResource Maven / Gradle / Ivy
The newest version!
// Copyright (C) 2017 Red Hat, Inc. and individual contributors as indicated by the @author tags.
// You may not use this file except in compliance with the Apache License, Version 2.0.
package io.agroal.narayana;
import io.agroal.api.transaction.TransactionAware;
import org.jboss.tm.LastResource;
import org.jboss.tm.XAResourceWrapper;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import static javax.transaction.xa.XAException.XAER_INVAL;
import static javax.transaction.xa.XAException.XAER_NOTA;
import static javax.transaction.xa.XAException.XAER_RMERR;
import static javax.transaction.xa.XAException.XA_RBROLLBACK;
/**
* @author Luis Barreiro
* @author Jesper Pedersen
*/
public class LocalXAResource implements XAResourceWrapper, LastResource {
private static final String PRODUCT_NAME = LocalXAResource.class.getPackage().getImplementationTitle();
private static final String PRODUCT_VERSION = LocalXAResource.class.getPackage().getImplementationVersion();
private final TransactionAware transactionAware;
private final String jndiName;
private Xid currentXid;
public LocalXAResource(TransactionAware transactionAware, String jndiName) {
this.transactionAware = transactionAware;
this.jndiName = jndiName;
}
public Object getConnection() throws Throwable {
return transactionAware.getConnection();
}
@Override
public void start(Xid xid, int flags) throws XAException {
if ( currentXid == null ) {
if ( flags != TMNOFLAGS ) {
throw XAExceptionUtils.xaException( XAER_INVAL, "Starting resource with wrong flags" );
}
try {
transactionAware.transactionStart();
} catch ( Exception t ) {
transactionAware.setFlushOnly();
throw XAExceptionUtils.xaException( XAER_RMERR, "Error trying to start local transaction: ", t );
}
currentXid = xid;
} else {
if ( flags != TMJOIN && flags != TMRESUME ) {
throw XAExceptionUtils.xaException( XAException.XAER_DUPID, "Invalid flag for join|resume" );
}
}
}
@Override
public void commit(Xid xid, boolean onePhase) throws XAException {
if ( xid == null || !xid.equals( currentXid ) ) {
throw XAExceptionUtils.xaException( XAER_NOTA, "Invalid xid to transactionCommit" );
}
currentXid = null;
try {
transactionAware.transactionBeforeCompletion( true );
transactionAware.transactionCommit();
} catch ( Exception t ) {
transactionAware.setFlushOnly();
throw XAExceptionUtils.xaException( onePhase ? XA_RBROLLBACK : XAER_RMERR, "Error trying to transactionCommit local transaction: ", t );
}
}
@Override
public void rollback(Xid xid) throws XAException {
if ( xid == null || !xid.equals( currentXid ) ) {
throw XAExceptionUtils.xaException( XAER_NOTA, "Invalid xid to transactionRollback" );
}
currentXid = null;
try {
transactionAware.transactionBeforeCompletion( false );
transactionAware.transactionRollback();
} catch ( Exception t ) {
transactionAware.setFlushOnly();
throw XAExceptionUtils.xaException( XAER_RMERR, "Error trying to transactionRollback local transaction: ", t );
}
}
@Override
public void end(Xid xid, int flags) throws XAException {
if ( xid == null || !xid.equals( currentXid ) ) {
transactionAware.setFlushOnly();
throw XAExceptionUtils.xaException( XAER_NOTA, "Invalid xid to transactionEnd" );
}
}
@Override
public void forget(Xid xid) throws XAException {
transactionAware.setFlushOnly();
throw XAExceptionUtils.xaException( XAER_NOTA, "Forget not supported in local XA resource" );
}
@Override
public int getTransactionTimeout() throws XAException {
return 0;
}
@Override
public boolean isSameRM(XAResource xaResource) throws XAException {
return this == xaResource;
}
@Override
public int prepare(Xid xid) throws XAException {
return XA_OK;
}
@Override
public Xid[] recover(int flags) throws XAException {
transactionAware.setFlushOnly();
throw XAExceptionUtils.xaException( XAER_RMERR, "No recover in local XA resource");
}
@Override
public boolean setTransactionTimeout(int timeout) throws XAException {
return false;
}
// --- XA Resource Wrapper //
@Override
public XAResource getResource() {
return this;
}
@Override
public String getProductName() {
return PRODUCT_NAME;
}
@Override
public String getProductVersion() {
return PRODUCT_VERSION;
}
@Override
public String getJndiName() {
return jndiName;
}
}