Wrong current task detected on UserTask7's listener

Hi guys,

I’ve got the following diagram:

In the following diagram the sequence we follow is:

  • We firt complete the bottom branch of the process: userTask1, userTask5, userTask6. We also set “condition1” for our exclusive gateway to follow the path to userTask3.

  • Then we send the boundary event evnBoundaryUserTask3, and the process reaches receiveTask4.

  • Then we set condition2 on the second exclusive gateway so that the subprocess follows the path to end, and we send MSGTASK4, to leave receiveTask4.

From this point what we expect is to reach userTask7.

The problem is that when querying the current task from userTask7’s create task listener it returns null (I use the taskService), and if we query the history service it says it’s receiveTask4 (which is supposedly ended). On the other side, the DelegateTask inside our listener says it’s userTask7.

Why doesn’t the task query from taskService returns a result that is coherent with DelegateTask from inside the listener?

Also, why does the receiveTask4 still appears as unfinished if whe query the history service with the following query?

Blockquote
historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).unfinished().list()

Can you help me, please?
Thanks in advance…

Alfonso.
PS: I also attach the bpmn diagram just in case it’s clearer for you.

testProcess.bpmn (5.8 KB)

Hi Alfonso,
How old is your Modeler? What version of Camunda are you trying to use? When I attempt to open your bpmn I get:
image

This is what I see in the xml:

exporter=“Camunda Modeler” exporterVersion=“1.7.0-nightly”

Which suggests an ancient (and maybe unreliable, given it looks to be a nightly build) version of Modeler

And after conversion I see:
image

Try downloading a more up to date Modeler and give it a try. There might be something in your model that’s causing your issue but it’ll be hard to figure it out given the abbreviated nature of the bpmn.

Joe

In reading through your description of the issue you may not be correlating the message to the instance. This would cause the message to never be received by the instance hence Receive Task 4 never completing. How are you correlating the message?

Joe

Hi Joe,

We are not correlating the message, we are using messageReceived method instead. This is what we do:

Blockquote
String foundExecutionId = null;
ExecutionQuery query =
runtimeService.createExecutionQuery().processInstanceId(processInstanceId).messageEventSubscriptionName(messageName); i
f (relatedProcessInstance == null || localVariableId == null) {
List executions = query.list();
if (executions != null && executions.size() > 0) {
foundExecutionId = executions.get(0).getId();
}
}
runtimeService.messageEventReceived(messageName, foundExecutionId, variables);

Can this be the cause of the problem? We search for an execution inside our process instance which is able to receive the message, and then we send it to that intermediate event receiver.

I could not test the diagram conversion with a newer version of camunda modeler, because I’m afraid that we would be forced to change many pieces of code now, and test it, and we are short of time now…

I keep looking forward to your answer,
Thanks a lot, Joe :wink:
Alfonso.

Hi Alfonso,
Where are you executing the above code? It could be a timing/transaction boundary issue if it’s executed before the token reaches Receive Task 4. Though it could be related to the version of Camunda you’re using. What version are you using?

Joe

Hi Joe, I’m using camunda version 7.8.0.

We execute this code when we are at receiveTask4, in order to leave that branch. Since the lower branch of the process is waiting at the gateway the process leaves task4 and reaches receiveTask7…

I don’t know if this gives you some hint on what’s going on…

Also, I apologize because I attached the wrong version of my bpmn diagram, here is the correct one, I attach here again.

Thanks in advance, Joe, I really apreciate your help :slight_smile:

Alfonso
testProcess.bpmn (17.1 KB)

Hi Alfonso,
Ah, that’s better :slight_smile: So, where are you executing this Java code? In a JUnit test, a POJO? I was able to deploy and test the process but got this error when I sent a message to Receive Task 4 (I used REST to send messages):

    "message": "ENGINE-03051 There was an exception while invoking the TaskListener. Message: 'Unknown property used in expression: ${userTask7Listener}. Cause: Cannot resolve identifier 'userTask7Listener''"

image
Your Java code should work. Could you upload the complete code as well? Do you have code associated with the listener?

Joe

Hi Joe,

First of all let me say that I appreciate your help very much :slight_smile:

Here goes my code, I uploaded it to:

I think I can narrow the problem a little bit more…
You will see that inside UserTaskListener we use three ways to find out which are the current tasks:

  • from runtimeService.getActiveActivityIds: it returns serviceTask7 (correct)
List<String> activityIds = delegateTask.getProcessEngineServices().getRuntimeService().getActiveActivityIds(delegateTask.getExecutionId());
  • from serviceTask.createTaskQuery: it doesn’t return any task at all (this is incorrect):

List tasks = delegateTask.getProcessEngineServices().getTaskService().createTaskQuery().processInstanceId(delegateTask.getProcessInstanceId()).list();

  • from our method, which queries the Activity History to query which are the unfinished activities. It returns receiveTask4 (even when we are already inside userTask7 delegates!).

