Search code examples
oracle11gc3p0

Why does C3p0's ComboPooledDataSource successfully connect to a database, but its clone doesn't?


In a Tomcat 8.5.15 environment using an Oracle 11 database, I want to implement a data source that handles encrypted passwords in the context.xml. I'm having troubles with that, as described in this StackOverflow question.

In hopes of determining the underlying problem, I simplified the scenario. First, I verified that the C3p0 resource specification worked fine.

   <Resource 
              auth="Container"
              description="MyDataSource"
              driverClass="oracle.jdbc.OracleDriver" 
              maxPoolSize="100"  
              minPoolSize="10"   
              acquireIncrement="1"  
              name="jdbc/MyDataSource"
              user="me"  
              password="mypassword"
              factory="org.apache.naming.factory.BeanFactory"
              type="com.mchange.v2.c3p0.ComboPooledDataSource"
              jdbcUrl="jdbc:oracle:thin:@mydb:1521:dev12c"
              />

It worked fine. Then, I created a clone of the ComboPooledDataSource, based on decompiling the class file:

public final class ComboPooledDataSourceCopy
        extends AbstractComboPooledDataSource
        implements Serializable, Referenceable {
    private static final long serialVersionUID = 1L;
    private static final short VERSION = 2;

    public ComboPooledDataSourceCopy() {
    }

    public ComboPooledDataSourceCopy(boolean autoregister) {
        super(autoregister);
    }

    public ComboPooledDataSourceCopy(String configName) {
        super(configName);
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.writeShort(2);
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        short version = ois.readShort();
        switch(version) {
            case 2:
                return;
            default:
                throw new IOException("Unsupported Serialized Version: " + version);
        }
    }
}

I created a revised resource specification using the cloned class:

   <Resource 
              auth="Container"
              description="MyDataSource"
              driverClass="oracle.jdbc.OracleDriver" 
              maxPoolSize="100"  
              minPoolSize="10"   
              acquireIncrement="1"  
              name="jdbc/MyDataSource"
              user="me"  
              password="mypassword"
              factory="org.apache.naming.factory.BeanFactory"
              type=type="com.mycompany.ComboPooledDataSourceCopy"
              jdbcUrl="jdbc:oracle:thin:@mydb:1521:dev12c"
              />

When I try to connect to the database using this specification, the connection attempt fails.

...
Caused by: java.sql.SQLException: com.mchange.v2.c3p0.impl.NewProxyConnection@6950dfda
[wrapping: oracle.jdbc.driver.T4CConnection@765426dd]
is not a wrapper for or implementation of oracle.jdbc.OracleConnection
    at com.mchange.v2.c3p0.impl.NewProxyConnection.unwrap(NewProxyConnection.java:1744)
    at org.jaffa.security.JDBCSecurityPlugin.executeStoredProcedure(JDBCSecurityPlugin.java:117)
    ... 67 more

Why does the clone attempt fail to connect?

UPDATE:

With assistance from our local DBA, we’ve been able to audit my connection attempts. It appears that we are successfully connecting to the database and logging in. Based on this, it sounds like the problem may be in how the code is handling the database’s response, rather than in our request generation.


Solution

  • The error was a result of a class loading problem, where the Oracle classes were being loaded from multiple jars (%CATALINA_HOME%\lib\ojdbc7-12.1.0.2.0.jar and %CATALINA_HOME%\webapps\my-webapp-1.0.0\WEB-INF\lib\ojdbc7-12.1.0.2.0.jar) by different class loaders. When I deleted %CATALINA_HOME%\webapps\my-webapp-1.0.0\WEB-INF\lib\ojdbc7-12.1.0.2.0.jar, my problem went away.

    These sources (1, 2, 3) discuss this in more detail.