2 Replies Latest reply on Apr 27, 2011 2:53 AM by laszlovandenhoek

    blocking task in start-state does not block

    laszlovandenhoek

      Hi,

       

      I'm running into the problem that a blocking task in a start-state node does not prevent a token to proceed to the next node, but a "regular" blocking task in a task-node does. I'm using the jBPM 3.2 runtime included with the latest JBoss SOA-P 5.1.

       

      The below JUnit test code illustrates the problem. There are two test cases; the only real difference is that the one tests a blocking start task and the other tests a blocking "regular" task. For me, the first test case fails but the second one succeeds. The way they are written, I would expect this to be the other way around.

       

      I understand from Re: task in start state that creating a new ProcessInstance will not automatically create a  TaskInstance for the task defined in the start-state, if any. While this  strikes me as odd, I can accept that is the way things work. However,  once I manually create the StartTaskInstance, I do expect it to block  progress to the next node.

       

      {code:java}
      import java.util.HashMap;

      import java.util.Map;

      import junit.framework.TestCase;

      import org.jbpm.graph.def.ProcessDefinition;

      import org.jbpm.graph.exe.ProcessInstance;

      import org.jbpm.taskmgmt.exe.TaskInstance;

      import org.junit.Before;

      import org.junit.Test;

       

      public class JbpmTest extends TestCase {

           private ProcessDefinition pd;

       

           @Before

           public void setUp() {

                this.pd = ProcessDefinition.parseXmlString(

                  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +

                  "<process-definition  xmlns=\"\"  name=\"blockingStartTask\">" +

       

                  "    <start-state name=\"start\">" +

                  "        <task blocking=\"true\" name=\"blocking task in start node\"></task>" +

                  "        <transition to=\"task\"></transition>" +

                  "    </start-state>" +

       

                  "    <task-node name=\"task\">" +

                  "        <task blocking=\"true\" name=\"blocking task in task node\" ></task>" +

                  "        <transition to=\"end\"></transition>" +

                  "    </task-node>" +

       

                  "    <end-state name=\"end\"></end-state>" +

       

                  "</process-definition>"

              );

          }

       

          @Test

          public void testBlockingStartTask() {

              ProcessInstance pi = pd.createProcessInstance();

       

              //I would have expected a task instance to have been created by now; I guess that's not how it works.

              //assertEquals("expected task was not created", 1, pi.getTaskMgmtInstance().getTaskInstances().size());

       

              TaskInstance ti = pi.getTaskMgmtInstance().createStartTaskInstance();

       

              assertEquals("expected task was not created", 1, pi.getTaskMgmtInstance().getTaskInstances().size());

              assertEquals("task has wrong name", "blocking task in start node", ti.getName());

              assertTrue(ti.isBlocking());

              assertTrue(ti.isStartTaskInstance());

              assertTrue(pi.getTaskMgmtInstance().hasBlockingTaskInstances(pi.getRootToken()));

       

              try {

                  pi.getRootToken().signal();

                  fail("task that should be blocking nevertheless did not block");

              } catch (IllegalStateException e) {

                  assertEquals("state changed despite blocking task", "start", pi.getRootToken().getNode().getName());

              }

       

              assertEquals("start", pi.getRootToken().getNode().getName());

       

          }

       

          @Test

          public void testBlockingRegularTask() {

              ProcessInstance pi = pd.createProcessInstance();

       

              assertEquals("start", pi.getRootToken().getNode().getName());

              pi.signal(); //this ought to go wrong, but it doesn't (see previous test case)

              assertEquals("task", pi.getRootToken().getNode().getName());

       

              assertEquals("expected task was not created", 1, pi.getTaskMgmtInstance().getTaskInstances().size());

       

              TaskInstance ti = pi.getTaskMgmtInstance().getTaskInstances().iterator().next();

       

              assertEquals("task has wrong name", "blocking task in task node", ti.getName());

              assertTrue(ti.isBlocking());

              assertFalse(ti.isStartTaskInstance());

              assertTrue(pi.getTaskMgmtInstance().hasBlockingTaskInstances(pi.getRootToken()));

       

              try {

                  pi.getRootToken().signal();

                  fail("task that should be blocking nevertheless did not block");

              } catch (IllegalStateException e) {

                  assertEquals("state changed despite blocking task", "task", pi.getRootToken().getNode().getName());

              }

       

              assertEquals("task", pi.getRootToken().getNode().getName());

       

       

       


              ti.end();

           
              assertEquals("end", pi.getRootToken().getNode().getName());

           
          }

      }


      {code}

       

       

      Any thoughts?

       

      Thanks in advance!

       

      Hi,

       

      I'm running into the problem that a blocking task in a start-state node does not prevent a token to proceed to the next node, but a "regular" blocking task in a task-node does. I'm using the jBPM 3.2 runtime included with the latest JBoss SOA-P 5.1.

       

      The below JUnit test code illustrates the problem. There are two test cases; the only real difference is that the one tests a blocking start task and the other tests a blocking "regular" task. For me, the first test case fails but the second one succeeds. The way they are written, I would expect this to be the other way around.

       

      I understand from {thread:id=390489} that creating a new ProcessInstance will not automatically create a TaskInstance for the task defined in the start-state, if any. While this strikes me as odd, I can accept that is the way things work. However, once I manually create the StartTaskInstance, I do expect it to block progress to the next node.

       

      {code}
      import java.util.HashMap;
      import java.util.Map;

       

      import junit.framework.TestCase;

       

      import org.jbpm.graph.def.ProcessDefinition;
      import org.jbpm.graph.exe.ProcessInstance;
      import org.jbpm.taskmgmt.exe.TaskInstance;
      import org.junit.Before;
      import org.junit.Test;

       

      public class JbpmTest extends TestCase {
         
          private ProcessDefinition pd;
         
          @Before
          public void setUp() {
              this.pd = ProcessDefinition.parseXmlString(           
                  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                  "<process-definition  xmlns=\"\"  name=\"blockingStartTask\">" +
                 
                  "    <start-state name=\"start\">" +
                  "        <task blocking=\"true\" name=\"blocking task in start node\"></task>" +
                  "        <transition to=\"task\"></transition>" +
                  "    </start-state>" +
                 
                  "    <task-node name=\"task\">" +
                  "        <task blocking=\"true\" name=\"blocking task in task node\" ></task>" +
                  "        <transition to=\"end\"></transition>" +
                  "    </task-node>" +
                 
                  "    <end-state name=\"end\"></end-state>" +
                 
                  "</process-definition>"
              );
          }
         
          @Test
          public void testBlockingStartTask() {
              ProcessInstance pi = pd.createProcessInstance();
             
              //I would have expected a task instance to have been created by now; I guess that's not how it works.
              //assertEquals("expected task was not created", 1, pi.getTaskMgmtInstance().getTaskInstances().size());
             
              TaskInstance ti = pi.getTaskMgmtInstance().createStartTaskInstance();
             
              assertEquals("expected task was not created", 1, pi.getTaskMgmtInstance().getTaskInstances().size());
              assertEquals("task has wrong name", "blocking task in start node", ti.getName());
              assertTrue(ti.isBlocking());
              assertTrue(ti.isStartTaskInstance());
              assertTrue(pi.getTaskMgmtInstance().hasBlockingTaskInstances(pi.getRootToken()));
             
              try {
                  pi.getRootToken().signal();
                  fail("task that should be blocking nevertheless did not block");
              } catch (IllegalStateException e) {
                  assertEquals("state changed despite blocking task", "start", pi.getRootToken().getNode().getName());
              }
             
              assertEquals("start", pi.getRootToken().getNode().getName());
             
          }
         
          @Test
          public void testBlockingRegularTask() {
              ProcessInstance pi = pd.createProcessInstance();
             
              assertEquals("start", pi.getRootToken().getNode().getName());
              pi.signal(); //this ought to go wrong, but it doesn't (see previous test case)
              assertEquals("task", pi.getRootToken().getNode().getName());
             
              assertEquals("expected task was not created", 1, pi.getTaskMgmtInstance().getTaskInstances().size());
             
              TaskInstance ti = pi.getTaskMgmtInstance().getTaskInstances().iterator().next();
             
              assertEquals("task has wrong name", "blocking task in task node", ti.getName());
              assertTrue(ti.isBlocking());
              assertFalse(ti.isStartTaskInstance());
              assertTrue(pi.getTaskMgmtInstance().hasBlockingTaskInstances(pi.getRootToken()));
             
              try {
                  pi.getRootToken().signal();
                  fail("task that should be blocking nevertheless did not block");
              } catch (IllegalStateException e) {
                  assertEquals("state changed despite blocking task", "task", pi.getRootToken().getNode().getName());
              }
             
              assertEquals("task", pi.getRootToken().getNode().getName());

       

              ti.end();
             
              assertEquals("end", pi.getRootToken().getNode().getName());
             
          }
      } {code}

       

      Any thoughts?

       

      Thanks in advance
        • 1. Re: blocking task in start-state does not block
          mohreece

          Hey László,

           

          The point you're missing here is that a task in a start-state has a different purpose than one in a task-node (which is, admittedly, not very clear from the documentation, but could be derived from this section).

           

          If you look at the jPDL definition, you'll see that there are only two node types that support tasks:

          • task-node: for human tasks that are part of your business process and are assigned, started and ended while the process is running. It has support for the full task lifecycle (e.g. through the optional attributes create-tasks and end-tasks), including the 'blocking' semantics.
          • start-state: for the sole purpose of being able to start a process by means of a human task. And therefore, blocking this makes no sense.

           

          Take a closer look at the unit test that is shown in the thread you referred to, and you'll see that in the test that has a task in its start-state, the process is started through a createStartTaskInstance() - taskInstance.end() sequence, before the token ends up waiting in the 'going steady' state.

           

          Your unit test starts the process in a different way (through the signal() call on the ProcessInstance). While this is still possible (i.e. having a task in the start-state doesn't prevent you from starting the process in another manner), it also means that in this case that task has no use anymore for this particular instance of the process, and therefore it is ignored completely.

           

          So if you set out to have a blocking task as the first thing in your process, you need to do so with a task-node that directly follows your start-state. And actually, that's pretty much what you've done in your second unit test - but you just as well may omit your not-so-blocking task from the process definition.

           

          Regards,

          Maurice

          • 2. Re: blocking task in start-state does not block
            laszlovandenhoek

            Thanks for explaining, Maurice! I had in fact read the section of the manual you are referring to, but what I really wanted to accomplish was to create a ProcessInstance by a JBoss ESB call, resulting in a (blocking) task for a user. I achieved this by putting the task in a task node directly following the (empty) start state, as you mentioned, and using the StartProcessInstanceCommand in the BpmProcessor Action of JBoss ESB (http://docs.redhat.com/docs/en-US/JBoss_Enterprise_SOA_Platform/5/html-single/ESB_Services_Guide/index.html#id5189004). This causes the ProcessInstance to automatically transition to the first node of the process (i.e., the task node), triggering a (properly blocking) task to be created.