Author: psteitz
Date: Fri Jul 13 06:10:05 2007
New Revision: 555980
URL: http://svn.apache.org/viewvc?view=rev&rev=555980
Log:
Added BasicManagedDataSource, extending BasicDataSource.
Also improved extensibility of BasicDataSource by encapsulating
methods to create object pool, connection factory and datasource
instance previously embedded in createDataSource.
JIRA: DBCP-230
Patch provided by Dain Sundstrom
Added:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/BasicManagedDataSource.java
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/DataSourceXAConnectionFactory.java
jakarta/commons/proper/dbcp/trunk/xdocs/changes.xml
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java?view=diff&rev=555980&r1=555979&r2=555980
==============================================================================
---
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java
(original)
+++
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/BasicDataSource.java
Fri Jul 13 06:10:05 2007
@@ -1135,6 +1135,65 @@
return (dataSource);
}
+ // create factory which returns raw physical connections
+ ConnectionFactory driverConnectionFactory = createConectionFactory();
+
+ // create a pool for our connections
+ createConnectionPool();
+
+ // Set up statement pool, if desired
+ GenericKeyedObjectPoolFactory statementPoolFactory = null;
+ if (isPoolPreparedStatements()) {
+ statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
+ -1, // unlimited maxActive (per key)
+ GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
+ 0, // maxWait
+ 1, // maxIdle (per key)
+ maxOpenPreparedStatements);
+ }
+
+ // Set up the poolable connection factory we will use
+ PoolableConnectionFactory connectionFactory = null;
+ try {
+ connectionFactory =
+ new PoolableConnectionFactory(driverConnectionFactory,
+ connectionPool,
+ statementPoolFactory,
+ validationQuery,
+ defaultReadOnly,
+ defaultAutoCommit,
+ defaultTransactionIsolation,
+ defaultCatalog,
+ abandonedConfig);
+ if (connectionFactory == null) {
+ throw new SQLException("Cannot create
PoolableConnectionFactory");
+ }
+ validateConnectionFactory(connectionFactory);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SQLNestedException("Cannot create
PoolableConnectionFactory (" + e.getMessage() + ")", e);
+ }
+
+ // Create and return the pooling data source to manage the connections
+ createDataSourceInstance();
+
+ try {
+ for (int i = 0 ; i < initialSize ; i++) {
+ connectionPool.addObject();
+ }
+ } catch (Exception e) {
+ throw new SQLNestedException("Error preloading the connection
pool", e);
+ }
+
+ return dataSource;
+ }
+
+ /**
+ * Creates a connection factory for this datasource. This method only
+ * exists so subclasses can replace the implementation class.
+ */
+ protected ConnectionFactory createConectionFactory() throws SQLException {
// Load the JDBC driver class
if (driverClassName != null) {
try {
@@ -1154,7 +1213,7 @@
driver = DriverManager.getDriver(url);
} catch (Throwable t) {
String message = "Cannot create JDBC driver of class '" +
- (driverClassName != null ? driverClassName : "") +
+ (driverClassName != null ? driverClassName : "") +
"' for connect URL '" + url + "'";
logWriter.println(message);
t.printStackTrace(logWriter);
@@ -1168,6 +1227,28 @@
setTestWhileIdle(false);
}
+ // Set up the driver connection factory we will use
+ if (username != null) {
+ connectionProperties.put("user", username);
+ } else {
+ log("DBCP DataSource configured without a 'username'");
+ }
+
+ if (password != null) {
+ connectionProperties.put("password", password);
+ } else {
+ log("DBCP DataSource configured without a 'password'");
+ }
+
+ ConnectionFactory driverConnectionFactory = new
DriverConnectionFactory(driver, url, connectionProperties);
+ return driverConnectionFactory;
+ }
+
+ /**
+ * Creates a connection pool for this datasource. This method only exists
+ * so subclasses can replace the implementation class.
+ */
+ protected void createConnectionPool() {
// Create an object pool to contain our active connections
if ((abandonedConfig != null) &&
(abandonedConfig.getRemoveAbandoned())) {
connectionPool = new AbandonedObjectPool(null,abandonedConfig);
@@ -1185,73 +1266,21 @@
connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
connectionPool.setTestWhileIdle(testWhileIdle);
-
- // Set up statement pool, if desired
- GenericKeyedObjectPoolFactory statementPoolFactory = null;
- if (isPoolPreparedStatements()) {
- statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
- -1, // unlimited maxActive (per key)
- GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
- 0, // maxWait
- 1, // maxIdle (per key)
- maxOpenPreparedStatements);
- }
-
- // Set up the driver connection factory we will use
- if (username != null) {
- connectionProperties.put("user", username);
- } else {
- log("DBCP DataSource configured without a 'username'");
- }
-
- if (password != null) {
- connectionProperties.put("password", password);
- } else {
- log("DBCP DataSource configured without a 'password'");
- }
-
- DriverConnectionFactory driverConnectionFactory =
- new DriverConnectionFactory(driver, url, connectionProperties);
-
- // Set up the poolable connection factory we will use
- PoolableConnectionFactory connectionFactory = null;
- try {
- connectionFactory =
- new PoolableConnectionFactory(driverConnectionFactory,
- connectionPool,
- statementPoolFactory,
- validationQuery,
- defaultReadOnly,
- defaultAutoCommit,
- defaultTransactionIsolation,
- defaultCatalog,
- abandonedConfig);
- if (connectionFactory == null) {
- throw new SQLException("Cannot create
PoolableConnectionFactory");
- }
- validateConnectionFactory(connectionFactory);
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new SQLNestedException("Cannot create
PoolableConnectionFactory (" + e.getMessage() + ")", e);
- }
+ }
- // Create and return the pooling data source to manage the connections
+ /**
+ * Creates the actual data source instance. This method only exists so
+ * subclasses can replace the implementation class.
+ *
+ * @throws SQLException if unable to create a datasource instance
+ */
+ protected void createDataSourceInstance() throws SQLException {
dataSource = new PoolingDataSource(connectionPool);
((PoolingDataSource)
dataSource).setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
dataSource.setLogWriter(logWriter);
-
- try {
- for (int i = 0 ; i < initialSize ; i++) {
- connectionPool.addObject();
- }
- } catch (Exception e) {
- throw new SQLNestedException("Error preloading the connection
pool", e);
- }
-
- return dataSource;
}
+
private static void validateConnectionFactory(PoolableConnectionFactory
connectionFactory) throws Exception {
Connection conn = null;
try {
@@ -1276,7 +1305,7 @@
}
}
- private void log(String message) {
+ protected void log(String message) {
if (logWriter != null) {
logWriter.println(message);
}
Added:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/BasicManagedDataSource.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/BasicManagedDataSource.java?view=auto&rev=555980
==============================================================================
---
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/BasicManagedDataSource.java
(added)
+++
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/BasicManagedDataSource.java
Fri Jul 13 06:10:05 2007
@@ -0,0 +1,138 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.dbcp.managed;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.dbcp.SQLNestedException;
+
+import javax.sql.XADataSource;
+import javax.transaction.TransactionManager;
+import java.sql.SQLException;
+
+/**
+ * BasicManagedDataSource is an extension of BasicDataSource which
+ * creates ManagedConnections. This data source can create either
+ * create full two-phase-commit XA connections or one-phase-commit
+ * local connection. Both types of connections are committed or
+ * rolled back as part of the global transaction (a.k.a. XA
+ * transaction or JTA Transaction), but only XA connections can be
+ * recovered in the case of a system crash.
+ * </p>
+ * BasicManagedDataSource adds the TransactionManager and XADataSource
+ * properties. The TransactionManager property is required and is
+ * used to elist connections in global transactions. The XADataSource
+ * is optional and if set is the class name of the XADataSource class
+ * for a two-phase-commit JDBC driver. If the XADataSource property
+ * is set, the driverClassName is ignored and a DataSourceXAConnectionFactory
+ * is created. Otherwise, a standard DriverConnectionFactory is created
+ * and wrapped with a LocalXAConnectionFactory.
+ * </p>
+ * This is not the only way to combine the <em>commons-dbcp</em> and
+ * <em>commons-pool</em> packages, but provides a "one stop shopping"
+ * solution for basic requirements.</p>
+ *
+ * @see BasicDataSource
+ * @see ManagedConnection
+ * @version $Revision$
+ */
+public class BasicManagedDataSource extends BasicDataSource {
+ protected TransactionRegistry transactionRegistry;
+ protected TransactionManager transactionManager;
+ protected String xaDataSource;
+
+ /**
+ * Gets the required transaction manager property.
+ * @return the transaction manager used to enlist connections
+ */
+ public TransactionManager getTransactionManager() {
+ return transactionManager;
+ }
+
+ /**
+ * Sets the required transaction manager property.
+ * @param transactionManager the transaction manager used to enlist
connections
+ */
+ public void setTransactionManager(TransactionManager transactionManager) {
+ this.transactionManager = transactionManager;
+ }
+
+ /**
+ * Gets the optional XADataSource class name.
+ * @return the optional XADataSource class name
+ */
+ public String getXADataSource() {
+ return xaDataSource;
+ }
+
+ /**
+ * Sets the optional XADataSource class name.
+ * @param xaDataSource the optional XADataSource class name
+ */
+ public void setXADataSource(String xaDataSource) {
+ this.xaDataSource = xaDataSource;
+ }
+
+ protected ConnectionFactory createConectionFactory() throws SQLException {
+ if (transactionManager == null) {
+ throw new SQLException("Transaction manager must be set before a
connection can be created");
+ }
+
+ // If xa data source is not specified a DriverConnectionFactory is
created and wrapped with a LocalXAConnectionFactory
+ if (xaDataSource == null) {
+ ConnectionFactory connectionFactory =
super.createConectionFactory();
+ XAConnectionFactory xaConnectionFactory = new
LocalXAConnectionFactory(getTransactionManager(), connectionFactory);
+ transactionRegistry = xaConnectionFactory.getTransactionRegistry();
+ return xaConnectionFactory;
+ }
+
+ // Load the XA data source class
+ Class xaDataSourceClass = null;
+ try {
+ xaDataSourceClass = Class.forName(xaDataSource);
+ } catch (Throwable t) {
+ String message = "Cannot load XA data source class '" +
xaDataSource + "'";
+ logWriter.println(message);
+ t.printStackTrace(logWriter);
+ throw new SQLNestedException(message, t);
+ }
+
+ // Create the xa data source instance
+ XADataSource xaDataSource = null;
+ try {
+ xaDataSource = (XADataSource) xaDataSourceClass.newInstance();
+ } catch (Throwable t) {
+ String message = "Cannot create XA data source of class '" +
xaDataSource + "'";
+ logWriter.println(message);
+ t.printStackTrace(logWriter);
+ throw new SQLNestedException(message, t);
+ }
+
+ // finally, create the XAConectionFactory using the XA data source
+ XAConnectionFactory xaConnectionFactory = new
DataSourceXAConnectionFactory(getTransactionManager(), xaDataSource, username,
password);
+ transactionRegistry = xaConnectionFactory.getTransactionRegistry();
+ return xaConnectionFactory;
+ }
+
+ protected void createDataSourceInstance() throws SQLException {
+ dataSource = new ManagedDataSource(connectionPool,
transactionRegistry);
+ ((PoolingDataSource)
dataSource).setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
+ dataSource.setLogWriter(logWriter);
+ }
+}
Modified:
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/DataSourceXAConnectionFactory.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/DataSourceXAConnectionFactory.java?view=diff&rev=555980&r1=555979&r2=555980
==============================================================================
---
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/DataSourceXAConnectionFactory.java
(original)
+++
jakarta/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/managed/DataSourceXAConnectionFactory.java
Fri Jul 13 06:10:05 2007
@@ -33,6 +33,8 @@
public class DataSourceXAConnectionFactory implements XAConnectionFactory {
protected TransactionRegistry transactionRegistry;
protected XADataSource xaDataSource;
+ protected String username;
+ protected String password;
/**
* Creates an DataSourceXAConnectionFactory which uses the specified
XADataSource to create database
@@ -42,11 +44,50 @@
* @param xaDataSource the data source from which connections will be
retrieved
*/
public DataSourceXAConnectionFactory(TransactionManager
transactionManager, XADataSource xaDataSource) {
+ this(transactionManager, xaDataSource, null, null);
+ }
+
+ /**
+ * Creates an DataSourceXAConnectionFactory which uses the specified
XADataSource to create database
+ * connections. The connections are enlisted into transactions using the
specified transaction manager.
+ *
+ * @param transactionManager the transaction manager in which connections
will be enlisted
+ * @param xaDataSource the data source from which connections will be
retrieved
+ * @param username the username used for authenticating new connections or
null for unauthenticated
+ * @param password the password used for authenticating new connections
+ */
+ public DataSourceXAConnectionFactory(TransactionManager
transactionManager, XADataSource xaDataSource, String username, String
password) {
if (transactionManager == null) throw new
NullPointerException("transactionManager is null");
if (xaDataSource == null) throw new NullPointerException("xaDataSource
is null");
this.transactionRegistry = new TransactionRegistry(transactionManager);
this.xaDataSource = xaDataSource;
+ this.username = username;
+ this.password = password;
+ }
+
+ /**
+ * Gets the username used to authenticate new connections.
+ * @return the user name or null if unauthenticated connections are used
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * Sets the username used to authenticate new connections.
+ * @param username the username used for authenticating the connection or
null for unauthenticated
+ */
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ /**
+ * Sets the password used to authenticate new connections.
+ * @param password the password used for authenticating the connection or
null for unauthenticated
+ */
+ public void setPassword(String password) {
+ this.password = password;
}
public TransactionRegistry getTransactionRegistry() {
@@ -55,7 +96,12 @@
public Connection createConnection() throws SQLException {
// create a new XAConection
- XAConnection xaConnection = xaDataSource.getXAConnection();
+ XAConnection xaConnection;
+ if (username == null) {
+ xaConnection = xaDataSource.getXAConnection();
+ } else {
+ xaConnection = xaDataSource.getXAConnection(username, password);
+ }
// get the real connection and XAResource from the connection
Connection connection = xaConnection.getConnection();
Modified: jakarta/commons/proper/dbcp/trunk/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/jakarta/commons/proper/dbcp/trunk/xdocs/changes.xml?view=diff&rev=555980&r1=555979&r2=555980
==============================================================================
--- jakarta/commons/proper/dbcp/trunk/xdocs/changes.xml (original)
+++ jakarta/commons/proper/dbcp/trunk/xdocs/changes.xml Fri Jul 13 06:10:05 2007
@@ -54,6 +54,12 @@
<action dev="psteitz" type="add" issue="DBCP-228" due-to="Dain
Sundstrom">
Added support for pooling managed connections.
</action>
+ <action dev="psteitz" type="add" issue="DBCP-230" due-to="Dain
Sundstrom">
+ Added BasicManagedDataSource, extending BasicDataSource.
+ Also improved extensibility of BasicDataSource by encapsulating
+ methods to create object pool, connection factory and datasource
+ instance previously embedded in createDataSource.
+ </action>
</release>
<release version="1.2.2" date="2007-04-04"
description="This is a maintenance release containing bug fixes
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]