[ https://issues.apache.org/jira/browse/OPENJPA-2904?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Pawel Veselov updated OPENJPA-2904: ----------------------------------- Description: We have some custom code that we use to get the underlying connection object from OpenJPA. At first we were doing this: {code:java} public Connection getRawConnection(EntityManager em) { OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); return (Connection) oem.getConnection(); } {code} But sometimes we need the connection object before the entity manager has been otherwise used in any way. And the transaction of this connection should match the one created by JPA. So we changed this to: {code:java} public Connection getRawConnection(EntityManager em) { OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); oem.beginStore(); return (Connection) oem.getConnection(); } {code} This sometimes fails with an NPE if the connection object hasn't been initialized yet. So we changed this to: But sometimes we need the connection object before the entity manager has been otherwise used in any way. And the transaction of this connection should match the one created by JPA. So we changed this to: {code:java} public Connection getRawConnection(EntityManager em) { OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); oem.getConnection(); oem.beginStore(); return (Connection) oem.getConnection(); } {code} This, however, has an interesting side-effect. The returned {{JDBCStoreManager.ClientConnection}} class seems to be quickly GCed, which makes it close the underlying connection. In essence, calling {{oem.getConnection}} is bad unless the connection is retained, it really messes things up (see comment for the stack traces) We've now again changed this to: {code:java} public Connection getRawConnection(EntityManager em) { OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); Connection c = (Connection)oem.getConnection(); oem.beginStore(); return c; } {code} This should work now, but the possibility that {{getConnection()}} actually results in a connection closure is probably bad. was: (looking at commit 05069dfee, but this code hasn't changed in ages). There is a number of methods that chain to {{JDBCStore.getClientConnection()}} * {{StoreManager.getClientConnection()}} * {{StoreContext.getConnection()}} * {{OpenJPAEntityManager.getConnection()}} * {{EntityManagerImpl.unwrap()}} Callers of these methods typically use the retrieved connection object for an operation, and then let go of it, without any cleanup (as they are supposed to). However, {{JDBCStore.getClientConnection()}} implementation creates an instance of {{JDBCStoreManager.ClientConnection}} class every time it's called. These instances, considering how they are used, are therefore short-lived However, the implementation {{JDBCStoreManager.ClientConnection}} closes the underlying connection object on finalization. This has a relatively high chance of having the underlying connection closed before it's actually properly released. I don't necessarily know what the right fix for this is, but locally I will just make ClientConnection a field of RefCountConnection, it's a lightweight class so I can create it right away, then I'll have {{JDBCStore.getClientConnection()}} just return that. There may be some gotchas there, but I just need a quick solution because this suddenly became a persistent problem. I've overridden the pooled connection implementation to try to trace the connection random connection closure that we are experiencing under some random scenarios, and I attached an exception to the connection object when it's closed, and I see when an attempt to use a closed connection happens - it's because the GC closed it through {{JDBCStoreManager.ClientConnection}}. > OpenJPAEntityManager.getConnection() may lead to sudden connection closure > -------------------------------------------------------------------------- > > Key: OPENJPA-2904 > URL: https://issues.apache.org/jira/browse/OPENJPA-2904 > Project: OpenJPA > Issue Type: Bug > Affects Versions: 3.2.0, 3.2.1, 3.2.2 > Reporter: Pawel Veselov > Priority: Minor > > We have some custom code that we use to get the underlying connection object > from OpenJPA. > At first we were doing this: > {code:java} > public Connection getRawConnection(EntityManager em) { > OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); > return (Connection) oem.getConnection(); > } > {code} > But sometimes we need the connection object before the entity manager has > been otherwise used in any way. And the transaction of this connection should > match the one created by JPA. So we changed this to: > {code:java} > public Connection getRawConnection(EntityManager em) { > OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); > oem.beginStore(); > return (Connection) oem.getConnection(); > } > {code} > This sometimes fails with an NPE if the connection object hasn't been > initialized yet. So we changed this to: > But sometimes we need the connection object before the entity manager has > been otherwise used in any way. And the transaction of this connection should > match the one created by JPA. So we changed this to: > {code:java} > public Connection getRawConnection(EntityManager em) { > OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); > oem.getConnection(); > oem.beginStore(); > return (Connection) oem.getConnection(); > } > {code} > This, however, has an interesting side-effect. The returned > {{JDBCStoreManager.ClientConnection}} class seems to be quickly GCed, which > makes it close the underlying connection. In essence, calling > {{oem.getConnection}} is bad unless the connection is retained, it really > messes things up (see comment for the stack traces) > We've now again changed this to: > {code:java} > public Connection getRawConnection(EntityManager em) { > OpenJPAEntityManager oem = OpenJPAPersistence.cast(em); > Connection c = (Connection)oem.getConnection(); > oem.beginStore(); > return c; > } > {code} > This should work now, but the possibility that {{getConnection()}} actually > results in a connection closure is probably bad. -- This message was sent by Atlassian Jira (v8.20.10#820010)