[jboss-user] [JBoss jBPM] - Actions and async=

jeffj55374 do-not-reply at jboss.com
Thu Aug 9 14:25:17 EDT 2007


org.jbpm.JbpmException: token '18547' can't be locked by 'job[18548]' cause it's already locked by 'token[18547]'
Full stack trace, process definition, action handler are all below. 

Environment
jBPM 3.2.1
  | Standalone Java 1.6 (no appserver)
  | Actions and async="true" don't mix.
  | JobExecutor is configured for one thread.
  | Hibernate 3.2.4.sp1
  | Oracle 10g
  | 
  | 
  | Summary:
  | 1. Token is signaled to start the process. 
  | 2. Token transitions to node1 from the start node. 
  | 3. Node one has an action handler defined so Node.execute(...) calls GraphElement.executeAction() which locks the token.
  | 4. The action handler calls ctx.leaveNode after it does its work.  (Section 9.5 of the user guide states: "Note the difference 
  |    between an action that is placed in an event versus an action that is placed in a node. Actions that are put in an event
  |    are executed when the event fires. Actions on events have no way to influence the flow of control of the process. 
  |    It is similar to the observer pattern. On the other hand, an action that is put on a node has the responsibility of propagating the execution. 
  | 5. ctx.leaveNode on Node1 ultimately results in Node.enter() being called on Node2
  | 6. Since Node2 is an async node, rather than executing the node, the code prepares for an async continuation. 
  | 7. After sending the message the code attempts to lock the token, but it already locked as a result of #3
  |     // execute the node
  |     if (isAsync) {
  |       ExecuteNodeJob job = createAsyncContinuationJob(token);
  |       MessageService messageService = (MessageService) Services.getCurrentService(Services.SERVICENAME_MESSAGE);
  |       messageService.send(job);
  |       token.lock(job.toString());  // ** THIS IS THE PROBLEM LINE!!!! ***
  |     } else {
  |       execute(executionContext);
  |     }
  | 
  | The conflict:  
  | Javadoc for Token.lock():
  | /**
  |    * locks a process instance for further execution.  A locked token 
  |    * cannot continue execution.  This is a non-persistent
  |    * operation.  This is used to prevent tokens being propagated during 
  |    * the execution of actions.
  |    * @see #unlock(String) 
  |    */
  |   public void lock(String lockOwnerId) {
  | 
  | But Section 9.5 of the user's guide says that an action is responsible for propagating the execution, but the token is locked in an attempt to propagate it.
  | 
  | I'm currently trying to understand the design and come up with a solution to allow my process to run as designed.
  | What I don't understand yet is why the token is used to prevent propagation or why the code in Node.execute is trying to lock the token with the job id.  
  | Should the code unlock the token and then lock it with the job? Is the token lock really necessary? 
  | If I remove the action fron Node 1, things work fine.
  | 
  | Possibly related to http://jira.jboss.com/jira/browse/JBPM-983. Similar, but a little different twist
  | 
  | Any ideas?
  | 
  | Once I research this a little more, I might submit a bug, but I'd like a little feedback to verify that I'm on the right track.
  | 
  | Thanks for your help.
  | 
  | Full stack trace:
  | 
  | org.jbpm.JbpmException: token '18547' can't be locked by 'job[18548]' cause it's already locked by 'token[18547]'
  | 	at org.jbpm.graph.exe.Token.lock(Token.java:646)
  | 	at org.jbpm.graph.def.Node.enter(Node.java:316)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  | 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  | 	at java.lang.reflect.Method.invoke(Unknown Source)
  | 	at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
  | 	at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$dc89a302.enter()
  | 	at org.jbpm.graph.def.Transition.take(Transition.java:151)
  | 	at org.jbpm.graph.def.Node.leave(Node.java:393)
  | 	at org.jbpm.graph.def.Node.leave(Node.java:357)
  | 	at org.jbpm.graph.exe.ExecutionContext.leaveNode(ExecutionContext.java:120)
  | 	at com.digitalriver.mds.jbpm.SampleActionHandler.execute(SampleActionHandler.java:46)
  | 	at org.jbpm.graph.def.Action.execute(Action.java:122)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  | 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  | 	at java.lang.reflect.Method.invoke(Unknown Source)
  | 	at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
  | 	at org.jbpm.graph.def.Action$$EnhancerByCGLIB$$5863de36.execute()
  | 	at org.jbpm.graph.def.GraphElement.executeAction(GraphElement.java:255)
  | 	at org.jbpm.graph.def.Node.execute(Node.java:338)
  | 	at org.jbpm.graph.def.Node.enter(Node.java:318)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  | 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  | 	at java.lang.reflect.Method.invoke(Unknown Source)
  | 	at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
  | 	at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$dc89a302.enter()
  | 	at org.jbpm.graph.def.Transition.take(Transition.java:151)
  | 	at org.jbpm.graph.def.Node.leave(Node.java:393)
  | 	at org.jbpm.graph.node.StartState.leave(StartState.java:70)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  | 	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  | 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  | 	at java.lang.reflect.Method.invoke(Unknown Source)
  | 	at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
  | 	at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$dc89a302.leave()
  | 	at org.jbpm.graph.exe.Token.signal(Token.java:194)
  | 	at org.jbpm.graph.exe.Token.signal(Token.java:139)
  | 	at com.digitalriver.proto.StandaloneSample.runStandaloneSample(StandaloneSample.java:89)
  | 	at com.digitalriver.proto.StandaloneSample.run(StandaloneSample.java:130)
  | 	at com.digitalriver.proto.StandaloneSample.main(StandaloneSample.java:40)
  | 
  | 
  | 
  | 
  | The Job Executor bean config
  | 
  |  <bean id="jbpm.job.executor" class="org.jbpm.job.executor.JbpmJobExecutor">
  |   |     <property name="jbpmConfiguration" ref="jbpmConfiguration" />
  |   |     <property name="name" value="JbpmJobExector"/> 
  |   |     <property name="nbrOfThreads" value="1"/>
  |   |     <property name="idleInterval" value="5000"/>
  |   |     <property name="maxIdleInterval" value="300000"/>
  |   |     <property name="historyMaxSize" value="20"/>
  |   |     <property name="maxLockTime" value="600000"/>          <!-- 10 minutes -->
  |   |     <property name="lockMonitorInterval" value="60000"/>  <!-- 1 minute -->
  |   |     <property name="lockBufferTime" value="5000"/>        <!-- 5 seconds -->
  |   |   </bean> 
  | 
  | 
  | The Process Definition
  | 
  | <?xml version="1.0" encoding="UTF-8"?>
  |   | 
  |   | <process-definition
  |   |   xmlns=""  name="StandaloneSample">
  |   |    <start-state name="start">
  |   |       <transition name="" to="node1"></transition>
  |   |    </start-state>
  |   |    <end-state name="end1"></end-state>
  |   |    <node  name="node1">
  |   |      <action class="com.digitalriver.mds.jbpm.SampleActionHandler"></action>
  |   |      <transition name="" to="node2"></transition>
  |   |    </node>
  |   |    <node async="true" name="node2">
  |   |       <action class="com.digitalriver.mds.jbpm.SampleActionHandler"></action>
  |   |       <transition name="" to="end1"></transition>
  |   |     </node>
  |   | </process-definition>
  | 
  | The action handler
  | package com.digitalriver.mds.jbpm;
  |   | 
  |   | /** Copyright (c) Digital River, Inc. All rights reserved. 2007
  |   |  * Filename:	SampleActionHandler.java
  |   |  * Author:		@author
  |   |  */
  |   | 
  |   | 
  |   | import java.io.FileWriter;
  |   | 
  |   | import org.apache.commons.logging.Log;
  |   | import org.apache.commons.logging.LogFactory;
  |   | import org.jbpm.context.exe.ContextInstance;
  |   | import org.jbpm.graph.def.ActionHandler;
  |   | import org.jbpm.graph.exe.ExecutionContext;
  |   | 
  |   | /**
  |   |  * @author jpjohnson
  |   |  *
  |   |  */
  |   | public class SampleActionHandler
  |   |     implements ActionHandler {
  |   | 
  |   |   /**
  |   |    * 
  |   |    */
  |   |   private static final long serialVersionUID = 1L;
  |   |   @SuppressWarnings("unused")
  |   |   private static final Log log = LogFactory.getLog(SampleActionHandler.class);
  |   | 
  |   |   /* (non-Javadoc)
  |   |    * @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext)
  |   |    */
  |   |    public void execute(final ExecutionContext ctx) throws Exception
  |   |   {
  |   |     log.debug("JPJ execute called for task " + ctx.getNode().getName() + 
  |   |               " action " + ctx.getAction().getName());
  |   |     
  |   |     ContextInstance contextInstance = ctx.getProcessInstance().getContextInstance();
  |   |     Integer id = (Integer) contextInstance.getVariable("MyID");
  |   |     
  |   |     FileWriter file = new FileWriter("Node-" + ctx.getNode().getName() + " PI-" +
  |   |                                     ctx.getProcessInstance().getId() + ".txt");
  |   |     file.write("Test output: Process ID " + id);
  |   |     file.close();
  |   |     
  |   |     ctx.leaveNode();
  |   |     // ctx.getToken().signal();
  |   |   }
  |   | 
  |   | }
  |   | 
  | 
  | 

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4072679#4072679

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4072679



More information about the jboss-user mailing list