Application logging throws vfrtshadow ConnectionWrapper cannot be cast to DB Connection error
This issue occurs in the following circumstances:
- The vFunction Sudo or Sudoless Controller Installation TGZ is installed in a Linux environment
- An Application Server is used to run the JVM
- After adding the vFunction Agent Startup Parameters into the JVM, the Application is rebooted and the following error occurs
Sample Error #1
java.io.IOException: java.lang.ClassCastException: class vfrtshadow.com.p6spy.engine.wrapper.ConnectionWrapper cannot be cast to class org.postgresql.PGConnection
(vfrtshadow.com.p6spy.engine.wrapper.ConnectionWrapper and org.postgresql.PGConnection are in unnamed module of loader 'app')
at simple.io.ParallelOutputStream.executeAll(ParallelOutputStream.java:158) ~[bin/:?]
at simple.io.ParallelOutputStream.flush(ParallelOutputStream.java:124) ~[bin/:?]
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:143) ~[?:?]
at java.util.zip.DeflaterOutputStream.flush(DeflaterOutputStream.java:291) ~[?:?]
at java.io.FilterOutputStream.flush(FilterOutputStream.java:153) ~[?:?]
at simple.io.resource.SingleStashResource$ResourceOutputStream.flush(SingleStashResource.java:52) ~[bin/:?]
at simple.io.resource.ReplicatedStashResource$2.flush(ReplicatedStashResource.java:66) ~[bin/:?]
...
Caused by: java.lang.ClassCastException: class vfrtshadow.com.p6spy.engine.wrapper.ConnectionWrapper cannot be cast to class org.postgresql.PGConnection
(vfrtshadow.com.p6spy.engine.wrapper.ConnectionWrapper and org.postgresql.PGConnection are in unnamed module of loader 'app')
at simple.io.resource.AbstractDbResourceFolder.writeFileContent(AbstractDbResourceFolder.java:364) ~[bin/:?]
at simple.io.resource.AbstractDbResourceFolder$DbStashImpl.updateFileContent(AbstractDbResourceFolder.java:252) ~[bin/:?]
...
Sample Error #2
java.lang.ClassCastException: class vfrtshadow.com.p6spy.engine.wrapper.ConnectionWrapper cannot be cast to class oracle.jdbc.OracleConnection
(vfrtshadow.com.p6spy.engine.wrapper.ConnectionWrapper is in unnamed module of loader 'app'; oracle.jdbc.OracleConnection is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @100eeedc)
at com.relevant.namespace.data.NamespaceDataSource.getConnectionInternal(NamespaceDataSource.java:581)
at com.relevant.namespace.data.NamespaceDataSource.getConnection(NamespaceDataSource.java:518)
at com.relevant.namespace.data.internal.NamespaceConnection.createConnection(NamespaceConnection.java:201)
at com.relevant.namespace.data.internal.NamespaceConnection.<init>(NamespaceConnection.java:78)
This issue can be resolved by taking the following steps:
- Modify the code for the Database Connection to unwrap rather than Cast the connection. See the samples below.
- Deploy the code change.
- Restart the Application to confirm this change resolved the problem.
Sample Resolution #1
## Before
try{
conn = (OracleConnection) mUcpDataSource.getConnection();
applyConnectionOverrides(conn);
}
## After
try{
final var newConnection :Connection = mUcpDataSource.getConnection();
if (newConnection instanceof OracleConnection) {
conn = (OracleConnection) newConnection;
} else {
conn = newConnection.unwrap(OracleConnection.class);
}
applyConnectionOverrides(conn);
Sample Resolution #2
## Before
protected void writeFileContent(DbStashImpl stash, byte[] bytes, int byteOffset, int length, long contentOffset) throws IOException {
if(contentOffset > Integer.MAX_VALUE)
throw new IOException("File size is too big. Maximum is " + Integer.MAX_VALUE);
try {
Connection conn = dataLayer.getConnection(stash.dataSourceName, false);
try {
PGConnection pgConn = (PGConnection)DBUnwrap.getRealConnection(conn);
LargeObjectManager lom = pgConn.getLargeObjectAPI();
LargeObject lo = lom.open(stash.loid, LargeObjectManager.WRITE);
## After
protected void writeFileContent(DbStashImpl stash, byte[] bytes, int byteOffset, int length, long contentOffset) throws IOException {
if(contentOffset > Integer.MAX_VALUE)
throw new IOException("File size is too big. Maximum is " + Integer.MAX_VALUE);
try {
Connection conn = dataLayer.getConnection(stash.dataSourceName, false);
try {
PGConnection pgConn = (PGConnection)DBUnwrap.getRealConnection(conn);
PGConnection pgConn = null;
Connection realConn = DBUnwrap.getRealConnection(conn);
if(realConn instanceof PGConnection) {
pgConn = (PGConnection)realConn;
} else {
pgConn = realConn.unwrap(PGConnection.class);
}
LargeObjectManager lom = pgConn.getLargeObjectAPI();
LargeObject lo = lom.open(stash.loid, LargeObjectManager.WRITE);
Additional Documentation
- Stackoverflow documentation on casting vs. unwrapping
- Oracle documentation on casting vs unwrapping
- Postgres Unwrapping examples