You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2019/01/02 23:17:27 UTC
[openjpa] 01/03: OPENJPA-2754 re-enable dbcp2 auto detection
This is an automated email from the ASF dual-hosted git repository.
struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git
commit 6afab6486af7beda11e57696ec607a1c638e318e
Author: Mark Struberg <st...@apache.org>
AuthorDate: Thu Jan 3 00:13:59 2019 +0100
OPENJPA-2754 re-enable dbcp2 auto detection
---
.../openjpa/jdbc/conf/JDBCConfiguration.java | 2 +-
.../openjpa/jdbc/conf/JDBCConfigurationImpl.java | 10 +-
.../openjpa/jdbc/schema/AutoDriverDataSource.java | 45 +++
.../openjpa/jdbc/schema/DBCPDriverDataSource.java | 308 +++++++++++++++++++++
.../openjpa/jdbc/schema/DataSourceFactory.java | 80 ++----
.../jdbc/schema/SimpleDriverDataSource.java | 18 +-
.../src/doc/manual/ref_guide_dbsetup.xml | 18 +-
7 files changed, 414 insertions(+), 67 deletions(-)
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
index 6808f46..34ee5eb 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
@@ -486,7 +486,7 @@ public interface JDBCConfiguration
* Create an instance of the {@link DriverDataSource} to use
* for creating a {@link DataSource} from a JDBC {@link Driver}.
*/
- DataSource newDriverDataSourceInstance();
+ DriverDataSource newDriverDataSourceInstance();
/**
* The plugin string for the {@link SchemaFactory} to use to provide
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
index 9fdb6dd..abfea8a 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
@@ -36,6 +36,7 @@ import org.apache.openjpa.jdbc.kernel.UpdateManager;
import org.apache.openjpa.jdbc.meta.MappingDefaults;
import org.apache.openjpa.jdbc.meta.MappingRepository;
import org.apache.openjpa.jdbc.schema.DataSourceFactory;
+import org.apache.openjpa.jdbc.schema.DriverDataSource;
import org.apache.openjpa.jdbc.schema.SchemaFactory;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.DBDictionaryFactory;
@@ -245,8 +246,9 @@ public class JDBCConfigurationImpl
driverDataSourcePlugin = addPlugin("jdbc.DriverDataSource", false);
aliases = new String[]{
+ "auto", "org.apache.openjpa.jdbc.schema.AutoDriverDataSource",
"simple", "org.apache.openjpa.jdbc.schema.SimpleDriverDataSource",
- "dbcp", "org.apache.commons.dbcp2.BasicDataSource"
+ "dbcp", "org.apache.openjpa.jdbc.schema.DBCPDriverDataSource"
};
driverDataSourcePlugin.setAliases(aliases);
driverDataSourcePlugin.setDefault(aliases[0]);
@@ -686,9 +688,9 @@ public class JDBCConfigurationImpl
}
@Override
- public DataSource newDriverDataSourceInstance() {
- return (DataSource) driverDataSourcePlugin.
- instantiate(DataSource.class, this);
+ public DriverDataSource newDriverDataSourceInstance() {
+ return (DriverDataSource) driverDataSourcePlugin.
+ instantiate(DriverDataSource.class, this);
}
@Override
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/AutoDriverDataSource.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/AutoDriverDataSource.java
new file mode 100644
index 0000000..90b828f
--- /dev/null
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/AutoDriverDataSource.java
@@ -0,0 +1,45 @@
+/*
+ * 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.openjpa.jdbc.schema;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+/**
+ * Automatic Commons DBCP pooling or Simple non-pooling driver data source.
+ * If the commons-dbcp packages are on the class path, then they will be used,
+ * else it will fall back to non-DBCP mode.
+ */
+public class AutoDriverDataSource
+ extends DBCPDriverDataSource {
+
+ @Override
+ public Connection getConnection(Properties props) throws SQLException {
+ // if we're using managed transactions, or user specified a DBCP driver
+ // or DBCP is not on the classpath, then use SimpleDriver
+ if (conf == null || conf.isTransactionModeManaged() || conf.isConnectionFactoryModeManaged() ||
+ !isDBCPLoaded(getClassLoader())) {
+ return getSimpleConnection(props);
+ } else {
+ // use DBCPDriverDataSource
+ return getDBCPConnection(props);
+ }
+ }
+}
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DBCPDriverDataSource.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DBCPDriverDataSource.java
new file mode 100644
index 0000000..c2d28e4
--- /dev/null
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DBCPDriverDataSource.java
@@ -0,0 +1,308 @@
+/*
+ * 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.openjpa.jdbc.schema;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.util.Closeable;
+
+/**
+ * Commons DBCP basic pooling driver data source.
+ * The commons-dbcp packages must be on the class path for this plugin to work,
+ * as it WILL NOT fall back to non-DBCP mode if they are missing. For automatic
+ * usage of Commons DBCP when available, use AutoDriverDataSource instead.
+ */
+public class DBCPDriverDataSource
+extends SimpleDriverDataSource implements Configurable, Closeable {
+
+ private static String DBCPPACKAGENAME = "org.apache.commons.dbcp2";
+ private static String DBCPBASICDATASOURCENAME = "org.apache.commons.dbcp2.BasicDataSource";
+ private static Class<?> _dbcpClass;
+ private static Boolean _dbcpAvail;
+ private static RuntimeException _dbcpEx;
+
+ protected JDBCConfiguration conf;
+ private DataSource _ds;
+
+ @Override
+ public Connection getConnection(Properties props) throws SQLException {
+ return getDBCPConnection(props);
+ }
+
+ @Override
+ public void close() throws SQLException {
+ try {
+ if (_ds != null) {
+ if (isDBCPLoaded(getClassLoader())) {
+ ((org.apache.commons.dbcp2.BasicDataSource)_dbcpClass.cast(_ds)).close();
+ }
+ }
+ } catch (Exception e) {
+ // no-op
+ } catch (Throwable t) {
+ // no-op
+ } finally {
+ _ds = null;
+ }
+ }
+
+ protected Connection getDBCPConnection(Properties props) throws SQLException {
+ Connection con = getDBCPDataSource(props).getConnection();
+ if (con == null) {
+ throw new SQLException(_eloc.get("dbcp-ds-null",
+ DBCPBASICDATASOURCENAME, getConnectionDriverName(), getConnectionURL()).getMessage());
+ }
+ return con;
+ }
+
+ protected DataSource getDBCPDataSource(Properties props) {
+ if (isDBCPLoaded(getClassLoader())) {
+ if (_ds == null) {
+ try {
+ Properties dbcpProps = updateDBCPProperties(props);
+ _ds = (DataSource) Configurations.newInstance(DBCPBASICDATASOURCENAME, conf,
+ dbcpProps, getClassLoader());
+ } catch (Exception e) {
+ _dbcpEx = new RuntimeException(_eloc.get("driver-null", DBCPBASICDATASOURCENAME).getMessage(), e);
+ }
+ return _ds;
+ } else {
+ return _ds;
+ }
+ } else {
+ // user choose DBCP, so fail if it isn't on the classpath
+ if (_dbcpEx == null)
+ _dbcpEx = new RuntimeException(_eloc.get("driver-null", DBCPBASICDATASOURCENAME).getMessage());
+ throw _dbcpEx;
+ }
+ }
+
+ /**
+ * This method should not throw an exception, as it is called by
+ * AutoDriverDataSource to determine if user already specified
+ * to use Commons DBCP.
+ * @return true if ConnectionDriverName contains org.apache.commons.dbcp2,
+ * otherwise false
+ */
+ protected boolean isDBCPDataSource() {
+ return (getConnectionDriverName() != null &&
+ getConnectionDriverName().toLowerCase(Locale.ENGLISH).indexOf(DBCPPACKAGENAME) >= 0);
+ }
+
+ /**
+ * This method should not throw an exception, as it is called by
+ * AutoDriverDataSource to determine if it should use DBCP or not
+ * based on if org.apache.commons.dbcp2.BasicDataSource can be loaded.
+ * @return true if Commons DBCP was found on the classpath, otherwise false
+ */
+ static protected boolean isDBCPLoaded(ClassLoader cl) {
+ if (Boolean.TRUE.equals(_dbcpAvail) && (_dbcpClass != null)) {
+ return true;
+ } else if (Boolean.FALSE.equals(_dbcpAvail)) {
+ return false;
+ } else {
+ // first time checking, so try to load it
+ try {
+ _dbcpClass = Class.forName(DBCPBASICDATASOURCENAME, true, cl);
+ _dbcpAvail = Boolean.TRUE;
+ return true;
+ } catch (Exception e) {
+ _dbcpAvail = Boolean.FALSE;
+ // save exception details for later instead of throwing here
+ _dbcpEx = new RuntimeException(_eloc.get("driver-null", DBCPBASICDATASOURCENAME).getMessage(), e);
+ }
+ return _dbcpAvail.booleanValue();
+ }
+ }
+
+ /**
+ * Normalize properties for Commons DBCP. This should be done for every call from DataSourceFactory,
+ * as we do not have a pre-configured Driver to reuse.
+ * @param props
+ * @return updated properties
+ */
+ private Properties updateDBCPProperties(Properties props) {
+ Properties dbcpProps = mergeConnectionProperties(props);
+
+ // only perform the following check for the first connection attempt (_driverClassName == null),
+ // as multiple connections could be requested (like from SchemaTool) and isDBCPDriver() will be true
+ if (isDBCPDataSource()) {
+ String propDriver = hasProperty(dbcpProps, "driverClassName");
+ if (propDriver == null || propDriver.trim().isEmpty()) {
+ // if user specified DBCP for the connectionDriverName, then make sure they supplied a DriverClassName
+ throw new RuntimeException(_eloc.get("connection-property-invalid", "DriverClassName",
+ propDriver).getMessage());
+ }
+ propDriver = hasProperty(dbcpProps, "url");
+ if (propDriver == null || propDriver.trim().isEmpty()) {
+ // if user specified DBCP for the connectionDriverName, then make sure they supplied a Url
+ throw new RuntimeException(_eloc.get("connection-property-invalid", "URL",
+ propDriver).getMessage());
+ }
+ } else {
+ // set Commons DBCP expected DriverClassName to the original connection driver name
+ dbcpProps.setProperty(hasKey(dbcpProps, "driverClassName", "driverClassName"), getConnectionDriverName());
+ // set Commons DBCP expected URL property
+ dbcpProps.setProperty(hasKey(dbcpProps, "url", "url"), getConnectionURL());
+ }
+
+ // Commons DBCP requires non-Null username/password values in the connection properties
+ if (hasKey(dbcpProps, "username") == null) {
+ if (getConnectionUserName() != null)
+ dbcpProps.setProperty("username", getConnectionUserName());
+ else
+ dbcpProps.setProperty("username", "");
+ }
+ // Commons DBCP requires non-Null username/password values in the connection properties
+ if (hasKey(dbcpProps, "password") == null) {
+ if (getConnectionPassword() != null)
+ dbcpProps.setProperty("password", getConnectionPassword());
+ else
+ dbcpProps.setProperty("password", "");
+ }
+
+ // set some default properties for DBCP
+ if (hasKey(dbcpProps, "maxIdle") == null) {
+ dbcpProps.setProperty("maxIdle", "1");
+ }
+ if (hasKey(dbcpProps, "minIdle") == null) {
+ dbcpProps.setProperty("minIdle", "0");
+ }
+ if (hasKey(dbcpProps, "maxActive") == null) {
+ dbcpProps.setProperty("maxActive", "10");
+ }
+
+ return dbcpProps;
+ }
+
+ /**
+ * Merge the passed in properties with a copy of the existing _connectionProperties
+ * @param props
+ * @return Merged properties
+ */
+ private Properties mergeConnectionProperties(final Properties props) {
+ Properties mergedProps = new Properties();
+ mergedProps.putAll(getConnectionProperties());
+
+ // need to map "user" to "username" for Commons DBCP
+ String uid = removeProperty(mergedProps, "user");
+ if (uid != null) {
+ mergedProps.setProperty("username", uid);
+ }
+
+ // now, merge in any passed in properties
+ if (props != null && !props.isEmpty()) {
+ for (Iterator<Object> itr = props.keySet().iterator(); itr.hasNext();) {
+ String key = (String)itr.next();
+ String value = props.getProperty(key);
+ // need to map "user" to "username" for Commons DBCP
+ if ("user".equalsIgnoreCase(key)) {
+ key = "username";
+ }
+ // case-insensitive search for existing key
+ String existingKey = hasKey(mergedProps, key);
+ if (existingKey != null) {
+ // update existing entry
+ mergedProps.setProperty(existingKey, value);
+ } else {
+ // add property to the merged set
+ mergedProps.setProperty(key, value);
+ }
+ }
+ }
+ return mergedProps;
+ }
+
+ /**
+ * Case-insensitive search of the given properties for the given key.
+ * @param props
+ * @param key
+ * @return Key name as found in properties or null if it was not found.
+ */
+ private String hasKey(Properties props, String key) {
+ return hasKey(props, key, null);
+ }
+
+ /**
+ * Case-insensitive search of the given properties for the given key.
+ * @param props
+ * @param key
+ * @param defaultKey
+ * @return Key name as found in properties or the given defaultKey if it was not found.
+ */
+ private String hasKey(Properties props, String key, String defaultKey)
+ {
+ if (props != null && key != null) {
+ for (Iterator<Object> itr = props.keySet().iterator(); itr.hasNext();) {
+ String entry = (String)itr.next();
+ if (key.equalsIgnoreCase(entry))
+ return entry;
+ }
+ }
+ return defaultKey;
+ }
+
+ private String hasProperty(Properties props, String key) {
+ if (props != null && key != null) {
+ String entry = hasKey(props, key);
+ if (entry != null)
+ return props.getProperty(entry);
+ }
+ return null;
+
+ }
+
+ private String removeProperty(Properties props, String key) {
+ if (props != null && key != null) {
+ String entry = hasKey(props, key);
+ if (entry != null)
+ return (String)props.remove(entry);
+ }
+ return null;
+ }
+
+ // Configurable interface methods
+ @Override
+ public void setConfiguration(Configuration conf) {
+ if (conf instanceof JDBCConfiguration)
+ this.conf = (JDBCConfiguration)conf;
+ }
+
+ @Override
+ public void startConfiguration() {
+ // no-op
+ }
+
+ @Override
+ public void endConfiguration() {
+ // no-op
+ }
+
+}
+
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
index d41f154..8afd9df 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
@@ -18,7 +18,6 @@
*/
package org.apache.openjpa.jdbc.schema;
-import java.lang.reflect.Method;
import java.security.AccessController;
import java.sql.Connection;
import java.sql.Driver;
@@ -57,7 +56,7 @@ import org.apache.openjpa.util.UserException;
* @author Abe White
*/
public class DataSourceFactory {
- private static final String DBCPBASICDATASOURCENAME = "org.apache.commons.dbcp2.BasicDataSource";
+
private static final Localizer _loc = Localizer.forPackage(DataSourceFactory.class);
protected static Localizer _eloc = Localizer.forPackage(DelegatingDataSource.class);
@@ -86,42 +85,27 @@ public class DataSourceFactory {
}
if (Driver.class.isAssignableFrom(driverClass)) {
- DataSource rawDs = conf.newDriverDataSourceInstance();
- if (rawDs instanceof DriverDataSource) {
- DriverDataSource ds = (DriverDataSource)rawDs;
- ds.setClassLoader(loader);
- ds.setConnectionDriverName(driver);
- ds.setConnectionProperties(Configurations.
- parseProperties(props));
-
- if (!factory2) {
- ds.setConnectionFactoryProperties(Configurations.
- parseProperties(conf.getConnectionFactoryProperties()));
- ds.setConnectionURL(conf.getConnectionURL());
- ds.setConnectionUserName(conf.getConnectionUserName());
- ds.setConnectionPassword(conf.getConnectionPassword());
- } else {
- ds.setConnectionFactoryProperties
- (Configurations.parseProperties(conf.
- getConnectionFactory2Properties()));
- ds.setConnectionURL(conf.getConnection2URL());
- ds.setConnectionUserName(conf.getConnection2UserName());
- ds.setConnectionPassword(conf.getConnection2Password());
- }
- return ds;
- } else if (DBCPBASICDATASOURCENAME.equals(rawDs.getClass().getName())) {
- reflectiveCall(rawDs, "setDriverClassLoader", ClassLoader.class, loader);
- reflectiveCall(rawDs, "setDriverClassName", String.class, driver);
- reflectiveCall(rawDs, "setConnectionProperties", String.class, props);
-
- reflectiveCall(rawDs, "setUrl", String.class, factory2
- ? conf.getConnection2URL() : conf.getConnectionURL());
- reflectiveCall(rawDs, "setUsername", String.class, factory2
- ? conf.getConnection2UserName() : conf.getConnectionUserName());
- reflectiveCall(rawDs, "setPassword", String.class, factory2
- ? conf.getConnection2Password() : conf.getConnectionPassword());
- return rawDs;
+ DriverDataSource ds = conf.newDriverDataSourceInstance();
+ ds.setClassLoader(loader);
+ ds.setConnectionDriverName(driver);
+ ds.setConnectionProperties(Configurations.
+ parseProperties(props));
+
+ if (!factory2) {
+ ds.setConnectionFactoryProperties(Configurations.
+ parseProperties(conf.getConnectionFactoryProperties()));
+ ds.setConnectionURL(conf.getConnectionURL());
+ ds.setConnectionUserName(conf.getConnectionUserName());
+ ds.setConnectionPassword(conf.getConnectionPassword());
+ } else {
+ ds.setConnectionFactoryProperties
+ (Configurations.parseProperties(conf.
+ getConnectionFactory2Properties()));
+ ds.setConnectionURL(conf.getConnection2URL());
+ ds.setConnectionUserName(conf.getConnection2UserName());
+ ds.setConnectionPassword(conf.getConnection2Password());
}
+ return ds;
}
// see if their driver name is actually a data source
@@ -142,12 +126,6 @@ public class DataSourceFactory {
throw new UserException(_loc.get("bad-driver", driver)).setFatal(true);
}
- private static void reflectiveCall(Object obj, String meth, Class<?> valClass, Object value) throws Exception {
- Class<?> clazz = obj.getClass();
- Method method = clazz.getMethod(meth, valClass);
- method.invoke(obj, value);
- }
-
/**
* Install listeners and base decorators.
*/
@@ -277,7 +255,7 @@ public class DataSourceFactory {
return ds;
} catch (Exception e) {
- throw newConnectException(conf, factory2, e);
+ throw newConnectException(conf, factory2, e);
} finally {
if (conn != null)
try {
@@ -290,13 +268,13 @@ public class DataSourceFactory {
}
static OpenJPAException newConnectException(JDBCConfiguration conf,
- boolean factory2, Exception cause) {
- return new UserException(_eloc.get("poolds-null", factory2
- ? new Object[]{conf.getConnection2DriverName(),
- conf.getConnection2URL()}
- : new Object[]{conf.getConnectionDriverName(),
- conf.getConnectionURL()}),
- cause).setFatal(true);
+ boolean factory2, Exception cause) {
+ return new UserException(_eloc.get("poolds-null", factory2
+ ? new Object[]{conf.getConnection2DriverName(),
+ conf.getConnection2URL()}
+ : new Object[]{conf.getConnectionDriverName(),
+ conf.getConnectionURL()}),
+ cause).setFatal(true);
}
/**
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
index 6b1a369..5273e2e 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
@@ -83,15 +83,15 @@ public class SimpleDriverDataSource
}
protected Connection getSimpleConnection(Properties props) throws SQLException {
- Properties conProps = new Properties();
- if (props != null) {
- conProps.putAll(props);
- }
- if (_connectionProperties != null) {
- conProps.putAll(_connectionProperties);
- }
- Connection con = getSimpleDriver().connect(_connectionURL, conProps);
- if (con == null) {
+ Properties conProps = new Properties();
+ if (props != null) {
+ conProps.putAll(props);
+ }
+ if (_connectionProperties != null) {
+ conProps.putAll(_connectionProperties);
+ }
+ Connection con = getSimpleDriver().connect(_connectionURL, conProps);
+ if (con == null) {
throw new SQLException(_eloc.get("poolds-null",
_connectionDriverName, _connectionURL).getMessage());
}
diff --git a/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml b/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
index 5d5b8c1..a021dc0 100644
--- a/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
+++ b/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
@@ -79,8 +79,22 @@ provided implementations.
</seealso>
</indexterm>
<para>
-<literal>openjpa.jdbc.DriverDataSource=simple</literal>, will make
-OpenJPA to use <classname>org.apache.openjpa.jdbc.schema.SimpleDriverDataSource</classname>
+ Starting with OpenJPA 2.1, a new <classname>org.apache.openjpa.jdbc.schema.AutoDriverDataSource</classname>
+ is provided as the default, which will automatically
+ select between the old <classname>SimpleDriverDataSource</classname> and a new
+ <classname>DBCPDriverDataSource</classname> implementation based on if
+ <ulink url="https://commons.apache.org/dbcp/">Apache Commons DBCP2</ulink>
+ has been provided on the classpath and OpenJPA is not running in a container
+ managed mode or with managed transactions. Note, that only the
+ <literal>openjpa-all.jar</literal> includes Commons DBCP2, so you will need to
+ include the <literal>commons-dbcp2.jar</literal> from the OpenJPA binary
+ distribution if you are using the normal <literal>openjpa.jar</literal>.
+ </para>
+ <para>
+ To disable the automatic usage of Apache Commons DBCP when it is discovered
+ on the classpath, set
+ <literal>openjpa.jdbc.DriverDataSource=simple</literal>, which will revert
+ OpenJPA to the prior behavior of using <classname>org.apache.openjpa.jdbc.schema.SimpleDriverDataSource</classname>
</para>
<para>
To force usage of Apache Commons DBCP2, which will cause a fatal exception to