Search code examples
javasqloraclejdbcwebsphere

Cannot unwrap Oracle Connection


I recently upgraded my app (which uses WebSphere) to use ojdbc8. Here are lines where I unwrap a connection:

import java.sql.Connection;
import oracle.jdbc.OracleConnection;
// some processing here
public void unwrapAndProcess(Connection con) {
  OracleConnection conn = con.unwrap(OracleConnection.class);
  StructDescriptor desc = StructDescriptor.createDescriptor("DATAVAL", conn); // exception here
  // more processing here
}

Suddenly, I am getting the following issue on the line where I call .createDescriptor.

java.lang.RuntimeException: java.sql.SQLFeatureNotSupportedException: DSRA9130: Operation is not permitted by the application server: unwrap

I am not sure of the real cause as to why I am getting this issue or what can be done to rectify.

Here is a snippet of the exact stacktrace:

java.lang.RuntimeException: java.sql.SQLFeatureNotSupportedException: DSRA9130: Operation is not permitted by the application server: unwrap 
at com.ibm.ws.rsadapter.jdbc.WSJdbcWrapper.invoke(WSJdbcWrapper.java:259)
at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.invoke(WSJdbcConnection.java:5512)
at com.sun.proxy.$Proxy136.unwrap(Unknown Source)
at oracle.sql.StructDescriptor.isValidObject(StructDescriptor.java:90)
at oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:115)
at oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:79)
at (class & line where StructDescriptor.createDescriptor is used)

Solution

  • So the issue here is not the unwrap operation. Instead, it is what the Oracle driver does with the unwrapped connection.

    When calling the method:

    StructDescriptor desc = StructDescriptor.createDescriptor("DATAVAL", conn);
    

    The driver itself is trying to validate the connection and in doing so is trying to unwrap it again!

    The connection itself is still only a proxy connection handed out by WebSphere and not the physical connection.

    As such, we attempt to block method calls that could allow the user to close the underlying connection without it getting removed from the WebSphere connection pool.

    If we allowed the OracleConnection.unwrap() method to be invoked, then the driver would hand back the physical connection and the physical connection in the connection pool would be leaked.

    So it looks like this method in the ojdbc8 driver was written to be incompatible with third-party connection pools.

    I'm not too familiar with the method itself, but if you could use this method instead it does not do the same validation: https://javadoc.io/static/com.oracle.database.jdbc/ojdbc8/12.2.0.1/oracle/sql/StructDescriptor.html#createDescriptor-oracle.sql.SQLName-java.sql.Connection-boolean-boolean-

    Otherwise, the class itself is deprecated and the suggestion is to use java.sql.Struct which would likely be the best long-term solution for future upgrades.