Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connection cannot be cast to oracle.jdbc.OracleConnection

Why java.sql.Connection cannot be cast to oracle.jdbc.OracleConnection in code below?

My main goal is to pass to Oracle connection new user name and save it in 'SESSION' table in for example 'osuser' column because I want to trace in DB user changes and display it in the table.

@Repository
public class AuditLogDAOImpl implements AuditLogDAO {

    @PersistenceContext(unitName="myUnitName")
    EntityManager em;

    @Resource(name = "dataSource")
    DataSource dataSource;

    public void init() {

        try {
            Connection connection = DataSourceUtils.getConnection(dataSource);
            OracleConnection oracleConnection = (OracleConnection) connection; //Here I got cast exception!

            String metrics[] = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
            metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = "my_new_username";

            oracleConnection.setEndToEndMetrics(metrics, (short) 0);

            java.util.Properties props = new java.util.Properties();
            props.put("osuser", "newValue");

            oracleConnection.setClientInfo(props);

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Here is error log:

10:42:29,251 INFO  [STDOUT] org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6@bcc8cb
10:42:51,701 ERROR [STDERR] java.lang.ClassCastException: $Proxy286 cannot be cast to oracle.jdbc.OracleConnection

Generally I have 2 problem in this case:

  • why cast from Connection to OracleConnection fails and
  • what is the best way to implement my intend (I mean set the new user name to v$session.osuser in Oracle DB?

I work with Oracle 11g, Hibernate (using entity manager), data source via jndi.

Please help, thanks!

EDIT:

After some improvement the problem with casting still exists.

Improvement:

Connection connection = DataSourceUtils.getConnection(dataSource);
connection = ((org.jboss.resource.adapter.jdbc.WrappedConnection)connection).getUnderlyingConnection();
OracleConnection oracleConnection = (OracleConnection) connection;

Error:

java.lang.ClassCastException: $Proxy287 cannot be cast to org.jboss.resource.adapter.jdbc.WrappedConnection
like image 443
Roman Avatar asked Mar 18 '13 17:03

Roman


4 Answers

The connection you are retrieving is probably a wrapped connection.

If you really need to get the underlying Oracle connection you should use:

if (connection.isWrapperFor(OracleConnection.class)){
   OracleConnection oracleConnection= connection.unwrap(OracleConnection.class);  
}else{
   // recover, not an oracle connection
}

The isWrapperFor and unwrap methods are available since Java 1.6, and should be meaningfully implemented by the A/S connection wrappers.

like image 139
Carlo Pellegrini Avatar answered Nov 08 '22 22:11

Carlo Pellegrini


The connection pool usually has a wrapper around the real connection instance, that's why your cast fails.

What you are doing wouldn't work anyway, because the parameters in the properties instance are only checked when the connection is established. As you have a connection that is already active, it won't change anything.

You need tou use DBMS_APPLICATION_INFO.SET_CLIENT_INFO() in order to change this for an existing connection.

like image 4
a_horse_with_no_name Avatar answered Nov 08 '22 21:11

a_horse_with_no_name


This is just for people who come here via search on how to set metrics in OracleConnection, I spend great deal of time on this, so might help someone.

After you get your "connection" this should work:

DatabaseMetaData dmd = connection.getMetaData();
Connection metaDataConnection = null;

if(dmd != null)
{
    metaDataConnection = dmd.getConnection();
}

if(!(metaDataConnection instanceof OracleConnection))
{
    log.error("Connection is not instance of OracleConnection, returning");
    return; /* Not connection u want */
}

OracleConnection oraConnection = (OracleConnection)metaDataConnection;

String[] metrics = new String[END_TO_END_STATE_INDEX_MAX]; // Do the rest below...

It works for me for OracleConnection, but I face diff issue when setting metrics:

short zero = 0;
oraConnection.setEndToEndMetrics(metrics, zero);

After proxying connection via my method where I set metrics few times, I get:

java.sql.SQLRecoverableException: No more data to read from socket

But I think it has to do with some Spring wiring inits or connection pool.

like image 3
Jenya G Avatar answered Nov 08 '22 22:11

Jenya G


i had faced this issue when using spring to get connections. Typically , each layer adds a wrapper over the basic classes. i had just done connection.getClass().getName() to see the runtime type of the connection being retuned. It will be a Wrapper/proxy over which you can easily find the method to get the base OracleConnection type.

like image 1
Akhilesh Singh Avatar answered Nov 08 '22 23:11

Akhilesh Singh