Suspending a process instance unconditionally

How do i do that from within a service task? I’ve seen multiple threads about it, e.g. Process Instance suspend and activate - #3 by Urvashi_Prasad or Suspended processes continue to run, and can't keep track of their progress - #5 by Webcyberrob, but no explanation.

Suppose, for whatever reason i come to a certain point in the process that currently executing process instance must be suspended (e.g. after finishing currently executing service task). I tried using RuntimeService#suspendProcessInstanceById from both execution listener and service task itself, but none of it worked and the process instance continued its execution, after being supposedly suspended, calling other service tasks. It was done in debug mode, so no concurrency was present.

So i wonder, what is the correct way to gracefully but unconditionally stop the process instance from executing, to be able to start it again from where it was stopped at some undetermined point in time in future?

This method would generally be used via the REST API not by the process instance itself.
Can you explain the use case for wanting to have a process instance suspend itself?

This method would generally be used via the REST API

Excuse me, why then it’s available for CDI injection within java code of the service tasks?

Can you explain the use case

Conditions arise that prevent execution of the process instance at a particular moment in time, but they will be resolved at some undetermined point in time in future. These conditions are not BPMN errors or whatever, they are completely unrelated to BPM engine and shouldn’t cause any compensation behaviour or error flows, but can only be determined locally, by the currently executing task and not externally, that’s why using any kind of remote API is not applicable. The process instance must stop to be manually continued later.

Suspending a process instance is a prefectly normal thing (and only a matter of setting a flag in the database), so i don’t really understand why it is a big deal to explain.

It can certainly be used directly as java - i was just expressing the most common use-case in which a source (external to the process instance itself) is responsible for suspending or activating an instance. It’s not always the case that an instance suspends itself, because it then becomes more complicated to re-activate itself because a process instance being suspended means that no jobs or tasks will be completed for that instance and so it cannot decided to activate itself.

Hope that clarifies why i was questioning the use case you have.

So the answer to my question is essentiall “no”? The process instance can’t suspend itself no matter what?

It can, but it cant reactivate itself.

1 Like

It can

How?

I’ll see if i can create an example for you.

1 Like

Much appreciated! You need not make it too complicated, i’m able to read javadocs and decompiled code ;), just point me at the right direction.

Here’s an example i created using spring boot

2 Likes

Ah, so i must use RuntimeService#updateProcessInstanceSuspensionState instead? Lemme check if it helps.

There’s a little more to it - you also have to take into account where the transaction boundaries are.

Hmm, using updateProcessInstanceSuspensionState doesn’t work as well.

where the transaction boundaries are

Do you mean that the engine will complete transaction regardless of the suspension state?

suspension means that further jobs will will not be picked up by the engine so once the suspension commits to the DB any further jobs will not be picked up. which is why i added asynchronous before on the script tasks to ensure that after a suspension it would not continue the process.

In my case i use synchronous java delegate service tasks in a simple workflow of two such consecutive tasks. Even that i invoke updateProcessInstanceSuspensionState in the first task, the second still executes.

So adding a transaction boundary before the second service task should suspend the instance then. If your whole process in entirely synchronous then suspension will not work.

2 Likes

Ah, i see now. Why is that? Is there some docs i can read about this behaviour? In other words, if i don’t use anything in terms of transaction management (for my tests), - i won’t be able to do what i want?

You can check out this section of the docs for more detailed information.

No, i mean, something about why i can’t suspend a synchronous process? i can’t see any logical reason for that :).

It’s just because the engine never wanted to stop a thread in-flight, it would cause havoc. instead if you want to. it will only suspend an instance if it’s found a safe wait sate.

suspending a synchronous process would mean that he engine would have to create a state between what the user has defined as a transaction (i.e. the number of task executed between 2 transaction boundaries). Transaction boundaries are defined in design time and not runtime.