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

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

    Brian Westrich Newbie

      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.