You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2006/02/22 22:28:16 UTC
svn commit: r379915 -
/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java
Author: arminw
Date: Wed Feb 22 13:28:13 2006
New Revision: 379915
URL: http://svn.apache.org/viewcvs?rev=379915&view=rev
Log:
fix OJB-97, have to extend several classes of dbcp library to fix unexpected behavior
Modified:
db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java
Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java
URL: http://svn.apache.org/viewcvs/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java?rev=379915&r1=379914&r2=379915&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java Wed Feb 22 13:28:13 2006
@@ -15,9 +15,21 @@
* limitations under the License.
*/
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
import org.apache.commons.dbcp.AbandonedConfig;
import org.apache.commons.dbcp.AbandonedObjectPool;
+import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.KeyedObjectPoolFactory;
@@ -32,16 +44,6 @@
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.apache.ojb.broker.util.logging.LoggerWrapperPrintWriter;
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-
/**
* ConnectionFactory implementation using Commons DBCP and Commons Pool API
* to pool connections.
@@ -81,7 +83,7 @@
{
conn = ds.getConnection();
}
- catch (SQLException e)
+ catch(SQLException e)
{
throw new LookupException("Could not get connection from DBCP DataSource", e);
}
@@ -94,40 +96,43 @@
try
{
// We are using datasources, thus close returns connection to pool
- con.close();
+
+ // we have to check 'isClosed', because otherwise method
+ // org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.checkOpen
+ // will throw an unexpected exception (see javadoc for Coonection.close()) when
+ // con.close() is called several times.
+ if(!con.isClosed()) con.close();
}
- catch (SQLException e)
+ catch(SQLException e)
{
log.warn("Connection close failed", e);
}
}
- /**
- * Closes all managed pools.
- */
+ /** Closes all managed pools. */
public void releaseAllResources()
{
super.releaseAllResources();
- synchronized (poolSynch)
+ synchronized(poolSynch)
{
- if (!poolMap.isEmpty())
+ if(!poolMap.isEmpty())
{
Collection pools = poolMap.values();
Iterator iterator = pools.iterator();
ObjectPool op = null;
- while (iterator.hasNext())
+ while(iterator.hasNext())
{
try
{
op = (ObjectPool) iterator.next();
- if (op instanceof GenericObjectPool)
+ if(op instanceof GenericObjectPool)
{
// deactivates the idle evictor thread
- ((GenericObjectPool)op).setTimeBetweenEvictionRunsMillis(-1);
+ ((GenericObjectPool) op).setTimeBetweenEvictionRunsMillis(-1);
}
op.close();
}
- catch (Exception e)
+ catch(Exception e)
{
log.error("Exception occured while closing ObjectPool " + op, e);
}
@@ -141,9 +146,10 @@
/**
* Returns the DBCP DataSource for the specified connection descriptor,
* after creating a new DataSource if needed.
+ *
* @param jcd the descriptor for which to return a DataSource
* @return a DataSource, after creating a new pool if needed.
- * Guaranteed to never be null.
+ * Guaranteed to never be null.
* @throws LookupException if pool is not in cache and cannot be created
*/
protected DataSource getDataSource(JdbcConnectionDescriptor jcd)
@@ -151,12 +157,12 @@
{
final PBKey key = jcd.getPBKey();
DataSource ds = (DataSource) dsMap.get(key);
- if (ds == null)
+ if(ds == null)
{
// Found no pool for PBKey
try
{
- synchronized (poolSynch)
+ synchronized(poolSynch)
{
// Setup new object pool
ObjectPool pool = setupPool(jcd);
@@ -166,7 +172,7 @@
dsMap.put(key, ds);
}
}
- catch (Exception e)
+ catch(Exception e)
{
log.error("Could not setup DBCP DataSource for " + jcd, e);
throw new LookupException(e);
@@ -178,6 +184,7 @@
/**
* Returns a new ObjectPool for the specified connection descriptor.
* Override this method to setup your own pool.
+ *
* @param jcd the connection descriptor for which to set up the pool
* @return a newly created object pool
*/
@@ -189,17 +196,17 @@
{
ClassHelper.newInstance(jcd.getDriver());
}
- catch (InstantiationException e)
+ catch(InstantiationException e)
{
- log.fatal("Unable to instantiate the driver class: " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e);
+ log.fatal("Unable to instantiate the driver class: " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!", e);
}
- catch (IllegalAccessException e)
+ catch(IllegalAccessException e)
{
- log.fatal("IllegalAccessException while instantiating the driver class: " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e);
+ log.fatal("IllegalAccessException while instantiating the driver class: " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!", e);
}
- catch (ClassNotFoundException e)
+ catch(ClassNotFoundException e)
{
- log.fatal("Could not find the driver class : " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e);
+ log.fatal("Could not find the driver class : " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!", e);
}
// Get the configuration for the connection pool
@@ -232,7 +239,7 @@
// the classes that implement the pooling functionality.
//
final PoolableConnectionFactory poolableConnectionFactory;
- poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,
+ poolableConnectionFactory = new OJBPoolableConnectionFactory(connectionFactory,
connectionPool,
statementPoolFactory,
validationQuery,
@@ -248,9 +255,12 @@
final GenericObjectPool connectionPool;
final boolean doRemoveAbandoned = ac != null && ac.getRemoveAbandoned();
- if (doRemoveAbandoned) {
+ if(doRemoveAbandoned)
+ {
connectionPool = new AbandonedObjectPool(null, ac);
- } else {
+ }
+ else
+ {
connectionPool = new GenericObjectPool();
}
connectionPool.setMaxActive(config.maxActive);
@@ -269,7 +279,7 @@
protected KeyedObjectPoolFactory createStatementPoolFactory(JdbcConnectionDescriptor jcd)
{
final String platform = jcd.getDbms();
- if (platform.startsWith("Oracle9i"))
+ if(platform.startsWith("Oracle9i"))
{
// mkalen: let the platform set Oracle-specific statement pooling
return null;
@@ -279,21 +289,21 @@
GenericKeyedObjectPoolFactory statementPoolFactory = null;
final Properties properties = jcd.getConnectionPoolDescriptor().getDbcpProperties();
final String poolStmtParam = properties.getProperty(PARAM_NAME_POOL_STATEMENTS);
- if (poolStmtParam != null && Boolean.valueOf(poolStmtParam).booleanValue())
+ if(poolStmtParam != null && Boolean.valueOf(poolStmtParam).booleanValue())
{
int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
final String maxOpenPrepStmtString = properties.getProperty(PARAM_NAME_STATEMENT_POOL_MAX_TOTAL);
- if (maxOpenPrepStmtString != null)
+ if(maxOpenPrepStmtString != null)
{
maxOpenPreparedStatements = Integer.parseInt(maxOpenPrepStmtString);
}
// Use the same values as Commons DBCP BasicDataSource
statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
- -1, // unlimited maxActive (per key)
- GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
- 0, // maxWait
- 1, // maxIdle (per key)
- maxOpenPreparedStatements);
+ -1, // unlimited maxActive (per key)
+ GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
+ 0, // maxWait
+ 1, // maxIdle (per key)
+ maxOpenPreparedStatements);
}
return statementPoolFactory;
}
@@ -304,15 +314,15 @@
* @param jcd the OJB connection descriptor for the pool to be wrapped
* @param connectionPool the connection pool to be wrapped
* @return a DataSource attached to the connection pool.
- * Connections will be wrapped using DBCP PoolGuard, that will not allow
- * unwrapping unless the "accessToUnderlyingConnectionAllowed=true" configuration
- * is specified.
+ * Connections will be wrapped using DBCP PoolGuard, that will not allow
+ * unwrapping unless the "accessToUnderlyingConnectionAllowed=true" configuration
+ * is specified.
*/
protected DataSource wrapAsDataSource(JdbcConnectionDescriptor jcd,
ObjectPool connectionPool)
{
final boolean allowConnectionUnwrap;
- if (jcd == null)
+ if(jcd == null)
{
allowConnectionUnwrap = false;
}
@@ -331,7 +341,8 @@
if(jcd != null)
{
final AbandonedConfig ac = jcd.getConnectionPoolDescriptor().getAbandonedConfig();
- if (ac.getRemoveAbandoned() && ac.getLogAbandoned()) {
+ if(ac.getRemoveAbandoned() && ac.getLogAbandoned())
+ {
final LoggerWrapperPrintWriter loggerPiggyBack;
loggerPiggyBack = new LoggerWrapperPrintWriter(log, Logger.ERROR);
dataSource.setLogWriter(loggerPiggyBack);
@@ -355,8 +366,8 @@
*
* @param jcd the jdbc-connection-alias for which we are creating a ConnectionFactory
* @return a DriverManager-based ConnectionFactory that creates Connection instances
- * using DriverManager, and that follows the lifecycle contract defined in OJB
- * {@link org.apache.ojb.broker.platforms.Platform} API.
+ * using DriverManager, and that follows the lifecycle contract defined in OJB
+ * {@link org.apache.ojb.broker.platforms.Platform} API.
*/
protected org.apache.commons.dbcp.ConnectionFactory createConnectionFactory(JdbcConnectionDescriptor jcd)
{
@@ -370,8 +381,9 @@
/**
* mkalen: Left for binary API-compatibility with OJB 1.0.3 (don't break users' factories)
- * @deprecated since OJB 1.0.4,
- * please use {@link #createConnectionPool(org.apache.commons.pool.impl.GenericObjectPool.Config, org.apache.commons.dbcp.AbandonedConfig)}
+ *
+ * @deprecated since OJB 1.0.4, please use
+ * {@link #createConnectionPool(org.apache.commons.pool.impl.GenericObjectPool.Config, org.apache.commons.dbcp.AbandonedConfig)}
*/
protected ObjectPool createObjectPool(GenericObjectPool.Config config)
{
@@ -380,8 +392,9 @@
/**
* mkalen: Left for binary API-compatibility with OJB 1.0.3 (don't break users' factories)
- * @deprecated since OJB 1.0.4,
- * please use {@link #wrapAsDataSource(org.apache.ojb.broker.metadata.JdbcConnectionDescriptor, org.apache.commons.pool.ObjectPool)}
+ *
+ * @deprecated since OJB 1.0.4, please use
+ * {@link #wrapAsDataSource(org.apache.ojb.broker.metadata.JdbcConnectionDescriptor, org.apache.commons.pool.ObjectPool)}
*/
protected PoolingDataSource createPoolingDataSource(ObjectPool connectionPool)
{
@@ -393,6 +406,8 @@
// ----- end deprecated methods -----
+
+
//**************************************************************************************
// Inner classes
//************************************************************************************
@@ -401,6 +416,7 @@
* Inner class used as factory for DBCP connection pooling.
* Adhers to OJB platform specification by calling platform-specific init methods
* on newly created connections.
+ *
* @see org.apache.ojb.broker.platforms.Platform#initializeJdbcConnection
*/
class ConPoolFactory extends DriverManagerConnectionFactory
@@ -417,13 +433,13 @@
public Connection createConnection() throws SQLException
{
final Connection conn = super.createConnection();
- if (conn != null)
+ if(conn != null)
{
try
{
initializeJdbcConnection(conn, jcd);
}
- catch (LookupException e)
+ catch(LookupException e)
{
log.error("Platform dependent initialization of connection failed", e);
}
@@ -431,6 +447,138 @@
return conn;
}
+ }
+
+ /**
+ * Specific OJB version of {@link org.apache.commons.dbcp.PoolableConnectionFactory}. This is
+ * needed because the DBCP version cause some unexpected behavior - see overridden methods
+ * {@link #passivateObject(Object)}, {@link #activateObject(Object)} and {@link #makeObject()}.
+ */
+ static class OJBPoolableConnectionFactory extends PoolableConnectionFactory
+ {
+ public OJBPoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit)
+ {
+ super(connFactory, pool, stmtPoolFactory, validationQuery, defaultReadOnly, defaultAutoCommit);
+ }
+
+ public OJBPoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation)
+ {
+ super(connFactory, pool, stmtPoolFactory, validationQuery, defaultReadOnly, defaultAutoCommit, defaultTransactionIsolation);
+ }
+
+ public OJBPoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit, AbandonedConfig config)
+ {
+ super(connFactory, pool, stmtPoolFactory, validationQuery, defaultReadOnly, defaultAutoCommit, config);
+ }
+
+ public OJBPoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation, AbandonedConfig config)
+ {
+ super(connFactory, pool, stmtPoolFactory, validationQuery, defaultReadOnly, defaultAutoCommit, defaultTransactionIsolation, config);
+ }
+
+ public OJBPoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation, String defaultCatalog, AbandonedConfig config)
+ {
+ super(connFactory, pool, stmtPoolFactory, validationQuery, defaultReadOnly, defaultAutoCommit, defaultTransactionIsolation, defaultCatalog, config);
+ }
+
+ public OJBPoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, Boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation, String defaultCatalog, AbandonedConfig config)
+ {
+ super(connFactory, pool, stmtPoolFactory, validationQuery, defaultReadOnly, defaultAutoCommit, defaultTransactionIsolation, defaultCatalog, config);
+ }
+
+ /**
+ * Don't change autocommit state - This is handled by OJB.
+ */
+ public void passivateObject(final Object obj) throws Exception
+ {
+ if(obj instanceof OJBPoolableConnection)
+ {
+ OJBPoolableConnection conn = (OJBPoolableConnection) obj;
+ conn.clearWarnings();
+ // do not change, will be managed by OJB
+ //conn.setAutoCommit(true);
+
+ conn.passivate();
+ }
+ else
+ {
+ super.passivateObject(obj);
+ }
+ }
+
+ /**
+ * Don't change autocommit state, don't rollback connection when autocommit
+ * is set false and connection is not readonly - This is handled by OJB.
+ */
+ public void activateObject(final Object obj) throws Exception
+ {
+ if(obj instanceof OJBPoolableConnection)
+ {
+ OJBPoolableConnection conn = (OJBPoolableConnection) obj;
+ conn.activate();
+ // do not change, will be managed by OJB
+ // conn.setAutoCommit(_defaultAutoCommit);
+ if(_defaultTransactionIsolation != -1 && _defaultTransactionIsolation != conn.getTransactionIsolation())
+ {
+ conn.setTransactionIsolation(_defaultTransactionIsolation);
+ }
+ if(_defaultReadOnly.booleanValue() != conn.isReadOnly())
+ {
+ conn.setReadOnly(_defaultReadOnly.booleanValue());
+ }
+ if(_defaultCatalog != null)
+ {
+ conn.setCatalog(_defaultCatalog);
+ }
+ }
+ else
+ {
+ super.activateObject(obj);
+ }
+ }
+
+ /**
+ * Wraps the {@link org.apache.commons.dbcp.PoolableConnection} with
+ * {@link org.apache.ojb.broker.accesslayer.ConnectionFactoryDBCPImpl.OJBPoolableConnection}
+ * to allow access to protected methods.
+ */
+ synchronized public Object makeObject() throws Exception
+ {
+ PoolableConnection con = (PoolableConnection) super.makeObject();
+ return new OJBPoolableConnection(con, _pool, _config);
+ }
+ }
+
+ /**
+ * Needed to allow usage of methods {@link #activate()} and {@link #passivate()}
+ * in class {@link org.apache.ojb.broker.accesslayer.ConnectionFactoryDBCPImpl.OJBPoolableConnectionFactory}.
+ */
+ static class OJBPoolableConnection extends PoolableConnection
+ {
+ public OJBPoolableConnection(final Connection conn, final ObjectPool pool)
+ {
+ super(conn, pool);
+ }
+
+ public OJBPoolableConnection(final Connection conn, final ObjectPool pool, final AbandonedConfig config)
+ {
+ super(conn, pool, config);
+ }
+
+ protected void activate()
+ {
+ super.activate();
+ }
+
+ protected void passivate() throws SQLException
+ {
+ super.passivate();
+ }
+
+ public synchronized void close() throws SQLException
+ {
+ if(!isClosed()) super.close();
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org