-
1. Re: Why is Timer event not triggered in J2EE container?
garytse Aug 5, 2011 12:07 AM (in response to garytse)It seems this is the problem. The timer kick start correctly but somehow failed to start/ commit the transaction.
If anyone has any ideas, anything I can try will be much appreciated.
[WARN][JtaTransactionManager] Unable to begin transaction
java.lang.NullPointerException
at com.ibm.ejs.container.EJSContainer.processTxContextChange(EJSContainer.java:2117)
at com.ibm.ejs.container.UserTransactionWrapper.begin(UserTransactionWrapper.java:181)
at org.drools.persistence.jta.JtaTransactionManager.begin(JtaTransactionManager.java:153)
at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:281)
at org.drools.persistence.jpa.JpaJDKTimerService$JpaJDKCallableJob.call(JpaJDKTimerService.java:75)
at org.drools.persistence.jpa.JpaJDKTimerService$JpaJDKCallableJob.call(JpaJDKTimerService.java:63)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:284)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:80)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:183)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:665)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:690)
at java.lang.Thread.run(Thread.java:810)
[ERROR][SingleSessionCommandService] Could not commit session
java.lang.RuntimeException: Unable to begin transaction
at org.drools.persistence.jta.JtaTransactionManager.begin(JtaTransactionManager.java:156)
at org.drools.persistence.SingleSessionCommandService.execute(SingleSessionCommandService.java:281)
at org.drools.persistence.jpa.JpaJDKTimerService$JpaJDKCallableJob.call(JpaJDKTimerService.java:75)
at org.drools.persistence.jpa.JpaJDKTimerService$JpaJDKCallableJob.call(JpaJDKTimerService.java:63)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:284)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:80)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:183)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:665)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:690)
at java.lang.Thread.run(Thread.java:810)
Caused by: java.lang.NullPointerException
at com.ibm.ejs.container.EJSContainer.processTxContextChange(EJSContainer.java:2117)
at com.ibm.ejs.container.UserTransactionWrapper.begin(UserTransactionWrapper.java:181)
at org.drools.persistence.jta.JtaTransactionManager.begin(JtaTransactionManager.java:153)
... 10 more
-
2. Re: Why is Timer event not triggered in J2EE container?
mgeldenhuys Aug 5, 2011 8:03 AM (in response to garytse)HI Gary,
Are you using User managed Transactions in your bean? If so, you need to register the transaction manger in the environment. You can look at this :
http://docs.jboss.org/jbpm/v5.1/userguide/ch07.html#d0e2820
Mare
-
3. Re: Why is Timer event not triggered in J2EE container?
garytse Aug 5, 2011 9:15 AM (in response to mgeldenhuys)Yes, sorry I've stripped too much from my code. It's updated.
The exception comes after 3 minutes when the timer kicks in.
This line suggests that the timer is triggered:
at org.drools.persistence.jpa.JpaJDKTimerService$JpaJDKCallableJob.call(JpaJDKTimerService.java:75)
However, I suspect that Websphere's cannot find the transaction/ context for it? Is there anything to do with the EJB starting its own threads (by Drools) ?
com.ibm.ejs.container.EJSContainer.processTxContextChange
Thanks for the suggestion Mare.
-
4. Re: Why is Timer event not triggered in J2EE container?
mgeldenhuys Aug 8, 2011 5:13 AM (in response to garytse)Hi Gary,
I think that your suspicion is correct. The original transaction you use to create the process finishes successfully, since it is only mandated to create the process and that happens without a problem. Therefore the original transaction has already commited and is not available when the timer fires.
Since the timer is executing now in the engine (StatefullKnowledgeSession) and transaction management has been specified as BMT. the engine now requires a transaction manager to get a transaction from it. And this is probably where the problem arises.
The way you do that is by registering the Transaction Manager with the StatefullKnowledgeSession, and that is done upon creation/retrieval of the said StatefullKnowledgeSession. That means getting the Transaction Manager which is managed by Websphere in your case and passing it to the KnowledgeService through an Environment.
The question now really is, how are you creating your StatefullKnowledgeSession? If you are using the jbpm-gwt-core jar's sources CommandDelegate as an example, you will have to look at the following lines,
Environment env = KnowledgeBaseFactory.newEnvironment(); env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
This is where you will need to add the reference to your transaction manager,
env.set( EnvironmentName.TRANSACTION_MANAGER, TransactionManagerServices.getTransactionManager() ); // Change second parameter to where you get your transaction manager from
If this does not work, someone from the community with more experience will need to assist. Whichever way, please post your findings, as I would like to see how it pans out.
Mare
-
5. Re: Why is Timer event not triggered in J2EE container?
garytse Aug 9, 2011 6:01 AM (in response to mgeldenhuys)Thanks for the suggestion, Mare.
The transaction manager is where I'm having problem with, and that's why I am unable to get a TransactionManager for the 2nd parameter.
According to this: http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html
"...WebSphere Application Server does not expose the javax.transaction.TransactionManager interface to applications or application frameworks deployed into WebSphere Application Server..."
As far as I know, both Hibernate and Spring have something of their own to work around this problem, something like :
- org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
- org.springframework.transaction.jta.WebSphereUowTransactionManager
While I do not know the how Spring and Hibernate work around on TransactionManager, I found a work-around to this problem; and it goes in 2 parts :--
1. WebSphere does not like threads being created in EJB, and it's against J2EE practise
The first part of the solution is to fix the threads created directly using J2SE. The class doing that is : org.drools.time.impl.JDKTimerService. Using the example and classes from: http://www.ibm.com/developerworks/websphere/techjournal/0606_johnson/0606_johnson.html I was then able to create the thread pool using the WebSphere's WorkerManager. Now, the threads under this are under J2EE context.
org.drools.time.impl.JDKTimerService:
public JDKTimerService(int size) { ... InitialContext ctx = new InitialContext(); WorkManager wm = (WorkManager)ctx.lookup("wm/default"); WASThreadFactory wasThreadFactory = new WASThreadFactory(wm); this.scheduler = new ScheduledThreadPoolExecutor( size, wasThreadFactory );
WASThreadFactory coming from the example classes in IBM developer works.
2. Re-initialize the "UserTransaction"
When the timer service kicks in, it tries to call the single command service class (forgot actual class at the moment). I perform a JNDI UserTransaction lookup to make it so that the drools transaction manager is new.
Gary