User: mulder
Date: 00/06/02 06:48:49
Added: src/main/org/jboss/minerva/xa TransactionListener.java
XAClientConnection.java XAConnectionImpl.java
XADataSourceImpl.java XAResourceImpl.java
package.html
Log:
Initial entry of Minerva JDBC Pools into CVS.
Pools, DataSources, and other non-jBoss-dependent code is under
org.jboss.minerva.*
JavaDoc source HTML files are included - the package comments are in
the package.html files in the various packages, and the overview
comments are in org/jboss/minerva/minerva.html
MBeans to load a pool into jBoss are in org.jboss.jdbc
A new logging Writer is on org.jboss.logging.
Revision Changes Path
1.1 jboss/src/main/org/jboss/minerva/xa/TransactionListener.java
Index: TransactionListener.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.minerva.xa;
/**
* Callback for notification when a transaction is finished.
* @version $Revision: 1.1 $
* @author Aaron Mulder ([EMAIL PROTECTED])
*/
public interface TransactionListener {
/**
* Indicates that the transaction this instance was part of has finished.
*/
public void transactionFinished(XAConnectionImpl con);
}
1.1 jboss/src/main/org/jboss/minerva/xa/XAClientConnection.java
Index: XAClientConnection.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.minerva.xa;
import java.sql.*;
import java.util.*;
import org.jboss.minerva.jdbc.*;
import org.jboss.minerva.pools.*;
/**
* Wrapper for database connections used by an XAConnection. When close is
* called, it does not close the underlying connection, just informs the
* XAConnection that close was called. The connection will not be closed (or
* returned to the pool) until the transactional details are taken care of.
* This instance only lives as long as one client is using it - though we
* probably want to consider reusing it to save object allocations.
* @version $Revision: 1.1 $
* @author Aaron Mulder ([EMAIL PROTECTED])
*/
public class XAClientConnection implements ConnectionWrapper {
private final static String CLOSED = "Connection has been closed!";
private Connection con;
private HashSet statements;
private Vector listeners;
private XAConnectionImpl xaCon;
/**
* Creates a new connection wrapper.
* @param xaCon The handler for all the transactional details.
* @param con The "real" database connection to wrap.
*/
public XAClientConnection(XAConnectionImpl xaCon, Connection con) {
this.con = con;
this.xaCon = xaCon;
statements = new HashSet();
listeners = new Vector();
}
/**
* Gets a reference to the "real" connection. This should only be used if
* you need to cast that to a specific type to call a proprietary method -
* you will defeat all the pooling if you use the underlying connection
* directly.
*/
public Connection getUnderlyingConnection() {
return con;
}
/**
* Closes this connection wrapper permanently. All further calls with throw
* a SQLException.
*/
public void shutdown() {
con = null;
statements = null;
listeners = null;
xaCon = null;
}
/**
* Updates the last used time for this connection to the current time.
* This is not used by the current implementation.
*/
public void setLastUsed() {
}
/**
* Indicates that an error occured on this connection.
*/
public void setError(SQLException e) {
xaCon.setConnectionError(e);
}
/**
* Indicates that a statement has been closed and no longer needs to be
* tracked. Outstanding statements are closed when the connection is
* returned to the pool.
*/
public void statementClosed(Statement st) {
statements.remove(st);
}
// ---- Implementation of java.sql.Connection ----
public Statement createStatement() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
StatementInPool st = new StatementInPool(con.createStatement(), this);
statements.add(st);
return st;
} catch(SQLException e) {
setError(e);
throw e;
}
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.prepareStatement(sql);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public CallableStatement prepareCall(String sql) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.prepareCall(sql);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public String nativeSQL(String sql) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.nativeSQL(sql);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.setAutoCommit(autoCommit);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public boolean getAutoCommit() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.getAutoCommit();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void commit() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.commit();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void rollback() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.rollback();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void close() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
Collection copy = (Collection)statements.clone();
Iterator it = copy.iterator();
while(it.hasNext())
try {
((Statement)it.next()).close();
} catch(SQLException e) {}
xaCon.clientConnectionClosed();
shutdown();
}
public boolean isClosed() throws SQLException {
if(con == null) return true;
try {
return con.isClosed();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public DatabaseMetaData getMetaData() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.getMetaData();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void setReadOnly(boolean readOnly) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.setReadOnly(readOnly);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public boolean isReadOnly() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.isReadOnly();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void setCatalog(String catalog) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.setCatalog(catalog);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public String getCatalog() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.getCatalog();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void setTransactionIsolation(int level) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.setTransactionIsolation(level);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public int getTransactionIsolation() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.getTransactionIsolation();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public SQLWarning getWarnings() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.getWarnings();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void clearWarnings() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.clearWarnings();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public Statement createStatement(int resultSetType, int resultSetConcurrency)
throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
StatementInPool st = new
StatementInPool(con.createStatement(resultSetType, resultSetConcurrency), this);
statements.add(st);
return st;
} catch(SQLException e) {
setError(e);
throw e;
}
}
public PreparedStatement prepareStatement(String sql, int resultSetType, int
resultSetConcurrency) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.prepareStatement(sql, resultSetType, resultSetConcurrency);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public CallableStatement prepareCall(String sql, int resultSetType, int
resultSetConcurrency) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.prepareCall(sql, resultSetType, resultSetConcurrency);
} catch(SQLException e) {
setError(e);
throw e;
}
}
public Map getTypeMap() throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
return con.getTypeMap();
} catch(SQLException e) {
setError(e);
throw e;
}
}
public void setTypeMap(Map map) throws SQLException {
if(con == null) throw new SQLException(CLOSED);
try {
con.setTypeMap(map);
} catch(SQLException e) {
setError(e);
throw e;
}
}
}
1.1 jboss/src/main/org/jboss/minerva/xa/XAConnectionImpl.java
Index: XAConnectionImpl.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.minerva.xa;
import java.sql.*;
import java.util.Vector;
import javax.sql.*;
import javax.transaction.xa.XAResource;
/**
* A transaction wrapper around a java.sql.Connection. This provides access to
* an XAResource (there is a one-to-one mapping between XAResource and
* XAConnection) and a java.sql.Connection (in this implementation, there is
* also a one-to-one mapping between XAConnection and java.sql.Connection).
* In order to pool java.sql.Connections in a transactional environment, this
* is the class that should be pooled - though you could pool the connections,
* there is no need to create and destroy these wrappers so frequently.
*
* <P>Note that there con only be one transaction at a time accessing one of
* these wrappers, and requests to a pool for multiple connections on behalf of
* one transaction should use the same wrapper. This is because there is no
* distinction between connections and transactions in a java.sql.Connection,
* and work done by one connection on behalf of a transaction would not be
* visible to another connection working on behalf of the same transaction - you
* would have effectively created two transactions.</P>
*
* <P>This also implies that an XAConnection should not be released to a
* connection pool until the work has been committed or rolled back. However,
* it must sent the close notification as usual in order to be delisted from
* the transaction. So the ConnectionEventListener must not release the
* XAConnection to a pool when it receives the close event. Instead, it should
* also register a TransactionListener that will be notified when the
* Transaction is finished, and release the XAConnection at that time.</P>
* @see org.jboss.minerva.xa.TransactionListener
* @version $Revision: 1.1 $
* @author Aaron Mulder ([EMAIL PROTECTED])
*/
public class XAConnectionImpl implements XAConnection {
private final static String CLOSED = "Connection has been closed!";
private Connection con;
private XAResourceImpl resource;
private Vector listeners;
private TransactionListener transListener;
/**
* Creates a new transactional wrapper.
* @param con The underlying non-transactional Connection.
* @param resource The transaction resource used to enlist this
* connection in a transaction.
*/
public XAConnectionImpl(Connection con, XAResourceImpl resource) {
this.con = con;
this.resource = resource;
listeners = new Vector();
}
/**
* Sets the transaction listener.
*/
public void setTransactionListener(TransactionListener tl) {
transListener = tl;
}
/**
* Clears the transaction listener.
*/
public void clearTransactionListener() {
transListener = null;
}
/**
* Shuts down this wrapper (and the underlying Connection) permanently.
*/
public void close() {
try {
con.close();
} catch(SQLException e) {}
con = null;
resource = null;
listeners.clear();
listeners = null;
}
/**
* Indicates that the connection given to the client has been closed.
* If there is currently a transaction, this object should not be closed or
* returned to a pool. If not, it can be closed or returned immediately.
*/
public void clientConnectionClosed() {
boolean trans = resource.isTransaction(); // could be committed directly on
notification? Seems unlikely, but let's not rule it out.
Vector local = (Vector)listeners.clone();
for(int i=local.size()-1; i>=0; i--)
((ConnectionEventListener)local.elementAt(i)).connectionClosed(new
ConnectionEvent(this));
if(!trans)
transactionFinished();
}
/**
* Indicates that the outstanding transaction has finished and this object
* can be closed or returned to a pool. This dispatches a close event to
* all listeners.
* @see #addConnectionEventListener
*/
public void transactionFinished() {
if(transListener != null)
transListener.transactionFinished(this);
}
/**
* Indicates that the connection given to the client has had an error.
* If there is currently a transaction, this object should not be closed or
* returned to a pool. If not, it can be closed or returned immediately.
*/
public void setConnectionError(SQLException e) {
Vector local = (Vector)listeners.clone();
for(int i=local.size()-1; i>=0; i--)
((ConnectionEventListener)local.elementAt(i)).connectionErrorOccurred(new
ConnectionEvent(this, e));
}
// ---- Implementation of javax.sql.XAConnection ----
public XAResource getXAResource() {
return resource;
}
public void addConnectionEventListener(ConnectionEventListener listener) {
listeners.addElement(listener);
}
public void removeConnectionEventListener(ConnectionEventListener listener) {
listeners.remove(listener);
}
public Connection getConnection() {
return new XAClientConnection(this, con);
}
}
1.1 jboss/src/main/org/jboss/minerva/xa/XADataSourceImpl.java
Index: XADataSourceImpl.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.minerva.xa;
import java.io.PrintWriter;
import java.sql.*;
import java.util.Properties;
import javax.sql.*;
/**
* Transactional DataSource wrapper for JDBC 1.0 drivers. This is very
* lightweight - it just passes requests through to an underlying driver, and
* wraps the results with an XAConnection. The XAConnection and corresponding
* XAResource are responsible for closing the connection when appropriate.
* Note that the underlying driver may perform pooling, but need not. This
* class does not add any pooling capabilities.
* @version $Revision: 1.1 $
* @author Aaron Mulder ([EMAIL PROTECTED])
*/
public class XADataSourceImpl implements XADataSource {
private String url;
private String user;
private String password;
private Properties properties;
private int loginTimeout;
private PrintWriter logWriter;
/**
* Empty constructure for beans, reflection, etc.
*/
public XADataSourceImpl() {
}
/**
* Specifies the URL and properties to connect to the underlying driver.
* If the properties are null, they will not be used.
*/
public XADataSourceImpl(String url, Properties properties) {
this.url = url;
this.properties = properties;
}
/**
* Gets the JDBC URL used to open an underlying connection.
*/
public String getURL() {return url;}
/**
* Sets the JDBC URL used to open an underlying connection.
*/
public void setURL(String url) {this.url = url;}
/**
* Gets the JDBC user name used to open an underlying connection.
*/
public String getUser() {return user;}
/**
* Sets the JDBC user name used to open an underlying connection.
* This is optional - use it only if your underlying driver requires it.
*/
public void setUser(String user) {this.user = user;}
/**
* Gets the JDBC password used to open an underlying connection.
*/
public String getPassword() {return password;}
/**
* Sets the JDBC password used to open an underlying connection.
* This is optional - use it only if your underlying driver requires it.
*/
public void setPassword(String password) {this.password = password;}
/**
* Gets the JDBC properties used to open an underlying connection.
*/
public Properties getProperties() {return properties;}
/**
* Sets the JDBC properties used to open an underlying connection.
* This is optional - use it only if your underlying driver requires it.
*/
public void setProperties(Properties properties) {this.properties = properties;}
/**
* Gets the log writer used to record when XAConnections are opened.
*/
public PrintWriter getLogWriter() throws SQLException {return logWriter;}
/**
* Sets a log writer used to record when XAConnections are opened.
*/
public void setLogWriter(PrintWriter writer) throws SQLException {logWriter =
writer;}
/**
* This is not used by the current implementation, since the effect would
* differ depending on the underlying driver.
*/
public int getLoginTimeout() throws SQLException {return loginTimeout;}
/**
* This is not used by the current implementation, since the effect would
* differ depending on the underlying driver.
*/
public void setLoginTimeout(int timeout) throws SQLException {loginTimeout =
timeout;}
/**
* Gets an XAConnection. This first gets a java.sql.Connection from the
* underlying driver, and then wraps it in an XAConnection and XAResource.
* This uses the URL, user, password, and properties (or as many as you
* have specified) to make the connection.
*/
public XAConnection getXAConnection() throws SQLException {
Connection con;
if(user != null && user.length() > 0)
con = DriverManager.getConnection(url, user, password);
else if(properties != null)
con = DriverManager.getConnection(url, properties);
else
con = DriverManager.getConnection(url);
XAResourceImpl res = new XAResourceImpl(con);
XAConnectionImpl xacon = new XAConnectionImpl(con, res);
res.setXAConnection(xacon);
if(logWriter != null)
logWriter.println(getClass().getName()+" created new Connection
("+con.getClass().getName()+") with XAResource "+res.getClass().getName()+" and
XAConnection "+xacon.getClass().getName()+".");
return xacon;
}
/**
* Gets an XAConnection. This first gets a java.sql.Connection from the
* underlying driver, and then wraps it in an XAConnection and XAResource.
* This first sets the default user name and password to the values you
* specify. Then it uses those, the URL, and properties (or as many as you
* have specified) to make the connection.
*/
public XAConnection getXAConnection(String user, String password) throws
SQLException {
this.user = user;
this.password = password;
return getXAConnection();
}
}
1.1 jboss/src/main/org/jboss/minerva/xa/XAResourceImpl.java
Index: XAResourceImpl.java
===================================================================
/*
* jBoss, the OpenSource EJB server
*
* Distributable under GPL license.
* See terms of license at gnu.org.
*/
package org.jboss.minerva.xa;
import javax.transaction.xa.*;
import java.sql.*;
/**
* JTA resource implementation for JDBC 1.0 connections. This is somewhat
* limited in two respects. First, it does not support two-phase commits since
* JDBC 1.0 does not. It will operate in the presence of two-phase commits, but
* will throw heuristic exceptions if there is a failure during a commit or
* rollback. Second, it can only be associated with one transaction
* at a time, and will throw exceptions if a second transaction tries to
* attach before the first has called commit, rollback, or forget.
* <P><FONT COLOR="RED"><B>Warning:</B></FONT></P> This implementation assumes
* that forget will be called after a failed commit or rollback. Otherwise,
* the database connection will never be closed.</P>
* @version $Revision: 1.1 $
* @author Aaron Mulder ([EMAIL PROTECTED])
*/
public class XAResourceImpl implements XAResource {
private Connection con;
private XAConnectionImpl xaCon;
private Xid current;
private boolean active = false;
private int timeout_ignored = 0;
/**
* Creates a new instance as the transactional resource for the specified
* underlying connection.
*/
public XAResourceImpl(Connection con) {
this.con = con;
}
/**
* Sets the XAConnection associated with this XAResource. This is required,
* but both classes cannot include an instance of the other in their
* constructor!
* @throws java.lang.IllegalStateException
* Occurs when this is called more than once.
*/
void setXAConnection(XAConnectionImpl xaCon) {
if(this.xaCon != null)
throw new IllegalStateException();
this.xaCon = xaCon;
}
/**
* Gets whether there is outstanding work on behalf of a Transaction. If
* there is not, then a connection that is closed will cause the
* XAConnection to be closed or returned to a pool. If there is, then the
* XAConnection must be kept open until commit or rollback is called.
*/
public boolean isTransaction() {
return current != null;
}
/**
* Closes this instance permanently.
*/
public void close() {
con = null;
current = null;
xaCon = null;
}
/**
* Commits a transaction.
* @throws XAException
* Occurs when the state was not correct (end never called), the
* transaction ID is wrong, the connection was set to Auto-Commit,
* or the commit on the underlying connection fails. The error code
* differs depending on the exact situation.
*/
public void commit(Xid id, boolean twoPhase) throws XAException {
if(active) // End was not called!
throw new XAException(XAException.XAER_PROTO);
if(current == null || !id.equals(current)) // wrong Xid
throw new XAException(XAException.XAER_NOTA);
try {
if(con.getAutoCommit())
throw new XAException(XAException.XA_HEURCOM);
} catch(SQLException e) {}
try {
con.commit();
} catch(SQLException e) {
try {
con.rollback();
if(!twoPhase)
throw new XAException(XAException.XA_RBROLLBACK);
} catch(SQLException e2) {}
if(twoPhase)
throw new XAException(XAException.XA_HEURRB); // no 2PC!
else
throw new XAException(XAException.XA_RBOTHER);
// Truly, neither committed nor rolled back. Ouch!
}
current = null;
xaCon.transactionFinished();
}
/**
* Dissociates a resource from a global transaction.
* @throws XAException
* Occurs when the state was not correct (end called twice), or the
* transaction ID is wrong.
*/
public void end(Xid id, int flags) throws javax.transaction.xa.XAException {
if(!active) // End was called twice!
throw new XAException(XAException.XAER_PROTO);
if(current == null || !id.equals(current))
throw new XAException(XAException.XAER_NOTA);
active = false;
}
/**
* Indicates that no further action will be taken on behalf of this
* transaction (after a heuristic failure). It is assumed this will be
* called after a failed commit or rollback.
* @throws XAException
* Occurs when the state was not correct (end never called), or the
* transaction ID is wrong.
*/
public void forget(Xid id) throws javax.transaction.xa.XAException {
if(active) // End was not called!
throw new XAException(XAException.XAER_PROTO);
if(current == null || !id.equals(current))
throw new XAException(XAException.XAER_NOTA);
current = null;
xaCon.transactionFinished();
}
/**
* Gets the transaction timeout.
*/
public int getTransactionTimeout() throws javax.transaction.xa.XAException {
return timeout_ignored;
}
/**
* Since the concept of resource managers does not really apply here (all
* JDBC connections must be managed individually), indicates whether the
* specified resource is the same as this one.
*/
public boolean isSameRM(XAResource res) throws javax.transaction.xa.XAException {
return res == this;
}
/**
* Prepares a transaction to commit. Since JDBC 1.0 does not support
* 2-phase commits, this claims the commit is OK (so long as some work was
* done on behalf of the specified transaction).
* @throws XAException
* Occurs when the state was not correct (end never called), the
* transaction ID is wrong, or the connection was set to Auto-Commit.
*/
public int prepare(Xid id) throws javax.transaction.xa.XAException {
if(active) // End was not called!
throw new XAException(XAException.XAER_PROTO);
if(current == null || !id.equals(current)) // wrong Xid
throw new XAException(XAException.XAER_NOTA);
try {
if(con.getAutoCommit())
throw new XAException(XAException.XA_HEURCOM);
} catch(SQLException e) {}
return XA_OK;
}
/**
* Returns all transaction IDs where work was done with no corresponding
* commit, rollback, or forget. Not really sure why this is useful in the
* context of JDBC drivers.
*/
public Xid[] recover(int flag) throws javax.transaction.xa.XAException {
if(current == null)
return new Xid[0];
else
return new Xid[]{current};
}
/**
* Rolls back the work, assuming it was done on behalf of the specified
* transaction.
* @throws XAException
* Occurs when the state was not correct (end never called), the
* transaction ID is wrong, the connection was set to Auto-Commit,
* or the rollback on the underlying connection fails. The error code
* differs depending on the exact situation.
*/
public void rollback(Xid id) throws javax.transaction.xa.XAException {
if(active) // End was not called!
throw new XAException(XAException.XAER_PROTO);
if(current == null || !id.equals(current)) // wrong Xid
throw new XAException(XAException.XAER_NOTA);
try {
if(con.getAutoCommit())
throw new XAException(XAException.XA_HEURCOM);
} catch(SQLException e) {}
try {
con.rollback();
} catch(SQLException e) {
throw new XAException("Rollback failed: "+e.getMessage());
}
current = null;
xaCon.transactionFinished();
}
/**
* Sets the transaction timeout. This is saved, but the value is not used
* by the current implementation.
*/
public boolean setTransactionTimeout(int timeout) throws
javax.transaction.xa.XAException {
timeout_ignored = timeout;
return true;
}
/**
* Associates a JDBC connection with a global transaction. We assume that
* end will be called followed by prepare, commit, or rollback.
* If start is called after end but before commit or rollback, there is no
* way to distinguish work done by different transactions on the same
* connection). If start is called more than once before
* end, either it's a duplicate transaction ID or illegal transaction ID
* (since you can't have two transactions associated with one DB
* connection).
* @throws XAException
* Occurs when the state was not correct (start called twice), the
* transaction ID is wrong, or the instance has already been closed.
*/
public void start(Xid id, int flags) throws javax.transaction.xa.XAException {
if(active) {// Start was called twice!
if(current != null && id.equals(current))
throw new XAException(XAException.XAER_DUPID);
else
throw new XAException(XAException.XAER_PROTO);
}
if(current != null)
throw new XAException(XAException.XAER_NOTA);
if(con == null)
throw new XAException(XAException.XA_RBOTHER);
active = true;
}
}
1.1 jboss/src/main/org/jboss/minerva/xa/package.html
Index: package.html
===================================================================
<HTML>
<HEAD>
<TITLE>Minerva Pools: Package org.jboss.minerva.xa</TITLE>
</HEAD>
<BODY BGCOLOR="WHITE">
<P>Transactional wrappers for JDBC drivers that don't implement the JDBC
2.0 standard extension. This allows an "old" JDBC driver to participate
in a two-phase commit environment, though with certain limitations. For
example, you cannot use one transaction across multiple connections, and
there will be heuristic failures if commits or rollbacks fail under
certain circumstances. This wrapper also allows connections to
participate in JTA transactions, so a J2EE server can manage them
appropriately. Highly recommended for use in a J2EE server (as opposed
to using the non-conformant connections directly).</P>
</BODY>
</HTML>