Skip activity for failed job - null activityInstanceId

663 views
Skip to first unread message

j...@atlas.cz

unread,
May 25, 2015, 9:18:31 AM5/25/15
to camunda-...@googlegroups.com
Hi,

i have process, where more-less all activities are async-before, some also async-after. Most of them are serviceTasks with java behind, calling external systems.
I have own dashboard and want to put there SKIP button for failed job, which should simply skip first activity for job and continue with next one.

I realized, that in many cases i have null in act_ru_execution.act_inst_id_

Hence i end up with following:

public class SkipActivityResource extends AbstractCockpitPluginResource {

   
private String jobId;
   
   
public SkipActivityResource(String engineName, String jobId) {
       
super(engineName);
       
this.jobId = jobId;
   
}

   
@POST
   
public void skipActivity() {
       
Job job = getProcessEngine().getManagementService().createJobQuery().jobId(jobId).singleResult();
       
String processInstanceId = job.getProcessInstanceId();
   
     
ExecutionEntity execution =
(ExecutionEntity)getProcessEngine().getRuntimeService().createExecutionQuery().executionId(job.getExecutionId()).singleResult();  
     
       
String activityId = execution.getActivityId();
       
String activityInstanceId = execution.getActivityInstanceId();
       
       
if (activityInstanceId != null) {
            getProcessEngine
().getRuntimeService().createProcessInstanceModification(processInstanceId)
               
.startAfterActivity(activityId, activityInstanceId)
               
.cancelActivityInstance(activityInstanceId)
               
.execute();    
       
} else {
            getProcessEngine
().getRuntimeService().createProcessInstanceModification(processInstanceId)
           
.cancelAllForActivity(activityId)
           
.startAfterActivity(activityId)
           
.execute();
       
}
               
   
}
}

is it correct?
Can it be, that else-case will cancel more than one execution?

When is activityInstanceId actually filled and when is it null ?

thank you
best regards
jano

thorben....@camunda.com

unread,
May 26, 2015, 3:15:18 AM5/26/15
to camunda-...@googlegroups.com
Hi Jano,

The field activityInstanceId is used to build the activity instance tree that can be retrieved with RuntimeService#getActivityInstance.

This tree differentiates between activity instances and transition instances. Activity instances are instances of activities that are actually being executed at the moment, while transition instances are instances of a transition to an activity (e.g. async before, async after). Roughly speaking, transition instances are created from executions where activity instance id is null while for the other executions activity instances are created.

How to deal with transition instances then? The ProcessInstanceModificationBuilder has a method #cancelTransitionInstance that takes a transition instance id. The transition instance id is equal to the id of the execution performing the transition.

Cheers,
Thorben

j...@atlas.cz

unread,
Jun 22, 2015, 1:18:37 PM6/22/15
to camunda-...@googlegroups.com
Hello Thorben,

today i tried to finish work on this, but i got into troble again.

So i used engine.getRuntimeService().getActivityInstance(processInstanceId); to get tree and looked up for transitionInstanceId, which refers to executionId, where i want do a skip.

So i simply did

            engine.getRuntimeService().createProcessInstanceModification(processInstanceId)  
               
.startAfterActivity(activityId, transitionInstance.getParentActivityInstanceId())
               
.cancelTransitionInstance(transitionInstance.getId())
               
.execute();

but i have this error:

java.lang.NullPointerException
    at
org
.camunda.bpm.engine.impl.cmd.TransitionInstanceCancellationCmd.determineSourceInstanceExecution(TransitionInstanceCancellationCmd.java:43)
    at org
.camunda.bpm.engine.impl.cmd.AbstractInstanceCancellationCmd.execute(AbstractInstanceCancellationCmd.java:33)
    at org
.camunda.bpm.engine.impl.cmd.AbstractInstanceCancellationCmd.execute(AbstractInstanceCancellationCmd.java:26)
    at org
.camunda.bpm.engine.impl.cmd.ModifyProcessInstanceCmd.execute(ModifyProcessInstanceCmd.java:52)
    at org
.camunda.bpm.engine.impl.cmd.ModifyProcessInstanceCmd.execute(ModifyProcessInstanceCmd.java:30)
    at org
.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
    at org
.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:97)
    at org
.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42)
    at org
.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at org
.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40)
    at org
.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:32)
   
 at
org
.camunda.bpm.engine.impl.ProcessInstanceModificationBuilderImpl.execute(ProcessInstanceModificationBuilderImpl.java:219)
   
 at
org
.camunda.bpm.engine.impl.ProcessInstanceModificationBuilderImpl.execute(ProcessInstanceModificationBuilderImpl.java:210)

Before execution tree is:
└── SkipRetrySampleProcess:1:3=>18
   
└── SubProcess_1#multiInstanceBody=>SubProcess_1#multiInstanceBody:40
       
├── SubProcess_1=>SubProcess_1:52
       
  └── transition to/from ServiceTask_2:51
       
└── SubProcess_1=>SubProcess_1:58
           
└── transition to/from ServiceTask_2:57

While searching for instance to cancel it's already
└── SkipRetrySampleProcess:1:3=>18
   
└── SubProcess_1#multiInstanceBody=>SubProcess_1#multiInstanceBody:40
       
├── SubProcess_1=>SubProcess_1:52
       
  ├── transition to/from ServiceTask_2:80
       
  └── transition to/from EndEvent_2:81
       
└── SubProcess_1=>SubProcess_1:58
           
└── transition to/from ServiceTask_2:57

Why was "transition to/from ServiceTask_2:51" replaced by "transition to/from ServiceTask_2:80"?

Tested with 7.3.1ee.

My sample process def: skipRetrySample.bpmn

thorben....@camunda.com

unread,
Jun 23, 2015, 3:13:04 AM6/23/15
to camunda-...@googlegroups.com
Hi Jano,

That's a known issue we are going to fix with an upcoming patch release. See [1] for the JIRA ticket. Other than splitting the operations into two modifications (which looses atomicity), I am not aware of a good workaround.

Cheers,
Thorben

[1] https://app.camunda.com/jira/browse/CAM-4090

j...@atlas.cz

unread,
Jul 3, 2015, 6:59:11 AM7/3/15
to camunda-...@googlegroups.com
Hello Thorben,

with 7.3.2 it looks fine. I'm unsure, if i correctly implemented functionality to skip one failed activity. Hence i would like to ask two questions:

1) when i want to skip activity, where process is stopped (incident exists), is it always so, that execution.getActivityInstanceId() returns null?

2) in ActivityInstance tree i found transitionInstance for execution where i want to do a skip. Is code below correct way or are there some special cases to handle? I'm also unsure about ancestoreActivityInstanceId - what to use there?

engine.getRuntimeService().createProcessInstanceModification(processInstanceId)
   
.startAfterActivity(activityId, transitionInstance.getParentActivityInstanceId()) // FIXME how to find correct common ancestor? Is this correct?
   
.cancelTransitionInstance(transitionInstance.getId())
   
.execute();

thank you a lot
best regards
jano

thorben....@camunda.com

unread,
Jul 3, 2015, 7:18:15 AM7/3/15
to camunda-...@googlegroups.com
Hi Jano,

1) Yes, that is correct. That's how we differeniate an activity instance (id is set) from a transition instance (id is not set). When an execution is waiting to execute a job, that is represented as a transition instance and this is the case when there is an incident.
2) Your code looks fine. For example, when the transition is executed in a sub process, transitionInstance.getParentActivityInstanceId() returns the activity instance id of the sub process instance the transition is contained in.

Cheers,
Thorben
Reply all
Reply to author
Forward
0 new messages