4 Replies Latest reply on Oct 19, 2009 11:29 AM by bwestrich

    jBPM 4: how to transition via Java handler/listener?

      In jBPM 3.2.3, in a Java action handler you can do a transition by calling executionContext.leaveNode(String signalName).
      How is this done in jBPM 4?

      I've tried doing this using a Java event listener, but the transition doesn't execute. Here's the details:

      I used the following model (capital names are the states, small case names in parentheses are the transition names):

      Start ->
      Initial --(manually)--> TransitionedToManually --(byListener)--> TransitionedToByListener
      -> End

      Then I created a process instance for the model, which was initially in the "Initial" state, e.g.

      ProcessInstance processInstanceInitial = executionService.startProcessInstanceByKey("SimpleModel");
      assertEquals("Initial", processInstanceInitial.findActiveActivityNames().iterator().next());


      Then I manually signaled a transition:
      ProcessInstance processInstanceAtManualState =
       executionService.signalExecutionById(processInstanceInitial.getId(), "manually");


      After this signal, I wanted to transition to the TransitionedToManually state, and then (via Java code in a listener) transition to the 'TransitionedToByListener' state. So I wrote a Java event listener for the transitionedToManually state that looks like this:

      public class FirstEnterHandler implements EventListener {
       public void notify(EventListenerExecution execution) throws Exception {
       ExecutionService executionService =
       new Configuration().buildProcessEngine().getExecutionService();
       ProcessInstance processInstance =
       executionService.signalExecutionById(execution.getId(), "byListener");
       }
      }


      ...and attached it to the state like so...

      <state name="TransitionedToManually">
       <on event="start">
       <event-listener class="jbpm4.spike.FirstEnterHandler">
       </event-listener>
       </on>
       <transition to="TransitionedToByListener" name="byListener" />
       </state>


      But though the handler code executed, the second transition (byListener) did not happen (the execution ended in the state TransitionedToManually.
      One curious thing I noticed is that although the execution passed into the event listener's notice() method is in the state of TransitionedToManually, the process instance returned by signalExecutionById in that method is in the state Initial. I would have expected the process instance to be in the same state as the passed in execution.
      Any ideas on how to request a transition in jBPM 4 using Java?

      P.S. the full code of my example is shown below.


      First, the unit test that drives the rest of the code:

      package jbpm4.spike;
      
      import org.jbpm.api.ProcessInstance;
      import org.jbpm.test.JbpmTestCase;
      
      public class SimpleModelTest extends JbpmTestCase {
      
       String deploymentId;
      
       protected void setUp() throws Exception {
       super.setUp();
      
       deploymentId =
       repositoryService.createDeployment().addResourceFromClasspath("jbpm4/spike/process.jpdl.xml")
       .deploy();
       }
      
       public void test() {
      
       ProcessInstance processInstanceInitial = executionService.startProcessInstanceByKey("SimpleModel");
       assertEquals("Initial", processInstanceInitial.findActiveActivityNames().iterator().next());
      
       ProcessInstance processInstanceAtManualState =
       executionService.signalExecutionById(processInstanceInitial.getId(), "manually");
      
       ProcessInstance processInstanceAtListenerState;
       if (!FirstEnterHandler.TRANSITION_USING_HANDLER) {
       assertEquals("TransitionedToManually", processInstanceAtManualState.findActiveActivityNames()
       .iterator().next());
       processInstanceAtListenerState =
       executionService.signalExecutionById(processInstanceAtManualState.getId(), "byListener");
       } else {
       processInstanceAtListenerState =
       executionService.findProcessInstanceById(processInstanceAtManualState.getId());
       }
       assertEquals("TransitionedToByListener", processInstanceAtListenerState.findActiveActivityNames()
       .iterator().next());
       assertFalse(processInstanceAtListenerState.isEnded());
       ProcessInstance processInstanceAtEnd =
       executionService.signalExecutionById(processInstanceAtListenerState.getId(), "end");
       assertTrue(processInstanceAtEnd.isEnded());
       }
      }

      Next, the event listener:

      package jbpm4.spike;
      
      import org.jbpm.api.Configuration;
      import org.jbpm.api.ExecutionService;
      import org.jbpm.api.ProcessInstance;
      import org.jbpm.api.listener.EventListener;
      import org.jbpm.api.listener.EventListenerExecution;
      import org.jbpm.api.model.OpenExecution;
      
      public class FirstEnterHandler implements EventListener {
      
       public static boolean TRANSITION_USING_HANDLER = true;
      
       public void notify(EventListenerExecution execution) throws Exception {
       OpenExecution openExecution = execution;
       if (TRANSITION_USING_HANDLER) {
       ExecutionService executionService =
       new Configuration().buildProcessEngine().getExecutionService();
      
       ProcessInstance processInstance =
       executionService.signalExecutionById(execution.getId(), "byListener");
       }
       }
      }


      Finally, the process definition file (process.jpdl.xml):

      <?xml version="1.0" encoding="UTF-8"?>
      
      <process name="SimpleModel" xmlns="http://jbpm.org/4.0/jpdl">
      
       <start g="29,24,48,48">
       <transition to="Initial"/>
       </start>
      
       <state g="40,124,92,52" name="Initial">
       <transition g="-5,-18" name="manually" to="TransitionedToManually"/>
       </state>
      
       <state g="88,239,149,49" name="TransitionedToManually">
       <on event="start"> <!-- event used to be "node-enter" -->
       <event-listener class="jbpm4.spike.FirstEnterHandler">
       </event-listener>
       </on>
       <transition g="-5,-18" name="byListener" to="TransitionedToByListener"/>
       </state>
      
       <state g="191,338,154,52" name="TransitionedToByListener">
       <transition g="-5,-18" name="end" to="end1"/>
       </state>
      
       <end g="413,424,48,48" name="end1"/>
      
      </process>

      Thanks in advance for your help.


        • 1. Re: jBPM 4: how to transition via Java handler/listener?
          sebastian.s

          Since I haven't been working with jbpm 3.x it's hard for me to get what exactly you are trying to achieve. I tried your unit test and I got the message that the execution was not found.

          I can be wrong but doesn't this create a new process engine?

          ExecutionService executionService =
           new Configuration().buildProcessEngine().getExecutionService();
          


          I am really not sure how to retrieve a reference on the process eninge already created in the context of an EventListener but I tried using the following:
          ExecutionService executionService =
           Configuration.getProcessEngine().getExecutionService();
          


          The error that the execution was not found did not occur anymore but there was an assertion failure:

          12:24:14,734 SEV | [BaseJbpmTestCase] ASSERTION FAILURE: expected:<TransitionedTo[ByListener]> but was:<TransitionedTo[Manually]>
          junit.framework.ComparisonFailure: expected:<TransitionedTo[ByListener]> but was:<TransitionedTo[Manually]>
          


          Hope this helps at least bit. If this does not I'd be eager to know if it's possible and how.

          • 2. Re: jBPM 4: how to transition via Java handler/listener?
            camunda

            Influencing sequence flow in an eventHandler isn't the right approach. If yiu need own control flow logic, implement your custom activity.

            In jBPM 3 this was possible, but basically more because of a design flaw. This is why it was changed in jbpm 4.

            Cheers
            Bernd

            • 3. Re: jBPM 4: how to transition via Java handler/listener?
              sebastian.s

              Thanks Bernd for clarifying this.

              So here's your point to start, bwestrich. :)
              http://docs.jboss.com/jbpm/v4/userguide/html_single/#custom

              • 4. Re: jBPM 4: how to transition via Java handler/listener?

                Thanks Bernd and sebastian.s. I used the custom activity approach and it worked as expected!