3 Replies Latest reply on Jul 27, 2005 12:36 PM by kiran222

    java.lang.IllegalStateException: couldn't signal token 'Toke

      I am using jbpm-starters-kit-3.0 on a Linux box with JDK 1.5.

      I am having trouble moving from one state to another from within an Action Handler class.
      It works OK if I call processInstance.signal() repeatedly from the Test Case. But, If I call the token.signal() in the Action Handler I get this stack trace:

      13:56:13,884 DEBUG GraphElement : event 'process-start' on 'ProcessDefinition(work order process)' for 'Token(/)'
      13:56:13,885 DEBUG GraphElement : event 'before-signal' on 'StartState(start)' for 'Token(/)'
      13:56:13,886 DEBUG GraphElement : event 'node-leave' on 'StartState(start)' for 'Token(/)'
      13:56:13,887 DEBUG GraphElement : event 'transition' on 'Transition(1e87719)' for 'Token(/)'
      13:56:13,889 DEBUG GraphElement : executing action 'CreateWOAction'
      Action: Create the work order based on PR received
      13:56:13,901 ERROR GraphElement : action threw exception: couldn't signal token 'Token(/)' : couldn't leave node 'null' over its default transition
      java.lang.IllegalStateException: couldn't signal token 'Token(/)' : couldn't leave node 'null' over its default transition

      at org.jbpm.graph.exe.Token.signal(Token.java:90)
      at com.n2bb.upsell.jbpm.action.CreateWOAction.execute(CreateWOAction.java:21)
      at org.jbpm.graph.def.Action.execute(Action.java:79)
      at org.jbpm.graph.def.GraphElement.executeActions(GraphElement.java:186)
      at org.jbpm.graph.def.GraphElement.fireAndPropagateEvent(GraphElement.java:149)
      at org.jbpm.graph.def.GraphElement.fireEvent(GraphElement.java:133)
      at org.jbpm.graph.def.Transition.take(Transition.java:79)
      at org.jbpm.graph.def.Node.leave(Node.java:349)
      at org.jbpm.graph.node.StartState.leave(StartState.java:73)
      at org.jbpm.graph.exe.Token.signal(Token.java:127)
      at org.jbpm.graph.exe.Token.signal(Token.java:92)
      at org.jbpm.graph.exe.ProcessInstance.signal(ProcessInstance.java:201)
      at com.n2bb.upsell.jbpm.UpsellProcessTest.testWorkOrderProcess(UpsellProcessTest.java:29)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at junit.framework.TestCase.runTest(TestCase.java:154)
      at junit.framework.TestCase.runBare(TestCase.java:127)
      at junit.framework.TestResult$1.protect(TestResult.java:106)
      at junit.framework.TestResult.runProtected(TestResult.java:124)
      at junit.framework.TestResult.run(TestResult.java:109)
      at junit.framework.TestCase.run(TestCase.java:118)
      at junit.framework.TestSuite.runTest(TestSuite.java:208)
      at junit.framework.TestSuite.run(TestSuite.java:203)
      at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:289)
      at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeInVM(JUnitTask.java:1061)
      at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:676)
      at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeOrQueue(JUnitTask.java:1413)
      at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:633)
      at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
      at org.apache.tools.ant.Task.perform(Task.java:364)
      at org.apache.tools.ant.Target.execute(Target.java:341)
      at org.apache.tools.ant.Target.performTasks(Target.java:369)
      at org.apache.tools.ant.Project.executeTarget(Project.java:1214)
      at org.apache.tools.ant.Project.executeTargets(Project.java:1062)
      at org.apache.tools.ant.Main.runBuild(Main.java:673)
      at org.apache.tools.ant.Main.startAnt(Main.java:188)
      at org.apache.tools.ant.launch.Launcher.run(Launcher.java:196)
      at org.apache.tools.ant.launch.Launcher.main(Launcher.java:55)

      ---------------------------------------------------------------------------------------------------------
      Here is my processdefinition.xml:

      <process-definition name="work order process">
      
       <!-- START-STATE -->
       <start-state name="start">
       <transition to="Send to ES">
       <action class="com.n2bb.upsell.jbpm.action.CreateWOAction"/>
       </transition>
       </start-state>
      
       <!-- NODES -->
       <state name="Send to ES">
       <transition to="Send to AS">
       <action class="com.n2bb.upsell.jbpm.action.SendWOToESAction"/>
       </transition>
       </state>
      
       <state name="Send to AS">
       <transition to="Send for Audit">
       <action class="com.n2bb.upsell.jbpm.action.SendWOToAWDAction"/>
       </transition>
       </state>
      
       <state name="Send for Audit">
       <transition to="end">
       <action class="com.n2bb.upsell.jbpm.action.AuditWOAction"/>
       </transition>
       </state>
      
       <!-- END-STATE -->
       <end-state name="end" />
      
      </process-definition>
      

      ---------------------------------------------------------------------------------------------------------
      Here is the Test case:

      public class ProcessTest extends TestCase
      {
       public void testWorkOrderProcess()
       {
       try
       {
       FileInputStream fis = new FileInputStream("workorderprocess.par");
       ZipInputStream zis = new ZipInputStream(fis);
       ProcessDefinition processDefinition =
       ProcessDefinition.parseParZipInputStream(zis);
       ProcessInstance processInstance = new ProcessInstance(processDefinition);
      
       Token token = processInstance.getRootToken();
       assertSame(processDefinition.getStartState(), token.getNode());
       assertSame(processDefinition.getNode("start"), token.getNode());
      
       processInstance.signal();
       assertSame(processDefinition.getNode(
       "Send to ES"), token.getNode());
       }
       catch(Exception ex)
       {
       ex.printStackTrace();
       }
      
       }
      }

      ---------------------------------------------------------------------------------------------------------
      public class CreateWOAction
      extends JbpmAction
      {
       public void execute(ExecutionContext ec)
       {
       log("Create the work order based on PR received");
       ec.getToken().signal();
       }
      }
      


        • 1. Re: java.lang.IllegalStateException: couldn't signal token '
          brittm

          I'm going to take a stab at this, and I might get it wrong--but I'm not sure why you're trying to signal with CreateWOAction when you're already in a transition.

          You only need to signal when your process execution is stopped. In your case, you're signalling your process to take a transition in ProcessTest.processInstance.signal()--at this point, your process execution is in motion and won't stop again until it enters the state "send to ES". However, in the midst of the transition out of the start-state, you are signaling again. I don't know if you should see that error, but I do know that you don't need to signal again there.

          Perhaps in the midst of the transition, the token hasn't yet calculated it's next state and thus reports "null".

          -Britt

          • 2. Re: java.lang.IllegalStateException: couldn't signal token '
            kukeltje

            Britt,

            You may stab more often, it is quite right. You should not signal a token from within a transition that is being taken by that same token. Maybe a check could be build in, to give a better exception, but currently it is the way it is.

            The same is true for actions. Never signal our own state (the token that is in that state). If something like an automatic transition is needed, use the basic 'node' and implement functionality in the node and not in the action.

            • 3. Re: java.lang.IllegalStateException: couldn't signal token '

              Thanks Britt and Kukeltje for the quick replies with good reasoning.

              Can you please elaborate (possibly an example) on your statement?

              If something like an automatic transition is needed, use the basic 'node' and implement functionality in the node and not in the action.


              I am looking for a solution where there is no external Actor. Like, the JUnit test case that keeps calling processInstance.signal() or swimlane/actor assignments etc that needs User invervention. I want the ProcessInstance to go into a state, execute an Action Handler and then automatically transit into the next state. The processInstance waits in a State if it needs attention. Is it possible at all? or does it makes you wonder why am I thinking about BPM if it automatically transitions?

              Think about Purchase Order processing. It goes into a number of steps before the a purchased product is delivered out the door to the customer. I want to be able to keep track of where the Purchase Order is stuck in processing. If everything goes well, the product gets delivered without ANY intervention by any User or any System.

              Section 7.8 of jBPM JBoss 3.0 and also several other places state
              The Action Handler implementation can execute any business logic, but also has the responsibility to propagate the graph execution


              I interpret the statement that I would be able to signal the transition from an action handler.


              Thanks
              kiran222