Suspended tasks: intended use?

Hi,
usertasks have a boolean attribute ‘suspended’ ; mapping to, I guess, column ‘act_ru_task.suspension_state_’ .

My question : Can somebody give some more background on how this is supposed to work, especially in combination with suspending a process instance? Some things I’m pondering on:

  • if I suspend a process instance, are the usertasks automatically suspended as well?
  • if I suspend a task, will the API prohibit any more changes to this task (e.g complete a task), or is it our own responsibility to make these checks?

My ‘business reason’ I’m posting this question:
We have usecases where an external trigger (another system) should cause a process instance to be cancelled. So far, so good. But, sometimes, in real life, people make mistakes, or bad communication happens, and several minutes up to a few hours later, they revert the ‘cancellation’ in the other system.

If we immediately cancel a process instance on the first external trigger; we can never undo ’ this cancellation’. So I’m thinking about adding some time-dependant buffer, before actually cancelling the process instance.
But, while such a process instance is, let’s call it ‘pending cancellation’, I want to mask any usertasks from being visible / completeable by end-users (we use our own GUI, not the activiti webapp).

So, would I anger the Flowable spirits if I implement the following: ?

  • when I receive a ‘pending cancellation’ from the external system, I loop over all usertasks of our process-instance, and for-each update them and set suspended to ‘true’
  • I then program my GUI to hide suspended tasks (and if needed, to prohibit completing them)
  • when I receive a ‘undo cancellation’ , loop again, and set set suspended to ‘false’ again for each usertask
  • when no ‘undo cancellation’ is received, we could then program that after 12 hours, a real ‘cancel process instance’ is performed.
1 Like

Hi Pieter,

Yes, when a process instance is suspended, all the active user tasks will automatically become suspended. And the API validates that a user task is not suspended before it can be completed. When a user task is suspended and the complete action is invoked, an exception is thrown.

The use case you are describing would work. You don’t need to loop over all user tasks, when suspending a process instance all user tasks will be set to suspended automatically.

Best regards,

Tijs

Hi Tijs,
thanks already for the quick answer. Suspending the process instance seems the way to go for us, indeed.
Are there any other effects for suspending a process instance, next to suspending usertasks? Admitted, I could test all this myself, but I guess other forum might also be interested.
Some of the typical things that can still ‘cause progress’ in an instance, next to usertasks:

  • are timers halted (e.g an execution is waiting on a timer catching event) ?
  • will asynchronuous service tasks be suspended from execution?
  • can BPMN messages or BPMN signals be sent?

thanks for clarifying, that can help me judge the risk / impact on our process instances in general.

Hi Pieter,

Yes timers and asynchronous service task jobs are also suspended.
BPMN messages and BPMN signals are not processed for suspended process instances.

Best regards,

Tijs

Hi tijs,
when I try to suspend a asynchronous service task job, I have a problem that the process continue to go.

public class TestServiceTask implements JavaDelegate {
    ...
    @Override
    public void execute(DelegateExecution execution) {
          ...
          //produce a queue message

          runtimeService.suspendProcessInstanceById(execution.getProcessInstanceId());
    }    
}

I want to produce a queue message and then suspend this asynchronous service task in the TestServiceTask. I active the process when receiver response message.
How can I suspend asynchronous service task jobs?

Best regards,

Zhanyuerong

ACT_RU_SUSPENDED_JOB table have a data for this ServiceTask is suspended, but process continue to go.

Use ActivityBehavior instead of JavaDelegate, I have solved this problem that a asynchronous service task job is suspended but the process continue to go. But I have a new problem that TestServiceTask is repeated excution when I active the process, this is not what I expected, because it will produce repetitive queue messages.

Hi,
When I active the process, add code:
((FlowNode) execution.getCurrentFlowElement()).setBehavior(null);
my problem have been resolved. Thanks for Flowable, its awesome!

Best regards,

Zhanyuerong

Hi,
I am trying to suspend the process instance for user interaction to do action like accept or reject the process flow.
public class UserWorkflowTaskListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
runtimeService.suspendProcessInstanceById(execution.getProcessInstanceId());
}
}
but its give me an error
2019-09-23 16:48:01.524 ERROR 26851 — [enerContainer-1] o.f.c.e.impl.interceptor.CommandContext : Error while closing command context

java.lang.NullPointerException: null
	at com.rpa.core.process.tasklistener.UserWorkflowTaskListener.notify(UserWorkflowTaskListener.java:75) ~[classes/:na]
	at org.flowable.engine.impl.delegate.invocation.ExecutionListenerInvocation.invoke(ExecutionListenerInvocation.java:35) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.delegate.invocation.DelegateInvocation.proceed(DelegateInvocation.java:35) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.delegate.invocation.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:26) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.bpmn.helper.ClassDelegate.notify(ClassDelegate.java:99) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.bpmn.listener.ListenerNotificationHelper.executeExecutionListeners(ListenerNotificationHelper.java:79) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.agenda.AbstractOperation.executeExecutionListeners(AbstractOperation.java:78) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.agenda.AbstractOperation.executeExecutionListeners(AbstractOperation.java:69) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.agenda.ContinueProcessOperation.executeSynchronous(ContinueProcessOperation.java:141) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.agenda.ContinueProcessOperation.continueThroughFlowNode(ContinueProcessOperation.java:113) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.agenda.ContinueProcessOperation.continueThroughSequenceFlow(ContinueProcessOperation.java:311) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.agenda.ContinueProcessOperation.run(ContinueProcessOperation.java:79) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperation(CommandInvoker.java:88) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.interceptor.CommandInvoker.executeOperations(CommandInvoker.java:72) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:56) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.engine.impl.interceptor.BpmnOverrideContextInterceptor.execute(BpmnOverrideContextInterceptor.java:25) ~[flowable-engine-6.4.0.jar:6.4.0]
	at org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor.execute(TransactionContextInterceptor.java:53) ~[flowable-engine-common-6.4.0.jar:6.4.0]
	at org.flowable.common.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:71) ~[flowable-engine-common-6.4.0.jar:6.4.0]
	at org.flowable.common.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:49) [flowable-spring-common-6.4.0.jar:6.4.0]
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) [spring-tx-5.1.8.RELEASE.jar:5.1.8.RELEASE]
	at org.flowable.common.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:46) [flowable-spring-common-6.4.0.jar:6.4.0]
	at org.flowable.common.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30) [flowable-engine-common-6.4.0.jar:6.4.0]
	at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:56) [flowable-engine-common-6.4.0.jar:6.4.0]
	at org.flowable.common.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:51) [flowable-engine-common-6.4.0.jar:6.4.0]

Hey @rg2609 please post new topics instead of writing to an older topic.

The NPE that you have has nothing to do with suspending the task. I don’t know how you have the runtimeService defined in your UserWorkflowTaskListener. If you are autowiring it then you should not use class delegate for your listener. If you use class delegate Flowable will instantiate the class for you, it won’t go via the Spring dependency injection. You could either use a delegate expression or a normal expression to access your bean or access the runtime service via CommandContextUtil.getProcessEngineConfiguration().getRuntimeService().

Cheers,
Filip

P.S. There is no reason for you to crosspost (I saw that you posted on Stackoverflow)

1 Like