jBPM persistency problem
lvdberg Sep 12, 2009 7:47 PMHi guys,
I am trying to solve a problem I have with jBPM in Seam. I want to have a reporting-task supervised
every day, meaning if the actor doesn't fill in his/her report within an hour, he should receive a warning every 24 hours. After trying to get the whole stuff working I found out that the timer has some problems when you use a repeat value. However if you use a repeat value of tru or yes everything seems to work. But now the tricky part. I am trying to save objects the taskinstance instance and that won't work without a nasty error which in fact doesn't seem to be a faulure.
I stripped everything down to some simple beans to see what happen:
My processdefinition:
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jbpm.org:jpdl-3.2 http://jbpm.org/xsd/jpdl-3.2.xsd" name="test"> <event type="process-start"> <script> System.out.println("@@@@@@ PROCESS START"); </script> </event> <event type="process-end"> <script> System.out.println("@@@@@@ PROCESS END"); </script> </event> <start-state name="start-state"> <transition to="login-checker" /> </start-state> <task-node name="login-checker"> <event type="node-enter"> <script> System.out.println("STATE " + node + " entered."); </script> </event> <event type="node-leave"> <script> System.out.println("STATE " + node + " left."); </script> </event> <task name="check-this" > <assignment actor-id="#{actor.id}"/> <timer duedate="10 seconds" name="wait-for-timeout" repeat="yes"> <action expression="#{bpmRequestTimeOut.check()}" /> </timer> </task> <transition to="end-state" /> </task-node> <end-state name="end-state" /> </process-definition>
The timer action bean:
@Name("bpmRequestTimeOut") public class BpmRequestTimeOutAction implements Serializable { @In(required=false) TaskInstance taskInstance; @In Events events; @Logger Log log; @Transactional public void check(){ if (taskInstance != null){ log.info("Finally the timer works: Timed out processInstance " + taskInstance.getName()); events.raiseEvent("timedOutCheck", taskInstance.getId()); } } }
The observer bean:
@Name("timeOutListener") public class TimeOutListener { @In(required=false) TaskInstance taskInstance; @Logger Log log; //@In(required=false, scope=ScopeType.BUSINESS_PROCESS) //@Out(required=false, scope=ScopeType.BUSINESS_PROCESS) Long counter = -1L; @In Actor actor; @Observer(create=true, value="timedOutCheck") @Transactional public void listen(Long tid){ if (taskInstance != null){ Long counter = (Long) taskInstance.getContextInstance().getVariable("counter"); if (counter == null) counter = 0L; log.info("TimeOut received. taskInstance " + taskInstance.getName()); counter++; taskInstance.getContextInstance().setVariable("counter", counter); if (counter > 10) { log.info("Timer expired over 10 times, special log will be made and failure will be registered."); taskInstance .getContextInstance().createVariable("refusedInteractionActor", taskInstance.getActorId()); taskInstance.end(); } } else log.info("TimeOut received. taskInstance == null."); } }
I tried every configuratuion and this solutions gives the least problems, just one single (but nasty) error:
2009-09-11 23:58:58,193 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] (JbpmJobExecutor:192.168.1.101:1) 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.job.Timer#4] at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435) at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635) at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115) 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:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027) at org.jbpm.persistence.db.DbPersistenceService.flushSession(DbPersistenceService.java:278) at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:236) at org.jbpm.svc.Services.close(Services.java:236) at org.jbpm.JbpmContext.close(JbpmContext.java:136) at org.jbpm.job.executor.JobExecutorThread.executeJob(JobExecutorThread.java:190) at org.jbpm.job.executor.JobExecutorThread.run(JobExecutorThread.java:60)
As you can see in the observer bean I also tried to use @In/Out with the counter attribute but it gives the same problem.
The funny thing is that the value get's saved and retrieved without a problem. It has to do with saving the object, because at the moment I directly do a te
taskInstance.end() there are no errors.
It works but I really don't like these kind of errors, because you never know...
I am using jboss 5.1 with 2.1.1 and the whole application is using a single (MySQL) database (domainmodel and jbpm-tables).
Any hints/tips would be very much appreciated!
Leo