ggkmath
ggkmath

Reputation: 4246

newbie java error for ClassCastException connecting to remote database using JDBC

Anyone know what could be causing the following RUN TIME error in my Java program trying to access an Oracle database on a different Linux server?

java.lang.ClassCastException : com.sun.gjc.spi.jdbc40.CallableStatementWrapper40 cannot be cast to oracle.jdbc.OracleCallableStatement

I was following the discussion/example on page 4-14 to 4-15 in Oracle's JDBC Developer Guide ( http://isu.ifmo.ru/docs/doc112/java.112/e10589.pdf ). I created something similar to that example and it worked fine. Then I started modifying it to get to the below code AND introduced GlassFish into the process, and now I get that error.

Here's my Java code:

public List<Report> GetReports(String var1, String var1, String var3) throws Exception {
    Connection conn;
    CallableStatement cs;
    ResultSet rset;
    String out1; 

    Context context = new InitialContext();
    DataSource ds = (DataSource)context.lookup("jdbc/myPool");
    conn = ds.getConnection();

    cs = conn.prepareCall( "{call my_proc (?,?,?,?,?)}" );

    cs.setString(1, var1);
    cs.setString(2, var2);
    cs.setString(3, var3);

    cs.registerOutParameter(4, Types.VARCHAR);
    cs.registerOutParameter(5, OracleTypes.CURSOR);

    cs.execute();

    out1 = cs.getString(4); 

    List<Report> userReports = new ArrayList<Report>();

    rset = ((OracleCallableStatement)cs).getCursor(5);
    while ( rset.next() ) {
        Report report = new Report();
        report.col1 = rset.getString("myCol1");
        report.col2 = rset.getString("myCol2");
        userReports.add(report);
    }

    if ( rset != null ) {
        try { rset.close(); } catch ( Exception ex ) {}
        rset = null;
    }

    if ( conn != null ) {
        try { conn.close(); } catch ( Exception ex ) {}
        conn = null;
    }

return userReports;
}

Upvotes: 0

Views: 1900

Answers (3)

ggkmath
ggkmath

Reputation: 4246

There's probably more than one way to solve this, but the following change to the above code works for me. Replace this statement:

rset = ((OracleCallableStatement)cs).getCursor(5);

with this statement:

rset = (ResultSet) cs.getObject(5);

Upvotes: 0

Perception
Perception

Reputation: 80633

GlassFish enables something called statement wrapping by default. With this option enabled your statements, result sets and database meta data objects all get wrapped in a 'proxy' object. Normally there is no issue with this because you access these objects only via their standard JDBC interfaces, but if you need vendor specific capabilities then you will need to take extra steps to get past this 'proxy'.

Context context = new InitialContext();
DataSource ds = (DataSource)context.lookup("jdbc/myPool");
conn = ds.getConnection();
conn = ds.getConnection(conn); // <-- 'Unwrap' the vendor specific connection

On a side note, it doesn't look like you need the Oracle specific version of callable statement, the cast might be totally superfluous.

You can read more about statement wrapping on the Oracle Development Guide for Glassfish Server.

Upvotes: 1

twain249
twain249

Reputation: 5706

The problem is you defined the variable as

CallableStatement cs;

and then casted it with

rset = ((OracleCallableStatement)cs).getCursor(5);

the CallableStatement is the super interface of OracleCallableStatement and you can't cast a super interface to it's child (you can do the opposite). You should be able to just change cs into an OracleCallableStatement.

Upvotes: 0

Related Questions