Activity is null error


#1

Hi
I am testing some functionality and I did encounter this (for me) “strange” behaviour. I have the following process:

  • message intermediate throw event to the non-interrupting subprocess (send to A)
  • message start event non-interrupting (this is A)
  • message end event to interrupting subprocess (send to B)
  • message start event interrupting (this is B) this is where the error happens


Sample process: testKorelaceSubProcessVsSubprocess.bpmn (12.8 KB)

I know you should not use and correlate messages inside one process but I just want to understand what is happening here. Could someone please help me to understand why there is an error if the sub1 receive is not set to async?
There is also a different behaviour when the sync (on the sub1 receive) is on and off. The order of steps inside the main process will change.

This is the order when async (before) is set:

  • Main send (start)
  • Main send (end)
  • Main receive
  • Sub1 receive
  • Sub1 send
  • Sub2 receive (kill)

This is the order when no async is set (the Main receive is missing - the token did not come to the catch event)

  • Main send (start)
  • Sub1 receive
  • Sub1 send
  • Main send (end)
  • Sub2 receive (kill)

When I was reading about wait states and async before/after, I did not realize that the async will “let the others do they work and then it will kick in”.

So is the error caused by the token that is not at the receive event and when the “event” occurs “there is nobody to catch him”?
Thanks!
Lukas


#2

Hi Lukas,

The problem in the case without async continuations is related to the engine’s threading model (details at https://docs.camunda.org/manual/7.10/user-guide/process-engine/transactions-in-processes/).

Without async continuations, everything is executed sequentially by the thread that completes Before send (main). You can make an analogy to imperative code (here pseudo-code):

function before-send-main() {
  main-send();
  main-receive();
}

function main-send() {
  sub1-receive();
  sub1-send();
}

function sub1-send()
{
  interrupt-main-process();
  sub2-receive();
  before-end-interrupting();
}

function interrupt-main-process()
{
  // special stuff, read below :)
}

(all functions not declared are supposed to be no-ops)

So when the calls reach sub1-send, we have the following call stack:

sub1-send
main-send
before-send-main

Next, the ominous interrupt-main-process function is called. This function will now corrupt the data stored at the before-send-main stackframe. This is not something possible in any imperative language I know, but in BPMN engine terms this is the analogy to what happens. Corruption means that the process instance state is changed by such that the subsequent call to main-receive() is not meaningful anymore and results in undefined behavior (such as the exception that you get).

I hope that makes the problem clear. With async continuations, you avoid the situation where the interruption affects the currently executing part of the main process. That’s why the exception does not show there.

As these situations are rather tricky to understand and avoid, we discourage using message/signal events in the same process instance.

Cheers,
Thorben