org.firebirdsql.jca.FBLocalTransaction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaybird Show documentation
Show all versions of jaybird Show documentation
JDBC Driver for the Firebird RDBMS
/*
* Firebird Open Source JavaEE Connector - JDBC Driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* 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
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a source control history command.
*
* All rights reserved.
*/
package org.firebirdsql.jca;
import org.firebirdsql.jdbc.FBConnection;
import org.firebirdsql.jdbc.SQLStateConstants;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.EISSystemException;
import javax.resource.spi.LocalTransactionException;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.sql.SQLException;
/**
* The class {@code FBLocalTransaction} implements LocalTransaction both
* in the cci and spi meanings. A flag is used to distinguish the current
* functionality. This class works by delegating the operations to the internal
* implementations of the XAResource functionality in FBManagedConnection.
*
* @author David Jencks
* @version 1.0
*/
public class FBLocalTransaction implements FirebirdLocalTransaction,
javax.resource.cci.LocalTransaction {
protected final FBManagedConnection mc;
protected Xid xid = null;
// used to determine if local transaction events notify
// ConnectionEventListeners see jca spec section 6.8. Basically
// not null means this is cci LocalTransaction, null means
// spi.LocalTransaction.
protected final ConnectionEvent beginEvent;
protected final ConnectionEvent commitEvent;
protected final ConnectionEvent rollbackEvent;
// should be package!!! perhaps reorganize and eliminate jdbc!!!
public FBLocalTransaction(FBManagedConnection mc, FBConnection c) {
this.mc = mc;
if (c == null) {
beginEvent = null;
commitEvent = null;
rollbackEvent = null;
} else {
beginEvent = new ConnectionEvent(mc,
ConnectionEvent.LOCAL_TRANSACTION_STARTED, null);
beginEvent.setConnectionHandle(c);
commitEvent = new ConnectionEvent(mc,
ConnectionEvent.LOCAL_TRANSACTION_COMMITTED, null);
commitEvent.setConnectionHandle(c);
rollbackEvent = new ConnectionEvent(mc,
ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK, null);
rollbackEvent.setConnectionHandle(c);
}
}
/**
* Get the associated Xid.
*
* @return instance of {@link Xid} representing a transaction ID that is managed by this local transaction.
*/
public Xid getXid() {
return xid;
}
/**
* Check whether a started transaction is associated with the current
* database connection.
*/
public boolean inTransaction() throws ResourceException {
try {
return mc.getGDSHelper().inTransaction();
} catch (SQLException ex) {
throw new FBResourceException(ex);
}
}
/**
* Begin a local transaction.
*
* @throws ResourceException
* generic exception if operation fails
* @throws LocalTransactionException
* error condition related to local transaction management
* @throws ResourceAdapterInternalException
* error condition internal to resource adapter
* @throws EISSystemException
* EIS instance specific error condition
*/
public void begin() throws ResourceException {
internalBegin();
}
/**
* Perform the internal operations to begin a local transaction.
*
* @throws ResourceException
* generic exception if operation fails
* @throws LocalTransactionException
* error condition related to local transaction management
* @throws ResourceAdapterInternalException
* error condition internal to resource adapter
* @throws EISSystemException
* EIS instance specific error condition
*/
public void internalBegin() throws ResourceException {
if (xid != null) {
// throw exception only if xid is known to the managed connection
if (mc.isXidActive(xid))
throw new FBResourceTransactionException(
"Local transaction active: can't begin another",
SQLStateConstants.SQL_STATE_TRANSACTION_ACTIVE);
}
xid = new FBLocalXid();
try {
mc.internalStart(xid, XAResource.TMNOFLAGS);
} catch (XAException | SQLException ex) {
xid = null;
throw new FBResourceException(ex);
}
if (beginEvent != null)
mc.notify(FBManagedConnection.localTransactionStartedNotifier, beginEvent);
}
/**
* Commit a local transaction.
*
* @throws ResourceException
* generic exception if operation fails
* @throws LocalTransactionException
* error condition related to local transaction management
* @throws ResourceAdapterInternalException
* error condition internal to resource adapter
* @throws EISSystemException
* EIS instance specific error condition
*/
public void commit() throws ResourceException {
internalCommit();
}
/**
* Perform the internal processing to commit a local transaction.
*
* @throws ResourceException
* generic exception if operation fails
* @throws LocalTransactionException
* error condition related to local transaction management
* @throws ResourceAdapterInternalException
* error condition internal to resource adapter
* @throws EISSystemException
* EIS instance specific error condition
*/
public void internalCommit() throws ResourceException {
// if there is no xid assigned, but we are still here,
// that means that automatic commit was called in managed
// scenario when managed connection was enlisted in global
// transaction
if (xid == null) return;
synchronized (mc.getSynchronizationObject()) {
try {
mc.internalEnd(xid, XAResource.TMSUCCESS);
mc.internalCommit(xid, true);
} catch (XAException ex) {
throw new FBResourceTransactionException(ex.getMessage(), ex);
} catch (SQLException ex) {
throw new FBResourceException(ex);
} finally {
xid = null;
}
if (commitEvent != null) {
mc.notify(FBManagedConnection.localTransactionCommittedNotifier, commitEvent);
}
}
}
/**
* Rollback a local transaction.
*
* @throws ResourceException
* generic exception if operation fails
* @throws LocalTransactionException
* error condition related to local transaction management
* @throws ResourceAdapterInternalException
* error condition internal to resource adapter
* @throws EISSystemException
* EIS instance specific error condition
*/
public void rollback() throws ResourceException {
internalRollback();
}
/**
* Perform the internal processing to rollback a local transaction.
*
* @throws ResourceException
* generic exception if operation fails
* @throws LocalTransactionException
* error condition related to local transaction management
* @throws ResourceAdapterInternalException
* error condition internal to resource adapter
* @throws EISSystemException
* EIS instance specific error condition
*/
public void internalRollback() throws ResourceException {
// if there is no xid assigned, but we are still here,
// that means that automatic commit was called in managed
// scenario when managed connection was enlisted in global
// transaction
if (xid == null) return;
synchronized (mc.getSynchronizationObject()) {
try {
mc.internalEnd(xid, XAResource.TMSUCCESS); // ??? on flags
// --FBManagedConnection is its own XAResource
mc.internalRollback(xid);
} catch (XAException | SQLException ex) {
throw new FBResourceTransactionException(ex.getMessage(), ex);
} finally {
xid = null;
}
if (rollbackEvent != null) {
mc.notify(FBManagedConnection.localTransactionRolledbackNotifier, rollbackEvent);
}
}
}
// This is an intentionally non-implemented xid, so if prepare is called
// with it, it won't work.
// Only object identity works for equals!
public static class FBLocalXid implements Xid {
private static final int formatId = 0x0102;// ????????????
private String strValue;
public FBLocalXid() {
strValue = "Xid[" + hashCode() + "]";
}
/**
* Return the global transaction id of this transaction.
*/
public byte[] getGlobalTransactionId() {
return null;
}
/**
* Return the branch qualifier of this transaction.
*/
public byte[] getBranchQualifier() {
return null;
}
/**
* Return the format identifier of this transaction.
*
* The format identifier augments the global id and specifies how the
* global id and branch qualifier should be interpreted.
*
*/
public int getFormatId() {
return formatId;
}
public String toString() {
return strValue;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy