Strange behaviour running in WIldfly 10 with EmulatedXAResource


ebenzacar@...
 

I'm encountering a strange behaviour for which I have not been able to pinpoint the cause and was hoping that someone could help point me in the right direction.

I have an application running under  JBoss EAP 7.0 (Wildfly 10), but only having the datasource specified at the container level.  I am trying to fully manage the JDOPersistenceFactory from within the JEE (EJB) application.

My persistence.xml is configured as follows (located in my EJB jar in the META-INF/ folder:
<persistence-unit name="cache" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:jboss/datasources/DS</non-jta-data-source>
<mapping-file>package.jdo</mapping-file>
<exclude-unlisted-classes/>
<properties>
<property name="datanucleus.connection.resourceType" value="RESOURCE_LOCAL"/>
<property name="datanucleus.transaction.type" value="RESOURCE_LOCAL"/>
<property name="datanucleus.storeManagerType" value="rdbms"/>
<property name="datanucleus.schema.autoCreateAll" value="false"/>
<property name="datanucleus.ConnectionFactoryName" value="java:jboss/datasources/DS"/>

<property name="datanucleus.connectionPoolingType" value="dbcp2-builtin"/>
</properties>
</persistence-unit>

I have instantiated my connection factory statically as follows:
public class DataNucleusPersistenceManagerFactory {

// hack to provide access to the pmfs from a static context
private static Map<PersistenceUnit, PersistenceManagerFactory> pmf = new ConcurrentHashMap<>();

static{
PersistenceManagerFactory persistenceManagerFactory = JDOHelper.getPersistenceManagerFactory("cache");
pmf.put(PersistenceUnit.CACHE, persistenceManagerFactory);
}

/**
* Retrieve PersistenceManagerFactory from legacy code
* @param type
* @return
*/
public static PersistenceManagerFactory getPersistenceManagerFactory( PersistenceUnit type){
return pmf.get(type);
}


All my Stateless EJBs are defined as BeanManagedTransactions by extending a base class with the following interceptor defined:
@TransactionManagement(TransactionManagementType.BEAN)
public class BaseManagerBean implements BaseManager {

PersistenceManager pm;

@AroundInvoke
public Object log(InvocationContext inv) throws Exception {
pm =
DataNucleusPersistenceManagerFactory.getPersistenceManagerFactory( CACHE );
pm.begin();

Object ret = inv.proceed();
pm.commit();

}

}

This allows for the logic for my bean method to simply use the pm within its logic without needing to worry about transaction boundaries/etc.  I have simplified the interceptor for illustration purposes.

My issue that I am encountering is when I have nested EJBs (ie: one EJB which calls another).  In this context, I end up with nested transactions, since each EJB method call will create a new PM and manage its own transaction.

When this happens, the inner transaction completes successfully, but the outer one throws and exception that:

Caused by: java.sql.SQLException: IJ031019: You cannot commit during a managed transaction
        at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.jdbcCommit(BaseWrapperManagedConnection.java:1063)
        at org.jboss.jca.adapters.jdbc.WrappedConnection.commit(WrappedConnection.java:834)
        at org.datanucleus.store.rdbms.ConnectionFactoryImpl$EmulatedXAResource.commit(ConnectionFactoryImpl.java:734)
        at org.datanucleus.transaction.ResourcedTransaction.commit(ResourcedTransaction.java:348)
        at org.datanucleus.transaction.ResourcedTransactionManager.commit(ResourcedTransactionManager.java:64)
        at org.datanucleus.TransactionImpl.internalCommit(TransactionImpl.java:417)
        at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:288)
        at org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:99)
        ... 128 more
 


Stepping through the code, falling into the IronJacamar libraries, I see that the ConnectionWrappers are treating this as an XA transaction.  I also see that from the `org.datanucleus.store.rdbms.ConnectionFactoryImpl$EmulatedXAResource` resource which the DN CF creates.

This is where I get confused.  I'm not sure why this is happening, nor if this is "normal"/expected behaviour.  I have tried to reproduce this in a small test application by embedding 2 txs, with the same PU defined, but it works properly there.  I have not yet tried embedding two EJBs in a test application.

I can only suspect that I have an errant configuration somewhere which is causing this, but cannot identify what.  My Datasource is configured the same for my test application.  Just for reference:

<datasource jndi-name="java:jboss/datasources/DS" pool-name="DS" enabled="true">
<
connection-url>jdbc:sqlserver://${db.tx.host};databaseName=${adams.db.tx.name}</connection-url>
<
driver>sqlserver</driver>
<
pool>
<
min-pool-size>5</min-pool-size>
<
max-pool-size>2000</max-pool-size>
</
pool>
<
security>
<
user-name>${adams.db.tx.username}</user-name>
<
password>${adams.db.tx.password}</password>
</
security>
<
validation>
<
check-valid-connection-sql>select getdate()</check-valid-connection-sql>
</
validation>
</
datasource>
<drivers> <driver name="sqlserver" module="com.microsoft.sqlserver"> <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</xa-datasource-class> </driver> </drivers>


What am I missing, doing wrong?  Do I have a incorrect or missing configuration?  What is  DN / WF seeing this as an XA transaction?  Or is this expected behaviour when working with nested EJBs due to the inherent stateless / pooling behaviour of EJBs?  If the latter, am I forced to move to Container Managed Transactions such that no bean commits its own transaction?  If not, how would I know which transaction is the outer transaction?

Thanks for any insights.

Eric

Join main@datanucleus.groups.io to automatically receive all group messages.