cancel
Showing results for 
Search instead for 
Did you mean: 

Query for boundary message event does not work

kiyer
Champ in-the-making
Champ in-the-making
Hi,
I am using activiti currently in the test setup to get acquainted. The out of the box config has been set to the H2 in memory database.
I have created a message boundary event for one of my subprocesses. In BPMN it is defined as:
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://activiti.org/bpmn20">  …  <message id="cancelRenewal" name="cancelRenewal"></message>  <process id="signupWorkflow" name="Sugarsync Signup Process" isExecutable="true">…     <boundaryEvent id="boundarymessage1" name="Message" attachedToRef="subprocess1" cancelActivity="true">        <messageEventDefinition messageRef="cancelRenewal"></messageEventDefinition>      </boundaryEvent>  </process></definitions>‍‍‍‍‍‍‍‍‍‍‍‍
I have plugged in a java service task where i wish to send a message to cancel this process:
[java]
RuntimeService runtimeService = execution.getEngineServices().getRuntimeService();
String executionId = runtimeService.createExecutionQuery().messageEventSubscriptionName("cancelRenewal").singleResult().getId();
[/java]
Unfortunately I get a nullpointerException because
[java]
runtimeService.createExecutionQuery().messageEventSubscriptionName("cancelRenewal").singleResult()
[/java] returns null.
Any idea if I am doing something wrong here? or is it a bug?

Thanks!
kiyer
8 REPLIES 8

jbarrez
Star Contributor
Star Contributor
Where is this service task in the process? Could it be that the boundary event is not yet persisted to the database because the service task is part of the same transaction?

kiyer
Champ in-the-making
Champ in-the-making
Interesting point regarding the transaction. I am building off of the unit test examples in Activiti user guide. here is the process fragment of interest: [img]https://docs.google.com/drawings/d/1zIjv90Sc0dauUHRfRjQCBsXlBZMGzMqxsPU9bxgobMA/pub?w=960&h=720[/img]
The subprocess for renew subscription has a boundary message event to cancel on receiving the message (See the xml posted earlier). The message is sent by the script task "Send cancel renewal message". It has the following groovy script in it [java]
processId = execution.processInstanceId;
org.activiti.engine.RuntimeService runtimeServiceVar = execution.engineServices.runtimeService;
println "Current processId: ${processId}";
executionId=runtimeServiceVar.createExecutionQuery().signalEventSubscriptionName("cancelRenewal").singleResult().id;
println "Sending cancel Renewal message to executionId: ${executionId}";
runtimeServiceVar.messageEventReceived("cancelRenewal",executionId);
[/java]
The following expression in the code above is null and hence I get a NullPointerException
[java]
runtimeServiceVar.createExecutionQuery().signalEventSubscriptionName("cancelRenewal").singleResult()
[/java]

They run as part of a single test method execution:
[java]
@Test
public void testSignupWorkflow() throws Exception {
  runtimeService.startProcessInstanceByKey("signupWorkflow");
  Task task = taskService.createTaskQuery()
    .taskCandidateGroup("anonymous").singleResult();
  String procId = task.getProcessInstanceId();
  assertEquals("User enters email address", task.getName());
  Map<String, Object> taskVariables = new HashMap<String, Object>();
  taskVariables.put("emailAddress", "kiyer@yopmail.com");
  taskService.complete(task.getId(), taskVariables);
  //Wait for timer task to fire
  HistoricProcessInstance historicProcessInstance = historyService
    .createHistoricProcessInstanceQuery().processInstanceId(procId)
    .singleResult();
  while(historicProcessInstance.getEndActivityId()==null){
    historicProcessInstance = historyService
      .createHistoricProcessInstanceQuery().processInstanceId(procId)
      .singleResult();
   System.out.println("Process has not ended yet. Trying again after 2 seconds");
   Thread.sleep(2000);
  }
  assertNotNull("Process should have ended by now!", historicProcessInstance.getEndActivityId());
  System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
  assertEquals(0, runtimeService.createProcessInstanceQuery().count());
[/java]

Is it failing to get any results because they are part of the same transaction? If yes, then I suppose this issue will not happen in a prod environment (which is a good thing). But then the question still remains, how can I unit test this workflow if the transactions mask the data about event subscritptions in the workflow?
Thanks for your help!

kiyer
Champ in-the-making
Champ in-the-making
Just an update: I noticed in the documentation that there is no way to query for boundary message events. Can such an example be please posted?  In the user guide section titled "Querying for Message Event subscriptions", there is no example of how boundary message events can be queried.

If a unit test which shows the working of such a query be posted, I would really appreciate it.

Thanks!
kiyer

frederikherema1
Star Contributor
Star Contributor

/**
   * Only select executions which have a message event subscription
   * for the given messageName.
   *
   * (The messageName is specified using the 'name' attribute of the message element
   * in the BPMN 2.0 XML.)
   *
   * @param messageName the name of the message the execution has subscribed to
   */
  ExecutionQuery messageEventSubscriptionName(String messageName);

Is that what you're looking for? See org.activiti.engine.test.bpmn.event.message.MessageBoundaryEventTest for test

kiyer
Champ in-the-making
Champ in-the-making
Hello Frederik,
Thanks for the pointers. I checked out the unit test you mentioned. The scenario in the test is a user task with a boundary message event. I tried it out in my project and it worked just fine. However what doesnt work is a boundary message event attached to a sub-process. If you see the image in Post#3 the renewal sub process has a boundary message attached to it with message ref:cancelRenewal.
When I try to query as:
[java]
runtimeService.createExecutionQuery().messageEventSubscriptionName("cancelRenewal").singleResult()
[/java]
I get a null. Please let me know if you need a unit test to verify this and I will be happy to set it up.

Thanks!
Karthik

frederikherema1
Star Contributor
Star Contributor
Yes, a unit-test for this would be great!

kiyer
Champ in-the-making
Champ in-the-making
Thanks for responding. It looks like I can't upload the unit test project directly to this forum. So please download the failing test case maven project  from here: https://www.sugarsync.com/pf/D6473659_753_6781691378
It looks like the core of the issue is how the perpetual timers are modeled. (No necessarily an issue with boundary message event). Looking forward to your analysis…
Thanks!

frederikherema1
Star Contributor
Star Contributor
Once the timer has fired, it moves on to the script-task. if that's finished, the subprocess ends (there is no outgoing from the script-task) so the scope is destroyed. Any boundary-events attached to this scope, will be removed.

Since that's the last active execution, your whole process ends as well… You should re-model the process if you want to have the script-task executed 3 times (eg. boundary-event with cancelActiviti="false" on a subprocess which triggers the scriptTask to run but doesn't cause the subprocess to end because of the timer firing.)