0

I am attempting to use a non-standard method, getServerJobIdentifier(), that is part of the IBM Java Tool Box (jt400.jar) and class com.ibm.as400.access.AS400JDBCConnection with C3P0 & rawConnectionOperation(). I am getting "java.lang.IllegalArgumentException: object is not an instance of declaring class". I have tried numerous options but have not stumbled upon the correct parameters to pass. I am using C3P0 0.9.5.4. Code snippet follows:

// The method I want to call.
// getServerJobIdentifier, public abstract java.lang.String com.ibm.as400.access.AS400JDBCConnection.getServerJobIdentifier()
String driverClassName = "com.ibm.as400.access.AS400JDBCDriver";
String m_DatabaseConnectionString = "jdbc:db2:*local;naming=sql;extended metadata=true";
Connection m_dbConnection;
ComboPooledDataSource   m_cpds;

m_cpds = new ComboPooledDataSource();
try {
    m_cpds.setDriverClass(driverClassName); //loads the jdbc driver
}
catch (Exception e) {
    e.printStackTrace();
    System.exit(0);
}
m_cpds.setJdbcUrl(m_DatabaseConnectionString);

m_dbConnection = m_cpds.getConnection();
String qualifiedName = "";
C3P0ProxyConnection castCon = (C3P0ProxyConnection)m_dbConnection;
Method m = AS400JDBCConnection.class.getDeclaredMethod("getServerJobIdentifier");
// This does return what I want.  getServerJobIdentified() has no parameters.
System.out.println("method=" + m.toString());
Object[] args = new Object[] {};

System.out.println("calling rawConnectionOperation");

qualifiedName = (String) castCon.rawConnectionOperation(m, C3P0ProxyConnection.RAW_CONNECTION, args);
// never gets here
System.out.println("qualifiedName=" + qualifiedName);

I know I'm that close or I think I am. Thanks!

import java.util.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import com.mchange.v2.c3p0.*;

import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400JDBCConnection;
import com.ibm.as400.access.AS400SecurityException;
import com.ibm.db2.jdbc.app.DB2Connection;

// javac -cp :./c3p0-0.9.5.4.jar:./mchange-commons-java-0.2.15.jar:./jt400.jar C3P0Main.java
// /QIBM/ProdData/OS400/jt400/lib/jt400Native.jar
// java -cp :./c3p0-0.9.5.4.jar:./mchange-commons-java-0.2.15.jar:./jt400.jar C3P0Main
// or
// java -cp :./c3p0-0.9.5.4.jar:./mchange-commons-java-0.2.15.jar:/QIBM/ProdData/OS400/jt400/lib/jt400Native.jar C3P0Main

// c3p0.acquireRetryAttempts=0
// c3p0.acquireRetryDelay=5000
// c3p0.breakAfterAcquireFailure=false

// c3p0.maxConnectionAge=10800
// c3p0.maxIdleTime=3600
// c3p0.maxIdleTimeExcessConnections=600

// c3p0.automaticTestTable=c3p0test
// c3p0.idleConnectionTestPeriod=600
// c3p0.testConnectionOnCheckout=true

// java -cp :./c3p0-0.9.5.4.jar:./mchange-commons-java-0.2.15.jar:./jt400.jar -Dc3p0.acquireRetryAttempts=0 -Dc3p0.acquireRetryDelay=5000 -Dc3p0.breakAfterAcquireFailure=false -Dc3p0.maxConnectionAge=10800 -Dc3p0.maxIdleTime=3600 -Dc3p0.maxIdleTimeExcessConnections=600 -Dc3p0.automaticTestTable=c3p0test -Dc3p0.idleConnectionTestPeriod=600 -Dc3p0.testConnectionOnCheckout=true C3P0Main

public class C3P0Main {
    private Connection m_dbConnection;
    private ComboPooledDataSource   m_cpds;
    private String driverClassName = "com.ibm.as400.access.AS400JDBCDriver";
    //private String m_DatabaseConnectionString = "jdbc:as400:BNADEV;naming=sql;extended metadata=true;user=beak;password=roatan12";
    private String m_DatabaseConnectionString = "jdbc:as400:BNADEV;naming=sql;extended metadata=true";
    private String m_databaseServerJobID;

    public C3P0Main() throws SQLException
    {
        m_cpds = new ComboPooledDataSource();
        try {
            m_cpds.setDriverClass(driverClassName); //loads the jdbc driver
        }
        catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
        m_cpds.setJdbcUrl(m_DatabaseConnectionString);
    }

