Tuesday, May 1, 2012

JBPM and Clustering

I'll be precise: "Can JBPM be deployed in a Distributed environment?"
In other words, Can I deploy multiple instances of JBPM? (but I want only 1 JVM to control all the executions)

My answer is Yes, you can have that mode! Just need to disable the JobExecutor on the other instances (by altering the configuration file)


Otherwise, you'll see this exception on your consoles (If your JVM's fight for the JOB's):
15:51:55,379 [DispatcherThread] ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.pvm.internal.job.TimerImpl#385014]
 at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1769)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2412)
 at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2312)
 at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2612)
 at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:96)
 at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
 at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
 at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
 at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
 at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
 at org.jbpm.pvm.internal.tx.HibernateSessionResource.prepare(HibernateSessionResource.java:56)
 at org.jbpm.pvm.internal.tx.StandardTransaction.commit(StandardTransaction.java:107)
 at org.jbpm.pvm.internal.tx.StandardTransaction.complete(StandardTransaction.java:64)
 at org.jbpm.pvm.internal.tx.StandardTransactionInterceptor.execute(StandardTransactionInterceptor.java:57)
 at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.executeInNewEnvironment(EnvironmentInterceptor.java:53)
 at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:40)
 at org.jbpm.pvm.internal.svc.RetryInterceptor.execute(RetryInterceptor.java:56)
 at org.jbpm.pvm.internal.svc.SkipInterceptor.execute(SkipInterceptor.java:43)
 at org.jbpm.pvm.internal.jobexecutor.DispatcherThread.acquireJobs(DispatcherThread.java:126)
 at org.jbpm.pvm.internal.jobexecutor.DispatcherThread.run(DispatcherThread.java:67)

If you're too lazy to have specific configuration per JVM, and you don't care about those exceptions, you're good to go (because that exception does not impact the Execution of your process instance), however, you can hide it by using Log4J (I'll explain that in another post)

Friday, April 13, 2012

Delegate to Seam the management of my JBPM4 engine

The problem was really simple, it's just implement a Singleton without writing it :P

I have a simple class, but I just need it to be loaded when the app starts, because my class will load the JBPM4 engine (and that should be done only once - this process may take up to 4 seconds, which will make really slow the first request coming to my End-Point)
But let me write more code and less words
Just add to your class these tags
Define which method will be your Creation method (Initialization method), on my case the one which will load the Engine
Now the one which will Destroy your class (shutdown my JBPM4 engine) and release resources
and optionally, your Constructor

Simple, Isnt' it?
Now you can inject this Seam Component using Injection into another Seam Component, just like this