Skip Task in Camunda Using ProcessInstanceModification

HI,

I am trying to skip any task activity from process Execution and overriding ExecutionListener notify method for the task which need to get skipped.

@Override
public void notify(DelegateExecution execution) throws Exception {

		RuntimeService runtimeService = execution.getProcessEngineServices()
				.getRuntimeService();
		runtimeService.createProcessInstanceModification(execution.getProcessInstanceId())
		  .cancelActivityInstance(execution.getActivityInstanceId())
		  .cancelAllForActivity(execution.getCurrentActivityId())
		  .execute();
}

Indeed execution runs fine, but got the command Context null pointer exception, while closing the removeExecutionContext. Kindly assist with the following exception, how to handle so whole execution can be completed.

Exception Logs:


org.camunda.commons.logging.BaseLogger.logError ENGINE-16006 BPMN Stack Trace:
null (transition-notifiy-listener-start, ProcessInstance[0504953d-5033-11e7-8547-1078d2449d46], pa=Single Process Model)
UserTask_01mo44z
^
|
ExclusiveGateway_0uimsxk
^
|
UserTask_1460r79

13-Jun-2017 18:04:50.917 SEVERE [http-nio-8080-exec-9] org.camunda.commons.logging.BaseLogger.logError ENGINE-16004 Exception while closing command context: null
java.lang.NullPointerException
at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.getListeners(AbstractEventAtomicOperation.java:78)
at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:37)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:89)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:125)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:104)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:79)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:69)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:622)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:597)
at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:58)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:89)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:125)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:104)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:79)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:69)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:622)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:597)
at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:58)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:89)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:125)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:104)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:79)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:613)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:587)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionCreateScope.scopeCreated(PvmAtomicOperationTransitionCreateScope.java:34)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationCreateScope.execute(PvmAtomicOperationCreateScope.java:50)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationCreateScope.execute(PvmAtomicOperationCreateScope.java:24)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:89)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:125)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:112)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:79)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:613)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:587)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.take(PvmExecutionImpl.java:731)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionDestroyScope.execute(PvmAtomicOperationTransitionDestroyScope.java:85)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionDestroyScope.execute(PvmAtomicOperationTransitionDestroyScope.java:33)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:89)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:125)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:104)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:79)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:613)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:587)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerEnd$1.callback(PvmAtomicOperationTransitionNotifyListenerEnd.java:42)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerEnd$1.callback(PvmAtomicOperationTransitionNotifyListenerEnd.java:37)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueExecutionIfNotCanceled(PvmExecutionImpl.java:1942)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:1891)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerEnd.eventNotificationsCompleted(PvmAtomicOperationTransitionNotifyListenerEnd.java:37)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerEnd.eventNotificationsCompleted(PvmAtomicOperationTransitionNotifyListenerEnd.java:24)

Can someone provide any pointer/help to handle this case. It would really appreciate.

HI,

Is there any other alternative to achieve the same process?

One Solution:


The skip activity can be achieved with the following changes, in execution we need to provide next sequence activity.

@Override
public void notify(DelegateExecution execution) throws Exception {
RuntimeService runtimeService = execution.getProcessEngineServices()
.getRuntimeService();
runtimeService.createProcessInstanceModification(execution.getProcessInstanceId())
.startTransition(outTransitionId) //next sequence flow id
.cancelActivityInstance(execution.getActivityInstanceId())
.execute();

}

With startTransition or calling startBeforeActivity, the issue produced is execution of two sub-activities which result into multiple executionId of next task.
Is there any way out to stop one execution out of multiple execution ?

Any pointer will be helpful, kindly assist.

Hi @Karandeep_Singh,

you shouldn’t use the Process Instance Modification within the process instance. This could lead to undefined behavior.
If the skipping of the activities is part of your regular process then you should model it explicitly in your process.

Best regards,
Philipp

HI @Philipp_Ossler,

As defining process modeling explicitly, we have to deploy a different bpmn altogether. I have the requirement not for current instance, but can able to modify any existing instance.
For this purpose, I am looking the feasibility.

Kindly provide any reference to skip the activity in the flow.

Hi @Karandeep_Singh,

I’m sorry but I don’t understand your use case completely. Please describe it a bit more and provide an example.

Best regards,
Philipp

1 Like

HI @Philipp_Ossler,

In detailed scenario, I need to skip any activity(userTask/serviceTask) from the execution of process Instances in camunda. These process execution can be of former Instances or may be for current instances. Majority, these instances are former instances of deployed bpmn process.

