AnsweredAssumed Answered

Accessing Business-Data via JPA before and after Timer

Question asked by bardioc on Oct 10, 2011
Latest reply on Oct 10, 2011 by bardioc
Hello,

I've setup a very simple example of a process model that involves two Service-Tasks and a single Timer Catching Event. The model is as follows:

[attachment=0]TestCaseA02.png[/attachment]

Our customer's development rules require to separate the persistence database from the business database. Both are Oracle Databases (Version 11gR2), hosted on different machines.

I've setup the activity configuration as follows, because we are using WebSphere and are required to use JTA for transaction management. As there are two database-connections involved in our processes, we use XA Datasources configured via WebSphere for both datasources.


<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
   
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">   
    <property name="transactionManager"  ref="transactionManager" />
</bean>

The rest of the configuration is done by code as follows:


final ProcessEngineConfiguration pec = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
pec.setJobExecutorActivate(true);
pec.setDataSource(dataSource);
pec.setHistory(ProcessEngineConfiguration.HISTORY_FULL);
pec.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

The specified <dataSource> is injected into this EJB via


@Resource(name = "jdbc/persistence-db")
private DataSource dataSource;

Additionally, there exists a JPA configuration for the business database as 'persistence.xml'. It defines JTA as transaction type as well as a jta-data-source and the corresponding entity classes.

Within the process, the first of the two service tasks accesses the business database within a JavaDelegate by JNDI lookup to a EJB that itself contains an injected EntityManager, e.g.


service = InitialContext.doLookup("ejblocal:" + DatabaseAccessService.class.getName());
final EntityManager em = service.getEntityManager();
em.persist(businessObject);
em.flush();

When we try to do this after the timer fired, e.g. after a couple of seconds, we receive an exception, that no transaction manager can be found for the EJB:


<openjpa-2.1.1-SNAPSHOT-r422266:1141200 fatal user error> org.apache.openjpa.persistence.InvalidStateException: Es konnte kein automatischer Lookup der javax.transaction.TransactionManager-Implementierung des EJB-Containers durchgeführt werden.Vergewissern Sie sich, dass die Anwendung in einem mit EJB 1.1 kompatiblen EJB-Container ausgeführt wird, und setzen Sie anschließend die Eigenschaft org.apache.openjpa.ManagedRuntime auf den entsprechenden Wert, um den TransactionManager abzurufen.
   at org.apache.openjpa.ee.AutomaticManagedRuntime.getTransactionManager(AutomaticManagedRuntime.java:253)
   at org.apache.openjpa.kernel.AbstractBrokerFactory.syncWithManagedTransaction(AbstractBrokerFactory.java:717)
   at org.apache.openjpa.kernel.BrokerImpl.initialize(BrokerImpl.java:389)
   at com.ibm.ws.persistence.kernel.WsJpaBrokerImpl.initialize(WsJpaBrokerImpl.java:306)
   at org.apache.openjpa.kernel.BrokerImpl.initialize(BrokerImpl.java:323)


Caused by: javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component.  This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request.  Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application.  Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names. [Root exception is javax.naming.NameNotFoundException: Name "comp/TransactionSynchronizationRegistry" not found in context "java:".]
   at com.ibm.ws.naming.java.javaURLContextImpl.throwExceptionIfDefaultJavaNS(javaURLContextImpl.java:522)
   at com.ibm.ws.naming.java.javaURLContextImpl.throwConfigurationExceptionWithDefaultJavaNS(javaURLContextImpl.java:552)
   at com.ibm.ws.naming.java.javaURLContextImpl.lookupExt(javaURLContextImpl.java:481)

It is understandable, that there is no longer an EJB context available as the timer process ended the initial transaction. However, after the timer fired, I've read activity creates a new transaction to continue within the process.

How am I able to participate in this transacition, so my JPA call will utilize it and work as expected?
For me right now, the only possible option is to disable JTA for the business data and use LOCAL_RESOURCE instead together with creating the entity managers directly and by myself. However I'd like to know if there is a better approach for this using activity.

Thank you very much.

Heiko

Attachments

Outcomes