Datasource with JTA integration
christian.beikov Jun 4, 2015 5:16 PMHello!
I have two datasources, one for master only communication and another one for read only communication.
My use case is, that I want the read only datasource not to participate in a running transaction. Since I am using container managed transactions, I thought I could use @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) but apparently this didn't make any difference for the transaction system since it enlisted the read only datasource. When trying to enlist the master only datasource it fails with a cryptic error.
Caused by: org.hibernate.exception.GenericJDBCException: Could not open connection
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:235)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:171)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.connection(StatementPreparerImpl.java:63)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:162)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:186)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:160)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1885)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839)
at org.hibernate.loader.Loader.doQuery(Loader.java:910)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:325)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2149)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:78)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:68)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:503)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:468)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:213)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1106)
at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:176)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2587)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:996)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:306)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:186)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:876)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:858)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:863)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1196)
... 186 more
Caused by: java.sql.SQLException: javax.resource.ResourceException: IJ000457: Unchecked throwable in managedConnectionReconnected() cl=org.jboss.jca.core.connectionmanager.listener.TxConnectionListener@6e700878[state=NORMAL managed connection=org.jboss.jca.adapters.jdbc.local.LocalManagedConnection@1b815806 connection handles=0 lastReturned=1433450163370 lastValidated=1433450009358 lastCheckedOut=1433450017295 trackByTx=false pool=org.jboss.jca.core.connectionmanager.pool.strategy.OnePool@18e02a39 mcp=SemaphoreArrayListManagedConnectionPool@baa4336[pool=SweazerTestMasterOnly] xaResource=LocalXAResourceImpl@2a5935ff[connectionListener=6e700878 connectionManager=6913e920 warned=false currentXid=null productName=PostgreSQL productVersion=9.4.1 jndiName=java:jboss/datasources/SweazerTestMasterOnly] txSync=null]
at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:146)
at org.jboss.as.connector.subsystems.datasources.WildFlyDataSource.getConnection(WildFlyDataSource.java:67)
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:139)
at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:380)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228)
... 217 more
Caused by: javax.resource.ResourceException: IJ000457: Unchecked throwable in managedConnectionReconnected() cl=org.jboss.jca.core.connectionmanager.listener.TxConnectionListener@6e700878[state=NORMAL managed connection=org.jboss.jca.adapters.jdbc.local.LocalManagedConnection@1b815806 connection handles=0 lastReturned=1433450163370 lastValidated=1433450009358 lastCheckedOut=1433450017295 trackByTx=false pool=org.jboss.jca.core.connectionmanager.pool.strategy.OnePool@18e02a39 mcp=SemaphoreArrayListManagedConnectionPool@baa4336[pool=SweazerTestMasterOnly] xaResource=LocalXAResourceImpl@2a5935ff[connectionListener=6e700878 connectionManager=6913e920 warned=false currentXid=null productName=PostgreSQL productVersion=9.4.1 jndiName=java:jboss/datasources/SweazerTestMasterOnly] txSync=null]
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.reconnectManagedConnection(AbstractConnectionManager.java:927)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:740)
at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:138)
... 221 more
Caused by: javax.resource.ResourceException: IJ000461: Could not enlist in transaction on entering meta-aware object
at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.managedConnectionReconnected(TxConnectionManagerImpl.java:561)
at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.reconnectManagedConnection(AbstractConnectionManager.java:922)
... 223 more
Caused by: javax.transaction.SystemException: IJ000356: Failed to enlist: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 0:ffff0a000063:40f3ed17:5570b5a0:45 status: ActionStatus.ABORT_ONLY >
at org.jboss.jca.core.connectionmanager.listener.TxConnectionListener$TransactionSynchronization.checkEnlisted(TxConnectionListener.java:883)
at org.jboss.jca.core.connectionmanager.listener.TxConnectionListener.enlist(TxConnectionListener.java:390)
at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.managedConnectionReconnected(TxConnectionManagerImpl.java:554)
... 224 more
After I enabled prepared transactions on my PostgreSQL it suddenly worked so I guess that it tried to start a 2PC.
When setting the attribute "jta" to false on the read only datasource, it does not seem to do a 2PC anymore.
Here some example code:
@Stateless class Ejb1 { @Inject Ejb2 b2; @PersistenceContext(unitName="masterOnly") EntityManager em; public void business1() { List list = b2.getList(); Object someEntity = list.get(0); // Do something with someEntity em.merge(someEntity); } } @Stateless @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) class Ejb2 { @PersistenceContext(unitName="readOnly") EntityManager em; public List getList() { return em.createQuery("...").getResultList(); } }
Could you tell me what the expected behavior is, or what I might have misconfigured?
As far as I understand, the jta attribute enables JTA integration which should somehow also propagate the TransactionAttributeType and finally prevent the read only datasource from being enlisted to the transaction.
I guess setting the jta attribute to false is good enough for me for now, but I am wondering what the implications are and if that is a bug.
I am using IronJacamar 1.2.4.Final in Wildfly 9.0.0.CR1.