List currentActivities = ProcessUtils.getProcessCurrentActivities(delegateTask.getProcessEngineServices().getHistoryService(), delegateTask.getProcessInstanceId());

Which executes this HistoryService query:

   List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).unfinished().list();

We use the last way from outside the listeners to get to know if the process is stopped at some receiveTask (i.e. an activity that it’s not a user task), and using processInstance as a parameter.

In short, we’d like to have a method that it’s equivalent to the one that it’s working but passing the processInstanceId instead of the executionId, or alternatively, getting to know which is the parent execution of that processInstance…

Otherwise we are looping thru the executions inside a processInstance, as you will see in our sendMessage method inside our class ProcessUtils.

With all that, I’d be glad if you could explain why these methods return different things and also, which is the correct way to find out the current activity either from inside or outside the delegate.

Thank you very much, Joe :wink:

Ok, but when/where are you executing the code to finish Receive Task 4 during process execution?

From the SimpleTestCase class:

    assertThat(task("userTask3")).isNotNull();
   runtimeService().correlateMessage("MSG_BOUNDARY_USERTASK3");
    List<HistoricActivityInstance> currentActivities = ProcessUtils.getProcessCurrentActivities(processEngine().getHistoryService(), processInstance.getProcessInstanceId());
    System.out.print("from TestCase: Activities from HistoryService: ");
    for (HistoricActivityInstance activityInstance : currentActivities) {
        System.out.print(activityInstance.getActivityId());
        System.out.print(" / ");
    }
    System.out.println();

    runtimeService().setVariable(processInstance.getProcessInstanceId(), "condition2", true); 
    runtimeService().correlateMessage(("MSG_TASK4"));

    assertThat(task("userTask7")).isNotNull();

Sorry Joe, when I pasted the code the most interesting line of code was pasted in the same line of the upper one…

now the code is correct and you can see that inside SimpleTestCase I correlate the message:
runtimeService().correlateMessage((“MSG_TASK4”));

You should remove the extra set of parentheses…it should be runtimeService().correlateMessage("MSG_TASK4"); Also, you’re invoking the listener at the ‘create’ event before the transaction has been committed which is why you’re seeing ‘Receive Task 4’. Switch it to the ‘complete’ event and you’ll see the difference. I updated the git repo with the above. It works as you intended, it was just a matter of getting the timing correct with the transaction commits.

Joe

Thanks a lot, Joe! :slight_smile:

But the complete event for userTask7 won’t suit our needs… our goal is to send to ElasticSeach the taskId where our process instance is now in order to index it…

If we use the complete task then we are going to index it when the task is already gone…
Which event do you think we could use in order to send to Elasticsearch the current state? (userTask7)

Or is it that we must force an asyncBefore in userTask7?

Thanks again and sorry for being so insistent…

Well your code here works even using the ‘create’ event:

System.out.print("from User7TaskDelegate: activities from runtimeService.getActivityIds: ");

from User7TaskDelegate: activities from runtimeService.getActivityIds: userTask7 /

Yes… But it seems that runtimeService and TaskService operate in different transactions? Does it has to be this way?

The APIs are not working in different transactions, I believe it’s a matter of where the APIs are looking for information, whether’s it’s in the execution context or in the database. Typically when there’s a mismatch of what is expected versus was is observed it’s usually a matter of timing and when a transaction is committed to the database. Plus, these two services serve different functions. For more information regarding various services have a look here.

Ok, Joe! Thank you very much, you gave me a deeper understanding on what’s going on…

Let me ask you my last question… when it comes to using correlate or sendMessage, do you think that one way is more reliable than the other?

Can you have a look to our ProcessUtils.sendMessage? Is this the common way to find which is the right execution inside a processInstance that can receive a message? Or is it a shorter or more robust way to do so?

This is the last question, and let me say that your answers were really useful to us and gave us a deeper insight on the way it works!

I appreciate your help very much!
Cheers!
Alfonso.

You’re welcome Alfonso! Always glad to be of help. My preference is to use correlate as you don’t need to find the process instance execution id. All you need are the correlation keys whether it is the business key or a process variable. With correlate message you have many more options to send information like the message name, correlations, variables, business keys, etc) There is no need to have the process instance id or need to find the execution id. Have fun!

Joe

Thanks a lot for all your answers and dedication, you really made me understand how to solve this situation, I think I can manage to fix it now:

  • I will use correlate instead of sendMessage.
  • In order to query the current activities/tasks I will use execution query through runtimeService from outside the listeners or delegateTask.getExecution from inside the taskListener, in order to avoid possible out-of-date results caused by transactional issues.

Thanks again,
Alfonso.