e.g, Suppose we have the following bpmn process. In the process execution, we don’t need to apply the send invoice task. We need to skip the following task and our process will get executed to the next activity in the flow.
Is modification can be achieved using ProcessInstanceModification or any other alternative ?

I am trying for this solution. As mentioned above, but we don’t have to use current process Modification , then with any former process Instance how we skip that activity of functionality from same bpmn.

orderApproval.bpmn (6.0 KB)

Hi @Karandeep_Singh,

if you need to skip activities in a running process instance then you can use the process instance modification api (via Java, Rest or Cockpit EE).
If this is part of your regular process (and not an incident) then you should model in the process (e.g. using an exclusive gateway before the activity which can be skipped). If necessary, you can migrate the running process instances to a new process definition.

Note that it is not possible to run the modification within the process instance you want to modify.

Does this help you?

Best regards,
Philipp

Yes, work around with my problem statement through process modification REST API.

Thank you, @Philipp_Ossler

Hi karandeep Singh,
Could you please let me know how you have solved the skip task of the current process instance ? It would be a great help

thanks
Vamsi

HI Vamsi,

if I understood correctly, you need to skip your next task(user,service, etc) in current instance of ProcessDefinition.

There are two ways:

  1. Complete the next execution task using the Camunda REST endpoint for task completion. Brief explanation provided here:
    Example of completing a User Task with REST API

  2. Another way is providing following classes in Camunda Project:
    SkipExecutionListener and SkipTaskListener implemented ExecutionListener and TaskListener respectively.

Code Snippet:

public class SkipTaskListener implements TaskListener {

@Override
public void notify(DelegateTask delegateTask) {

		TaskService taskService = delegateTask.getExecution().getProcessEngineServices()
				.getTaskService();
		try {
			ExecutionEntity executionEntity = (ExecutionEntity) delegateTask.getExecution();
			String taskId = executionEntity.getTasks().get(0).getId();
			taskService.complete(taskId);
		}  catch (AuthorizationException e) {
			throw e;
		} catch (NullPointerException ne){
			throw ne;
		}
}

}

//Process Modification Approach
public class SkipExecutionListener implements ExecutionListener {

@Override
public void notify(DelegateExecution execution) throws Exception {
		RuntimeService runtimeService = execution.getProcessEngineServices().getRuntimeService();
		
		TaskService taskService = execution.getProcessEngineServices()
				.getTaskService();
		
		
	try{
		String outTransitionId = null;
			PvmActivity activity = ((ActivityExecution)execution).getActivity();
			List<PvmTransition> outgoingTransitions =   (activity.getOutgoingTransitions());
			
			if(null!= outgoingTransitions && !outgoingTransitions.isEmpty()){
				ListIterator<E> itr = (ListIterator<E>) outgoingTransitions.listIterator();
				
				while(itr.hasNext()){
					TransitionImpl outTransition = (TransitionImpl) itr.next();
					//TODO check outTransition for default flow , then condition of forward execution
					if(null != outTransition){
						outTransitionId =  outTransition.getId();
						break;
					}
				}
			}
			try {
				runtimeService.createProcessInstanceModification(execution.getProcessInstanceId())
				.startTransition(outTransitionId)
				.cancelActivityInstance(execution.getActivityInstanceId())
				.execute();

		      }  catch (AuthorizationException e) {
		        throw e;
		      }
		} catch (Exception e){
			throw e;
		}
		
	}

}

Thanks Karandeep. Could you please provide any sample bpmn which has integrated this code? If possible could you please share a one.

Also in the second approach, we can use any one right (either the TaskListener or ExecutionListener)? Am i correct?

HI Vamsi,

Yes, you can use anyone. ProcessModification process have certain limitations please use carefully or you can end up into dead state if BPMN model is not properly designed.

SKIP task always work well if you have back and forth flow, currently I don’t have any sample bpmn but you can implement on sample invoice flow.

Please include, listener class on the task where it needed to be executed.
Example,
<camunda:taskListener class=“org.camunda.bpm.listener.SkipTaskListener” event=“create” />

Thanks,
Karandeep

How to include SkipTaskListener through cammunda bpmn modeller? Is it possible?
I am able to add ExecutionListener through the GUI but not TaskListener. Are the TaskListeners specific to only usertasks? or i can add it for service tasks too ? Any pointers here Karandeep?

I think using TaskListener i can skip only user tasks but not service tasks right? If i use processmodification on service task, it is creating 2 different executions i guess from the logs

Hi Karan,

If possible, Could you please provide the pointers on how to overcome the multiple executions after the skipped task.

Thanks
Vamsi