Search code examples
javaspringoracle-databaseeclipselinkquerydsl

Using EclipseLink DCN causes ClassCastException in OracleChangeNotificationListener.register


first off, I'm using EclipseLink 2.5.2, ojdbc6, spring-orm 4.1.1, QueryDSL 3.7.1 and Tomcat7/Websphere 8 on Java 1.6.

Problem When I'm trying to add the OracleChangeNotificationListener - my application crashes.

The problematic line is

OracleConnection connection = (OracleConnection) databaseSession.getServerPlatform()
                    .unwrapConnection(accessor.getConnection());

with

databaseSession.getServerPlatform()
                        .unwrapConnection(accessor.getConnection());

returning (on tomcat) a

ProxyConnection[PooledConnection[oracle.jdbc.driver.T4CConnection@1f4fedf]]

Btw this patch doesnt work for me https://bugs.eclipse.org/bugs/show_bug.cgi?id=449065

persistence.xml

<persistence-unit name="xxxxContext" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
      <jta-data-source>jdbc/xxxx</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
      <properties>
        <property name="eclipselink.weaving" value="static"/>
        <property name="eclipselink.cache.database-event-listener" value="DCN"/>
      </properties>
    </persistence-unit>

Tomcat

Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy32 cannot be cast to oracle.jdbc.driver.OracleConnection
    at org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener.register(OracleChangeNotificationListener.java:96)
    at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:847)
    at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:756)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:313)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:336)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:302)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:388)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:541)
    at com.sun.proxy.$Proxy13.createEntityManager(Unknown Source)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:283)
    at com.sun.proxy.$Proxy19.getDelegate(Unknown Source)
    at com.mysema.query.jpa.impl.JPAProvider.getTemplates(JPAProvider.java:66)
    at com.mysema.query.jpa.impl.JPAQuery.<init>(JPAQuery.java:44)

Websphere

Caused by: java.lang.ClassCastException: com.ibm.ws.rsadapter.jdbc.WSJdbcConnection incompatible with oracle.jdbc.driver.OracleConnection
    at org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener.register(OracleChangeNotificationListener.java:96)
    at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:847)
    at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:756)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:313)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:336)
    at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:302)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
    at java.lang.reflect.Method.invoke(Method.java:611)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:388)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:541)
    at com.sun.proxy.$Proxy214.createEntityManager(Unknown Source)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:283)
    at com.sun.proxy.$Proxy215.getDelegate(Unknown Source)
    at com.mysema.query.jpa.impl.JPAProvider.getTemplates(JPAProvider.java:66)
    at com.mysema.query.jpa.impl.JPAQuery.<init>(JPAQuery.java:44)

Solution

  • Unwrapping the connection seems to work.

            Connection unwrapConnection = databaseSession.getServerPlatform()
                    .unwrapConnection(accessor.getConnection());
            oracle.jdbc.OracleConnection connection = null;
            try {
                if (unwrapConnection.isWrapperFor(OracleConnection.class)) {
                    connection = unwrapConnection.unwrap(OracleConnection.class);
                } else {
                    // recover, not an oracle connection
                    connection = (oracle.jdbc.OracleConnection) databaseSession.getServerPlatform()
                            .unwrapConnection(accessor.getConnection());
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }