cancel
Showing results for 
Search instead for 
Did you mean: 

Strange behaviour query/signal multi instance receive task

aapthorp
Champ in-the-making
Champ in-the-making
I have a process with a multi instance receive task i.e. one instance for the number of messages I expect to receive before the receive task completes.

When I query the receive task (as per the user guide but returning a list) I always get one extra execution returned. i.e. expect 2 get 3, etc. The returned ids always match what I find in the database (ACT_HI_ACTINST) except for the second one. I can never find this id.

The behaviour then gets stranger. If I signal the first execution I get an NPE error. However, signalling the second execution succeeds!

18-Feb-2013 19:40:49 org.activiti.engine.impl.interceptor.CommandContext close
SEVERE: Error while closing command context
java.lang.NullPointerException
        at org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior.leave(ParallelMultiInstanceBehavior.java:96)
        at org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.leave(AbstractBpmnActivityBehavior.java:49)
        at org.activiti.engine.impl.bpmn.behavior.ReceiveTaskActivityBehavior.signal(ReceiveTaskActivityBehavior.java:35)
        at org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior.signal(MultiInstanceActivityBehavior.java:102)
        at org.activiti.engine.impl.persistence.entity.ExecutionEntity.signal(ExecutionEntity.java:353)
        at org.activiti.engine.impl.cmd.SignalCmd.execute(SignalCmd.java:45)
        at org.activiti.engine.impl.cmd.NeedsActiveExecutionCmd.execute(NeedsActiveExecutionCmd.java:52)
        at org.activiti.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
        at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:60)
        at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
        at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40)
        at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:32)
        at org.activiti.engine.impl.RuntimeServiceImpl.signal(RuntimeServiceImpl.java:170)
        at com.ajita.activiti.MessageSender.notify(MessageSender.java:60)
        at org.activiti.engine.impl.delegate.TaskListenerInvocation.invoke(TaskListenerInvocation.java:34)

Has anyone else run into this issue or has no one else tried multi instance receive tasks?

I assume the reason for one extra task, is in effect a parent for each of the individual tasks, but then how is this stored in the database?

At what point does the individual multi task get marked as ended? When each one is signalled?
14 REPLIES 14

jbarrez
Star Contributor
Star Contributor
I assume the reason for one extra task, is in effect a parent for each of the individual tasks, but then how is this stored in the database?

Yes, internally the executions are stored as a tree structure. In the case of multi instance, there is indeed a 'parent' execution stored in the database

At what point does the individual multi task get marked as ended? When each one is signalled?

Indeed. Each of the child executions need to be signalled before the process continues.

I must admin, I think we haven't tested a multi instance receive yet. There aren't many use cases for it, but still it should work. Do you have a sinple unit test that demonstrates the problem?

aapthorp
Champ in-the-making
Champ in-the-making
Thanks, this starts to make a bit more sense.

Question, how do I detect which instance has already been signalled? I can see that one gets marked as inactive in the database. I assumed that Execution.isEnded() would tell me which one is complete, but seems to return false even for the inactive instance.

Interestingly my jUnit example returns the parent last and not first from the executionQuery.

jbarrez
Star Contributor
Star Contributor
Question, how do I detect which instance has already been signalled? I can see that one gets marked as inactive in the database. I assumed that Execution.isEnded() would tell me which one is complete, but seems to return false even for the inactive instance.

No, inactive means something different than ended (ended is actually an edge case, cause it really means the flow has stopped, which typically means they won't be in the database anymore).

Can't you use ExecutionQuery activityId(String activityId); to fetch the executions which are specifically on the receive task?
If that query also returns the parent or any already signalled children then we've hit a limit of Activiti and we'll have to add some new logic I'm afraid.

Interestingly my jUnit example returns the parent last and not first from the executionQuery.

The order of how they are returned is not specified, ie. that will be database specific.

aapthorp
Champ in-the-making
Champ in-the-making
Can't you use ExecutionQuery activityId(String activityId); to fetch the executions which are specifically on the receive task?
If that query also returns the parent or any already signalled children then we've hit a limit of Activiti and we'll have to add some new logic I'm afraid.

Indeed this is what I'm doing - line from my jUnit test (happy to provide the whole test) as follows:

List<Execution> executionList = runtimeService.createExecutionQuery()
        .processInstanceId(processInstance.getId())
        .activityId("receivetask1")
        .list();

So some new logic needed in Activiti then?

In the meantime I'll see if I can fix this with a native query. Am I correct in thinking that I want executions with the database column IS_ACTIVE = true ?

aapthorp
Champ in-the-making
Champ in-the-making
List<Execution> executionList = runtimeService.createNativeExecutionQuery()
        .sql("SELECT * FROM ACT_RU_EXECUTION WHERE ACT_ID_ = 'waitWeighed' AND IS_ACTIVE_ = 'TRUE'AND IS_SCOPE_ = 'FALSE'")
        .list();

Seems to do the trick, even with a normal single receive task.

jbarrez
Star Contributor
Star Contributor
Ok, interesting find. I'll see what makes most sense in Activiti and fix it, because this is definitely a bug in my opinion.

aapthorp
Champ in-the-making
Champ in-the-making
Thanks. Will you add to Jira?

jbarrez
Star Contributor
Star Contributor
Well, I've done some investigation in the meantime. And indeed, it solves the problem for multi instance receive … but it breaks the tests for a lot of other stuff. For example for boundary events which are scopes (ie IS_SCOPE_ = true) and don't have a parent….

So currently I'm not really sure what a valid solution would be. I'll discuss it tomorrow with the rest of the team.

jbarrez
Star Contributor
Star Contributor
Okay, managed to fix it and make it work for all the other cases.

See http://jira.codehaus.org/browse/ACT-1586

So the 5.12 release will have this fixed!