0

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;
}
1
  • can we assume the context was already binded to an Oracle Data Source? If so, when you lookup the context, instead of (DataSource), use (OracleDataSource) Commented Mar 9, 2012 at 4:36

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Perception. I borrowed this cast to the Oracle specific version from the link above, so perhaps I don't need it with GlassFish (?). How to eliminate the Oracle specifics? Should I just replace OracleCallableStatement with CallableStatement, or is something else needed?
Looks like you need to do the cast, to use the getCursor() method. Which is fine, just make sure to unwrap your connection like I showed in my code example (conn = ds.getConnection(conn);).
The unwrapping line above results in compile error on the this same (unwrap) line: cannot find symbol, symbol: method getConnection(java.sql.Connection), location: interface javax.sql.DataSource. I have imported both java.sql.* and javax.sql.DataSource.
0

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.

5 Comments

Thanks twain249, after doing that, I get a compile error on the conn.prepareCall( statement: java:230: incompatible types. found: java.sql.CallableStatement, required: oracle.jdbc.OracleCallableStatement.
The link above to page 4-14 and 4-15 of Oracle's JDBC Dev Guide shows cs is cast as a CallableStatement (and it compiles fine). I'm not sure this is the problem (or how else to explain their code?).
Try adding a cast to OracleCallableStatement in that line.
Thanks twain249. What would the syntax for that be?
cs = (OracleCallableStatement)conn.prepareCall( "{call my_proc (?,?,?,?,?)}" )
0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.