    public void run(String[] args) throws Exception
    {
        m_dbConnection = m_cpds.getConnection();
        System.out.println("m_dbConnection=" + m_dbConnection.toString());

        String qualifiedName = "";
        try {
            // To use it, first cast the returned Connection to a C3P0ProxyConnection.
            // Then call the method rawConnectionOperation, supplying the java.lang.reflect.Method object
            // for the non-standard method you wish to call as an argument. The Method you supply will
            // be invoked on the target you provide on the second argument (null for static methods),
            // and using the arguments you supply in the third argument to that function. For the target,
            // and for any of the method arguments, you can supply the special token
            // C3P0ProxyConnection.RAW_CONNECTION, which will be replaced with the
            // underlying vendor-specific Connection object before the Method is invoked.
            //
            // C3P0ProxyConnection castCon = (C3P0ProxyConnection) c3p0DataSource.getConnection();
            // Method m = CLOB.class.getMethod("createTemporary", new Class[]{Connection.class, boolean.class, int.class});
            // Object[] args = new Object[] {C3P0ProxyConnection.RAW_CONNECTION, Boolean.valueOf( true ), new Integer( 10 )};
            // CLOB oracleCLOB = (CLOB) castCon.rawConnectionOperation(m, null, args);

            // getServerJobIdentifier, public abstract java.lang.String com.ibm.as400.access.AS400JDBCConnection.getServerJobIdentifier()

            System.out.println("Is a wrapper for DB2Connection=" + m_dbConnection.isWrapperFor(com.ibm.db2.jdbc.app.DB2Connection.class));
            System.out.println("Is a wrapper for AS400JDBCConnection=" + m_dbConnection.isWrapperFor(AS400JDBCConnection.class));

            C3P0ProxyConnection castCon = (C3P0ProxyConnection)m_dbConnection;

            System.out.println("C3P0ProxyConnection.RAW_CONNECTION=" + C3P0ProxyConnection.RAW_CONNECTION.getClass().getName());

            Method method = AS400JDBCConnection.class.getMethod("getServerJobIdentifier");

            System.out.println("method=" + method.toString());
            Object[] method_args = new Object[] {};

            System.out.println("calling rawConnectionOperation");

            try {
                qualifiedName = (String) castCon.rawConnectionOperation(method, m_dbConnection, method_args);
                System.out.println("qualifiedName=" + qualifiedName);
            }
            catch (IllegalArgumentException | SQLException | InvocationTargetException | IllegalAccessException e) {
                System.out.println(e);
                System.out.println("oh well #1.");
            }

            try {
                Object[] method_args = new Object[] {};
                qualifiedName = (String) castCon.rawConnectionOperation(method, m_dbConnection, method_args);
                System.out.println("qualifiedName=" + qualifiedName);
            }
            catch (IllegalArgumentException | SQLException | InvocationTargetException | IllegalAccessException e) {
                System.out.println(e);
                System.out.println("oh well #2.");
            }

            if (castCon instanceof AS400JDBCConnection) {
                System.out.println("YES");
                qualifiedName = ((AS400JDBCConnection)C3P0ProxyConnection.RAW_CONNECTION).getServerJobIdentifier();
                String jobName = qualifiedName.substring(0, 10).trim();
                String jobUser = qualifiedName.substring(10, 20).trim();
                String jobNumber = qualifiedName.substring(20).trim();
                m_databaseServerJobID = jobNumber + '/' + jobUser + '/' + jobName;
                System.out.println("SQL Server Job ID: " + m_databaseServerJobID);
            }
            else {
                System.out.println("m_dbConnection is not an instance of DB2Connection.");
            }
        }
        catch (IllegalArgumentException | SQLException | NoSuchMethodException e) {
            System.out.println(e);
            System.out.println("oh well.");
        }
    }

    public static void main(java.lang.String args[])
    {
        try {
            C3P0Main app = new C3P0Main();
            app.run(args);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Kelly Beard
  • 684
  • 1
  • 8
  • 20
  • It seems to me that AS400JDBCConnection has to be the wrapped class, but somehow it might not be. I'd at least like to know how to get that class from C3P0, but that's another thing I'm working on. – Kelly Beard Jan 22 '20 at 22:10
  • 1
    i am not sure why this isn't working, but JDBC4 added an alternative way to get at the underlying Connection that might be easier. (raw connection operations are still useful for statement/result-set returning methods, so c3p0 can clean them up, but that is not your case.) what happens if you try `m_dbConnection.unwrap(AS400JDBCConnection.class)`? – Steve Waldman Jan 23 '20 at 05:55
  • What would be best is a query method that tells you what the underlying class is, not having to guess. I thought that something like System.out.println("C3P0ProxyConnection.RAW_CONNECTION=" + C3P0ProxyConnection.RAW_CONNECTION.getClass().getName()); would give me something other than "java.lang.Object". – Kelly Beard Jan 23 '20 at 18:08
  • 1
    you can try `Connection c = m_dbConnection.unwrap( Connection.class ); System.out.println( c.getClass().getName() );` – Steve Waldman Jan 24 '20 at 19:44
  • I thought this might be what happened, but then I thought that it couldn't, but the class that comes back is com.ibm.db2.jdbc.app.DB2Connection and not AS400JDBCConnection. Strange because when I "jar tvf" all of my jar files, DB2Connection does not appear but AS400JDBCConnection does. I'll have to dig deeper. Thanks for the tip. – Kelly Beard Jan 27 '20 at 15:00

0 Answers0