Uploaded image for project: 'jBPM'
  1. jBPM
  2. JBPM-1042

org.jbpm.JbpmException: token '1' can't be locked by 'job[1]' cause it's already locked by 'token[1]'

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • jBPM 3.2.2
    • jBPM 3.2.1
    • Runtime Engine
    • None

      org.jbpm.JbpmException: token '1' can't be locked by 'job[1]' cause it's already locked by 'token[1]' is thrown when a node has an ActionHandler that propagates execution via ExecutionContext.leaveNode() to a node that is marked as async="true".

      My ActionHandler.execute() method:
      public void execute(ExecutionContext executionContext) throws Exception

      { // Normally would do stuff here // Leave via the default transition // When this test case was written, this method would throw when // it tried to enter Node2 because it would try to lock the token but // it is already locked. executionContext.leaveNode(); }

      }

      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.

      The execute() method from Node does not propagate the execution context if there is a custom action associated with the node. Based on this code and the documentation above, I concluded that I must propagate the execution inside my action handler.

      // From org.jbpm.graph.def.Node.execute()
      public void execute(ExecutionContext executionContext) {
      // if there is a custom action associated with this node
      if (action!=null) {
      try

      { // execute the action executeAction(action, executionContext); }

      catch (Exception exception)

      { // NOTE that Error's are not caught because that might halt the JVM and mask the original Error. // search for an exception handler or throw to the client raiseException(exception, executionContext); }

      } else

      { // let this node handle the token // the default behaviour is to leave the node over the default transition. leave(executionContext); }

      }

      However this appears to conflict with the comments 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) {

      Originally this test case failed in jBPM 3.2.1 with the following exception

      • org.jbpm.JbpmException: token '1' can't be locked by 'job[1]' cause it's already locked by 'token[1]'
        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$$cc789161.enter(<generated>)
        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 org.jbpm.job.executor.SimpleAsyncProcessTest$AsyncAction.execute(SimpleAsyncProcessTest.java:57)
        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$$4852cc95.execute(<generated>)
        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$$cc789161.enter(<generated>)
        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$$cc789161.leave(<generated>)
        at org.jbpm.graph.exe.Token.signal(Token.java:194)
        at org.jbpm.graph.exe.Token.signal(Token.java:139)
        at org.jbpm.graph.exe.ProcessInstance.signal(ProcessInstance.java:270)
        at org.jbpm.job.executor.SimpleAsyncProcessTest.launchProcess(SimpleAsyncProcessTest.java:112)
        at org.jbpm.job.executor.SimpleAsyncProcessTest.testConsecutiveAycnActionHandlers(SimpleAsyncProcessTest.java:69)
        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 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.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

            tom.baeyens Tom Baeyens (Inactive)
            jeffj55374_jira Jeff (Inactive)
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: