Apache Commons DBCP connection object problem, Thread: ClassCastException in org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper

Viewed 54709

I am using Apache Commons DBCP (commons-dbcp.jar) Connection pool.

Once I obtained a connection from the pool it is wrapped in the class org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.

My requirement is to pass an array of Strings to pl/sql stored procedure in Oracle.

Here is what I am doing in the following code snippet:

Connection dbConn = ConnectionManager.ds.getConnection();
//The above statement returns me an connection wrapped in the class
//org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.

org.apache.commons.dbcp.DelegatingConnection del = new org.apache.commons.dbcp.DelegatingConnection(dbConn.getConnection());
con = del.getInnermostDelegate();

cs = con.prepareCall("call SP_NAME(?,?,?,?)");
oracle.sql.ArrayDescriptor arDesc= oracle.sql.ArrayDescriptor.createDescriptor("ARRAY_NAME", (OracleConnection) con);

CallableStatement c_stmt = conn.prepareCall("begin update_message_ids_ota
(:x); end;" );
c_stmt.setArray( 1, array_to_pass );
c_stmt.execute();

On executing the above code, I get the following exception:

java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection at oracle.sql.ArrayDescriptor.createDescriptor

I tried to find out solution over this going throughout almost of the sites and forums, but couldn't get the satisfied answer or solution on the same.

11 Answers

Hmmm,I have meet the same solution like you.I think there a two position need you mention it. 1.Config Connection pool set accessToUnderlyingConnectionAllowed = "true" ; 2.The nightmare concerned to open source project. The terrable conceration. In this case,that is

org.apache.commons.dbcp.DelegatingConnection 

is not equal to

org.apache.tomcat.dbcp.dbcp.DelegatingConnection

while in default apache common-dbcp.jar,you will never find the follow Class.But just the class is the key. So,we must find the Class in somewhere. I final find the package tomcat-dbcp.jar . You can get it from http://www.docjar.com/ After

import org.apache.tomcat.dbcp.dbcp.DelegatingConnection

,you can force cast you dbConn and get the Underlying Connection

oracle.jdbc.driver.OracleConnection delConn = 

(oracle.jdbc.driver.OracleConnection) 

((org.apache.tomcat.dbcp.dbcp.DelegatingConnection)c_stmt.getConnection()).getDelegate();

Then we can use delConn to get the ArrayDescriptor Remember one thing,in there,we do not need the

org.apache.commons.dbcp.DelegatingConnection Class

It's a so strange thing,but real work to the case.

I'm positing this here to make sure anyone else looking for advice knows about the ultimate solution to this:

If you're forced to use the non bundled version of the persistence manager (because an old repository still uses that structure which is incompatible with the bundled layout), here what you can do, the solution is quite simple:

Download the sources for Jackrabbit Core (you can get them from the Jackrabbit website) Open the OraclePersistenceManager class and find the following line of code:

Object blob = createTemporary.invoke(null,
                new Object[]{con, Boolean.FALSE, durationSessionConstant});

(Around line 377 - can also check the StackTrace for reference)

ConnectionFactory contains a static method that allows to unwrap a connection which is exactly what you need:

Object blob = createTemporary.invoke(null,
                new Object[]{org.apache.jackrabbit.core.util.db.ConnectionFactory
                        .unwrap(con), Boolean.FALSE, durationSessionConstant});

You will need Maven 2+ in order to compile the sources, I did that and had no dependency problems, note that I compiled version 2.2.10 of Jackrabbit.

I also made sure to log a bug against Jackrabbit 2.2.11 (current release which still has the issue): https://issues.apache.org/jira/browse/JCR-3262

Hope this helps!

I'm using java7 & ojdbc7.jar & Tomcat 8.

I had the same issue in tomcat while converting ((OracleConnection)connection).createARRAY

After searching for lot of solutions and forums, finally the worked solution for me is,

Connection connection = datasource.getConnection();
CallableStatement cs = connection.prepareCall("{ CALL PKG.PROCEDURE(?)}");

if(cs.getConnection().isWrapperFor(OracleConnection.class)) {
  OracleConnection orConn = cs.getConnection().unwrap(OracleConnection.class);
  orConn.createARRAY ..// is working perfectly.

}

If you did connection.isWrapperFor(OracleConnection.class) you will get false. you need to use cs.getConnection.

Might help someone.

Related