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:
I work with Oracle 11g, Hibernate (using entity manager), data source via jndi.
Please help, thanks!
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
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With