Author: ppoddar
Date: Fri Jul 11 13:28:49 2008
New Revision: 676073
URL: http://svn.apache.org/viewvc?rev=676073&view=rev
Log:
OPENJPA-656: raise error messages with connection parameters on connect failure
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java?rev=676073&r1=676072&r2=676073&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
Fri Jul 11 13:28:49 2008
@@ -26,6 +26,7 @@
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+
import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
@@ -45,7 +46,6 @@
import org.apache.openjpa.lib.util.Options;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.OpenJPAException;
-import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UserException;
/**
@@ -59,7 +59,7 @@
public class DataSourceFactory {
private static final Localizer _loc = Localizer.forPackage
- (DataSourceFactory.class);
+ (DataSourceFactory.class);
/**
* Create a datasource using the given configuration.
@@ -120,7 +120,7 @@
catch (OpenJPAException ke) {
throw ke;
} catch (Exception e) {
- throw new StoreException(e).setFatal(true);
+ throw newConnectException(conf, factory2, e);
}
// not a driver or a data source; die
@@ -175,7 +175,7 @@
} catch (OpenJPAException ke) {
throw ke;
} catch (Exception e) {
- throw new StoreException(e).setFatal(true);
+ throw newConnectException(conf, factory2, e);
}
}
@@ -237,14 +237,7 @@
return ds;
} catch (Exception e) {
- throw new StoreException(_loc.get("conn-failed", factory2
- ? new Object[]{conf.getConnection2DriverName(),
- conf.getConnection2URL(),
- conf.getConnection2Properties()}
- : new Object[]{conf.getConnectionDriverName(),
- conf.getConnectionURL(),
- conf.getConnectionProperties()}),
- e);
+ throw newConnectException(conf, factory2, e);
} finally {
if (conn != null)
try {
@@ -255,6 +248,18 @@
}
}
}
+
+ static OpenJPAException newConnectException(JDBCConfiguration conf,
+ boolean factory2, Exception cause) {
+ return new UserException(_loc.get("conn-failed", factory2
+ ? new Object[]{conf.getConnection2DriverName(),
+ conf.getConnection2URL(),
+ conf.getConnection2Properties()}
+ : new Object[]{conf.getConnectionDriverName(),
+ conf.getConnectionURL(),
+ conf.getConnectionProperties()}),
+ cause).setFatal(true);
+ }
/**
* Return a data source with the given user name and password
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java?rev=676073&r1=676072&r2=676073&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
Fri Jul 11 13:28:49 2008
@@ -77,8 +77,8 @@
throws SQLException {
Connection con = getDriver().connect(_connectionURL, props);
if (con == null) {
- throw new UserException(_loc.get("conn-failed",
- _connectionDriverName, _connectionURL, props));
+ throw new SQLException(_loc.get("conn-failed",
+ _connectionDriverName, _connectionURL,
props).getMessage());
}
return con;
}
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java?rev=676073&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
Fri Jul 11 13:28:49 2008
@@ -0,0 +1,198 @@
+/*
+ * 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.conf;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.PersistenceException;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * Verifies appropriate exception is thrown when an incorrect protocol or
+ * sub-protocol is specified in the JDBC URL. Per the JDBC specification, the
+ * Driver should return a null connection upon getConnection() when a bad
driver
+ * is specified on the URL. OpenJPA must be able to handle this condition and
+ * return an appropriate message.
+ *
+ * OpenJPA JIRA: [EMAIL PROTECTED]
http://issues.apache.org/jira/browse/OPENJPA-656}
+ *
+ * @author Jeremy Bauer
+ * @author Pinaki Poddar
+ *
+ */
+public class TestBadJdbcUrl extends TestCase {
+ public static final String GOOD_URL =
"jdbc:derby:target/database/openjpa-derby-database;create=true";
+ public static final String GOOD_DRIVER =
"org.apache.derby.jdbc.EmbeddedDriver";
+ public static final String GOOD_DATASOURCE =
"org.apache.commons.dbcp.BasicDataSource";
+
+ public static final String BAD_DRIVER = "bad.driver";
+ public static final String BAD_URL_PROTOCOL = "bad.url.protocol";
+ public static final String BAD_URL_SUBPROTOCOL = "bad.url.sub.protocol";
+ public static final String BAD_CONN_PROPS =
"connectionUrl=bad,connectionDriver=bad";
+
+ /*
+ * Test specifying URL with bad protocol but a valid Driver.
+ */
+ public void testBadUrlProtocolValueWithValidDriverClass() {
+ Properties p = new Properties();
+ p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
+ p.put("openjpa.ConnectionURL", BAD_URL_PROTOCOL);
+ verifyConnectException(p, PersistenceException.class,
+ UserException.class, GOOD_DRIVER,
BAD_URL_PROTOCOL);
+ }
+
+ /*
+ * Test specifying URL with bad protocol but a valid DataSource.
+ */
+ public void testBadUrlProtocolValueWithValidDataSource() {
+ Properties p = new Properties();
+ p.put("openjpa.ConnectionDriverName", GOOD_DATASOURCE);
+ p.put("openjpa.ConnectionURL", BAD_URL_PROTOCOL);
+ p.put("openjpa.ConnectionProperties", BAD_CONN_PROPS);
+ verifyConnectException(p, PersistenceException.class,
+ null, (String[])null);
+ }
+
+ /*
+ * Test specifying URL with bad sub-protocol but a valid Driver.
+ */
+ public void testBadUrlSubprotocolValueWithValidDriverClass() {
+ Properties p = new Properties();
+ p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
+ p.put("openjpa.ConnectionURL", BAD_URL_SUBPROTOCOL);
+ verifyConnectException(p, PersistenceException.class,
+ UserException.class, GOOD_DRIVER,
BAD_URL_SUBPROTOCOL);
+ }
+
+ /*
+ * Test specifying URL with bad sub-protocol but a valid Driver.
+ */
+ public void testBadUrlSubprotocolValueWithValidDataSource() {
+ Properties p = new Properties();
+ p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
+ p.put("openjpa.ConnectionURL", BAD_URL_SUBPROTOCOL);
+ verifyConnectException(p, PersistenceException.class,
+ UserException.class, GOOD_DRIVER,
BAD_URL_SUBPROTOCOL);
+ }
+
+ /*
+ * Test specifying Valid URL with an invalid Driver.
+ */
+ public void testValidUrlWithInvalidDriver() {
+ Properties p = new Properties();
+ p.put("openjpa.ConnectionDriverName", BAD_DRIVER);
+ p.put("openjpa.ConnectionURL", GOOD_URL);
+ verifyConnectException(p, PersistenceException.class,
+ UserException.class, GOOD_URL, BAD_DRIVER);
+ }
+
+ /**
+ * Attempts to connect with given properties and analyze exception for
the
+ * existence of given target exception and error message strings.
+ *
+ * @param props
+ * the properties to initialize the persistence unit
+ * @param target
+ * the type expected exception to be raised.
+ * @param nested
+ * the type expected nested exception. null implies not to
look
+ * for any.
+ * @param keys
+ * the strings that must occur in the exception message.
+ */
+ private void verifyConnectException(Properties props, Class targetType,
+ Class nestedType, String... keys) {
+ EntityManagerFactory emf = null;
+ EntityManager em = null;
+ try {
+ emf = Persistence.createEntityManagerFactory("test",
props);
+ em = emf.createEntityManager();
+ OpenJPAPersistence.cast(em).getConnection();
+ fail("Should have caught a " + targetType.getName());
+ } catch (Throwable t) {
+ assertException(t, targetType, nestedType);
+ assertMessage(t, keys);
+ } finally {
+ if (em != null)
+ em.close();
+ if (emf != null)
+ emf.close();
+ }
+ }
+
+ /**
+ * Asserts that the given targetType is assignable from actual. Asserts
that
+ * the nestedType is a nested within the given actual Throwable
+ *
+ * @param actual
+ * @param targetType
+ * @param nestedType
+ */
+ void assertException(final Throwable actual, Class targetType,
+ Class nestedTargetType) {
+ if (targetType == null)
+ return;
+ assertNotNull(actual);
+ Class actualType = actual.getClass();
+ if (!targetType.isAssignableFrom(actualType)) {
+ actual.printStackTrace();
+ fail(targetType.getName() + " is not assignable from "
+ + actualType.getName());
+ }
+
+ if (nestedTargetType != null) {
+ Throwable nested = actual.getCause();
+ Class nestedType = (nested == null) ? null :
nested.getClass();
+ while (nestedType != null) {
+ if
(nestedType.isAssignableFrom(nestedTargetType)) {
+ return;
+ } else {
+ Throwable next = nested.getCause();
+ if (next == null || next == nested)
+ break;
+ nestedType = next.getClass();
+ nested = next;
+ }
+ }
+ actual.printStackTrace();
+ fail("No nested type " + nestedTargetType + " in " +
actual);
+ }
+ }
+
+ /**
+ * Assert that each of given keys are present in the message of the
given
+ * Throwable.
+ */
+ void assertMessage(Throwable actual, String... keys) {
+ if (actual == null || keys == null)
+ return;
+ String message = actual.getMessage();
+ for (String key : keys) {
+ assertTrue(key + " is not in " + message,
message.contains(key));
+ }
+ }
+}