commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pste...@apache.org
Subject svn commit: r555980 - in /jakarta/commons/proper/dbcp/trunk: src/java/org/apache/commons/dbcp/ src/java/org/apache/commons/dbcp/managed/ xdocs/
Date Fri, 13 Jul 2007 13:10:08 GMT
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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message