You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mt...@apache.org on 2009/12/01 22:13:31 UTC
svn commit: r885935 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/
Author: mtylenda
Date: Tue Dec 1 21:13:30 2009
New Revision: 885935
URL: http://svn.apache.org/viewvc?rev=885935&view=rev
Log:
OPENJPA-1248: Improve LOB streaming with PostgreSQL when connections are being wrapped by data source; refactor and modify test case not to run Reader LOB tests while on PostgreSQL
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java
openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/AbstractLobTest.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/TestInputStreamLob.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java?rev=885935&r1=885934&r2=885935&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java Tue Dec 1 21:13:30 2009
@@ -24,6 +24,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.security.AccessController;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
@@ -47,6 +48,7 @@
import org.apache.openjpa.lib.jdbc.DelegatingConnection;
import org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement;
import org.apache.openjpa.lib.util.ConcreteClassGenerator;
+import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.InternalException;
@@ -56,7 +58,7 @@
import org.postgresql.largeobject.LargeObjectManager;
/**
- * Dictionary for Postgres.
+ * Dictionary for PostgreSQL.
*/
public class PostgresDictionary
extends DBDictionary {
@@ -67,6 +69,9 @@
private static Constructor<PostgresConnection> postgresConnectionImpl;
private static Constructor<PostgresPreparedStatement> postgresPreparedStatementImpl;
+ private Method dbcpGetDelegate;
+ private Method connectionUnwrap;
+
static {
try {
postgresConnectionImpl = ConcreteClassGenerator.getConcreteConstructor(
@@ -385,8 +390,7 @@
DelegatingConnection conn = (DelegatingConnection)store
.getConnection();
conn.setAutoCommit(false);
- LargeObjectManager lom = ((PGConnection)conn.getInnermostDelegate())
- .getLargeObjectAPI();
+ LargeObjectManager lom = getLargeObjectManager(conn);
if (rs.getInt(column) != -1) {
LargeObject lo = lom.open(rs.getInt(column));
return lo.getInputStream();
@@ -412,8 +416,7 @@
.getConnection();
try {
conn.setAutoCommit(false);
- PGConnection pgconn = (PGConnection)conn.getInnermostDelegate();
- LargeObjectManager lom = pgconn.getLargeObjectAPI();
+ LargeObjectManager lom = getLargeObjectManager(conn);
// The create method is valid in versions previous to 8.3
// in 8.3 this method is deprecated, use createLO
int oid = lom.create();
@@ -451,9 +454,7 @@
int oid = res.getInt(1);
if (oid != -1) {
conn.setAutoCommit(false);
- PGConnection pgconn = (PGConnection)conn
- .getInnermostDelegate();
- LargeObjectManager lom = pgconn.getLargeObjectAPI();
+ LargeObjectManager lom = getLargeObjectManager(conn);
if (ob != null) {
LargeObject lo = lom.open(oid, LargeObjectManager.WRITE);
OutputStream os = lo.getOutputStream();
@@ -466,9 +467,7 @@
} else {
if (ob != null) {
conn.setAutoCommit(false);
- PGConnection pgconn = (PGConnection)conn
- .getInnermostDelegate();
- LargeObjectManager lom = pgconn.getLargeObjectAPI();
+ LargeObjectManager lom = getLargeObjectManager(conn);
oid = lom.create();
LargeObject lo = lom.open(oid, LargeObjectManager.WRITE);
OutputStream os = lo.getOutputStream();
@@ -514,9 +513,7 @@
int oid = res.getInt(1);
if (oid != -1) {
conn.setAutoCommit(false);
- PGConnection pgconn = (PGConnection)conn
- .getInnermostDelegate();
- LargeObjectManager lom = pgconn.getLargeObjectAPI();
+ LargeObjectManager lom = getLargeObjectManager(conn);
lom.delete(oid);
}
} finally {
@@ -677,6 +674,75 @@
}
/**
+ * Get the native PostgreSQL Large Object Manager used for LOB handling.
+ */
+ protected LargeObjectManager getLargeObjectManager(DelegatingConnection conn) throws SQLException {
+ return getPGConnection(conn).getLargeObjectAPI();
+ }
+
+ /**
+ * Get the native PostgreSQL connection from the given connection.
+ * Various attempts of unwrapping are being performed.
+ */
+ protected PGConnection getPGConnection(DelegatingConnection conn) {
+ Connection innerConn = conn.getInnermostDelegate();
+ if (innerConn instanceof PGConnection) {
+ return (PGConnection) innerConn;
+ }
+ if (innerConn.getClass().getName().startsWith("org.apache.commons.dbcp")) {
+ return (PGConnection) getDbcpDelegate(innerConn);
+ }
+ return (PGConnection) unwrapConnection(conn, PGConnection.class);
+ }
+
+ /**
+ * Get the delegated connection from the given DBCP connection.
+ *
+ * @param conn must be a DBCP connection
+ * @return connection the DBCP connection delegates to
+ */
+ protected Connection getDbcpDelegate(Connection conn) {
+ Connection delegate = null;
+ try {
+ if (dbcpGetDelegate == null) {
+ Class<?> dbcpConnectionClass =
+ Class.forName("org.apache.commons.dbcp.DelegatingConnection", true, AccessController
+ .doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()));
+
+ dbcpGetDelegate = dbcpConnectionClass.getMethod("getInnermostDelegate");
+ }
+ delegate = (Connection) dbcpGetDelegate.invoke(conn);
+ } catch (Exception e) {
+ throw new InternalException(_loc.get("dbcp-unwrap-failed"), e);
+ }
+ if (delegate == null) {
+ throw new InternalException(_loc.get("dbcp-unwrap-failed"));
+ }
+ return delegate;
+ }
+
+ /**
+ * Get (unwrap) the delegated connection from the given connection.
+ * Use reflection to attempt to unwrap a connection.
+ * Note: This is a JDBC 4 operation, so it requires a Java 6 environment
+ * with a JDBC 4 driver or data source to have any chance of success.
+ *
+ * @param conn a delegating connection
+ * @param connectionClass the expected type of delegated connection
+ * @return connection the given connection delegates to
+ */
+ private Connection unwrapConnection(Connection conn, Class<?> connectionClass) {
+ try {
+ if (connectionUnwrap == null) {
+ connectionUnwrap = Connection.class.getMethod("unwrap", Class.class);
+ }
+ return (Connection) connectionUnwrap.invoke(conn, connectionClass);
+ } catch (Exception e) {
+ throw new InternalException(_loc.get("connection-unwrap-failed"), e);
+ }
+ }
+
+ /**
* Connection wrapper to work around the postgres empty result set bug.
*/
protected abstract static class PostgresConnection
Modified: openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties?rev=885935&r1=885934&r2=885935&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties Tue Dec 1 21:13:30 2009
@@ -194,3 +194,9 @@
continue processing. If this is a benign error you may disable it entirely \
by setting the supportsQueryTimeout attribute on the DBDictionary to false.\
The exception thrown was {1}.
+dbcp-unwrap-failed: Unable to get underlying connection from DBCP pooled \
+ connection. Make sure the DBCP property AccessToUnderlyingConnectionAllowed \
+ is enabled.
+connection-unwrap-failed: Unable to get underlying connection from pooled \
+ connection. Java version 6 and a version 4 capable JDBC driver \
+ or data source are minimum requirements to perform this operation.
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/AbstractLobTest.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/AbstractLobTest.java?rev=885935&r1=885934&r2=885935&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/AbstractLobTest.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/AbstractLobTest.java Tue Dec 1 21:13:30 2009
@@ -20,17 +20,18 @@
package org.apache.openjpa.jdbc.meta.strats;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.datacache.DataCachePCData;
-import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.MySQLDictionary;
import org.apache.openjpa.jdbc.sql.OracleDictionary;
-import org.apache.openjpa.jdbc.sql.PostgresDictionary;
import org.apache.openjpa.jdbc.sql.SQLServerDictionary;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.persistence.JPAFacadeHelper;
@@ -46,25 +47,22 @@
public abstract class AbstractLobTest extends SingleEMFTestCase {
+ protected List<Class<? extends DBDictionary>> supportedDatabases =
+ new ArrayList<Class<? extends DBDictionary>>
+ (Arrays.asList(MySQLDictionary.class, OracleDictionary.class, SQLServerDictionary.class));
+
public void setUp() throws Exception {
+ setSupportedDatabases(supportedDatabases.toArray(new Class<?>[] {}));
+ if (isTestsDisabled()) {
+ return;
+ }
+
super.setUp(getLobEntityClass(), CLEAR_TABLES,
"openjpa.DataCache", "true",
"openjpa.RemoteCommitProvider", "sjvm",
"openjpa.ConnectionRetainMode", "transaction");
}
- public boolean isDatabaseSupported() {
- DBDictionary dict = ((JDBCConfiguration) emf.getConfiguration())
- .getDBDictionaryInstance();
- if (dict instanceof MySQLDictionary ||
- dict instanceof SQLServerDictionary ||
- dict instanceof OracleDictionary ||
- dict instanceof PostgresDictionary) {
- return true;
- }
- return false;
- }
-
public void insert(LobEntity le) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -74,12 +72,10 @@
}
public void testInsert() {
- if (!isDatabaseSupported()) return;
insert(newLobEntity("oOOOOOo", 1));
}
public void testInsertAndSelect() throws IOException {
- if (!isDatabaseSupported()) return;
String s = "oooOOOooo";
insert(newLobEntity(s, 1));
EntityManager em = emf.createEntityManager();
@@ -94,7 +90,6 @@
}
public void testInsertNull() {
- if (!isDatabaseSupported()) return;
insert(newLobEntity(null, 1));
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -105,7 +100,6 @@
}
public void testUpdate() throws IOException {
- if (!isDatabaseSupported()) return;
insert(newLobEntity("oOOOOOo", 1));
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -123,7 +117,6 @@
}
public void testUpdateWithNull() {
- if (!isDatabaseSupported()) return;
insert(newLobEntity("oOOOOOo", 1));
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -140,7 +133,6 @@
}
public void testUpdateANullObjectWithoutNull() throws IOException {
- if (!isDatabaseSupported()) return;
insert(newLobEntity(null, 1));
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -158,7 +150,6 @@
}
public void testDelete() {
- if (!isDatabaseSupported()) return;
insert(newLobEntity("oOOOOOo", 1));
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -175,7 +166,6 @@
}
public void testLifeCycleInsertFlushModify() {
- if (!isDatabaseSupported()) return;
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
LobEntity le = newLobEntity("oOOOOOo", 1);
@@ -187,7 +177,6 @@
}
public void testLifeCycleLoadFlushModifyFlush() {
- if (!isDatabaseSupported()) return;
insert(newLobEntity("oOOOOOo", 1));
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -201,7 +190,6 @@
public void testReadingMultipleTimesWithASingleConnection()
throws IOException {
- if (!isDatabaseSupported()) return;
insert(newLobEntity("oOOOOOo", 1));
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -222,7 +210,6 @@
}
public void testDataCache() {
- if (!isDatabaseSupported()) return;
OpenJPAEntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -241,7 +228,6 @@
}
public void testSetResetAndFlush() throws IOException {
- if (!isDatabaseSupported()) return;
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
LobEntity le = newLobEntity("oOOOOOo", 1);
@@ -259,7 +245,6 @@
}
public void testSetFlushAndReset() throws IOException {
- if (!isDatabaseSupported()) return;
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
LobEntity le = newLobEntity("oOOOOOo", 1);
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/TestInputStreamLob.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/TestInputStreamLob.java?rev=885935&r1=885934&r2=885935&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/TestInputStreamLob.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/meta/strats/TestInputStreamLob.java Tue Dec 1 21:13:30 2009
@@ -22,6 +22,8 @@
import java.io.IOException;
import java.io.InputStream;
+import org.apache.openjpa.jdbc.sql.PostgresDictionary;
+
/**
* Defines all the abstract methods from AbstractLobTest to tests the
* the LOB support with an InputStream.
@@ -32,6 +34,12 @@
public class TestInputStreamLob extends AbstractLobTest {
+ @Override
+ public void setUp() throws Exception {
+ supportedDatabases.add(PostgresDictionary.class);
+ super.setUp();
+ }
+
protected LobEntity newLobEntity(String s, int id) {
InputStreamLobEntity isle = new InputStreamLobEntity();
isle.setId(id);