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