Resolving incidents after execution

Hello camundians,

we’re currently trying to develop a method to restart a failed process instance via the API, prior to an activity where an incident happened. We would like to resolve the incident manually, and then restart the associated activity. We are not trying to handle the incident at the execution-time of the process.

We are doing this: Get the current incidents associated with the processInstanceId using
List<Incident> incidentList = runtimeService.createIncidentQuery().processInstanceId(processInstanceId).list();

The returned Incidents are of type IncidentEntity, which offers a resolve() method. However, this call yields a NullPointerException. As far as we understand from debugging, the execution Context required to do this is missing at that point.

If the activity is successfully restarted using the camunda cockpit, however, the incident seems to be resolved/deleted internally and disappears. Our expectation at this point would also actually be to find the incident as a HistoricIncident, but that list is empty.

Can someone please elaborate on the underlying concepts and point us at a solution that we could use?

Cheers

Hi @fbo,

could you publish your stack trace and code may be. On top of my head I can only tell you that resolve() method which you refer to has to be executed in command context, otherwise it will fail.

Cheers,
Askar

Hi @aakhmerov,

this is a simple code fragment trying to resolve all incidents of a (historic) processInstance:

List<Incident> incidentList = runtimeService.createIncidentQuery().processInstanceId(processInstanceId).list();
for (Incident inc : incidentList) {
  IncidentEntity entity = (IncidentEntity) inc;
  entity.resolve();
}

Could you explain to us the concept of the Command Context?

Cheers

@fbo,

is it executed inside of java delegate or what is the scope of execution? Could you please provide full class? Implementation of methods in the entities relies on availability of engine resources in “context”, like entity manager, etc. which is usually provided through command wrapping object. This is really more of internal engine concept and I am not sure we should go deep into it as it’s not intended to be used from outside of engine itself. And this probably will not be helpful information in your case.

Cheers,
Askar

As long as the process has incidents (and is still running), it is no Historic Instance.
For retrieving Historic Incidents you need the HistoryService, runtimeService always just returns stuff for running processes.

But as far as I know it’s not possible that a process has more than one Incident. (@Askar ?)

To execute your Code in command context you have to retrieve the Command Executer, e.g. like this:

CommandExecutor executor = Context.getProcessEngineConfiguration().getCommandExecutorTxRequired()

Then you have to wrap your code in a command, and execute this command with the executer. E.g.:

executor.execute((commandContext) -> {
  List<Incident> incidentList = runtimeService.createIncidentQuery().processInstanceId(processInstanceId).list();
  for (Incident inc : incidentList) {
    IncidentEntity entity = (IncidentEntity) inc;
    entity.resolve();
  }
}

Hope that helps!

Best regards,
Patrick

1 Like

Hi @patrick.schalk,

thanks for your answer.

I think I need to clarify: We are not within a running delegate when we want to do this. So I think we cannot get a valid CommandContext. Probably this solution is not viable here.

Let me take a step back and ask the question more generally: So far we have observed that when we simply restart an instance that yielded an incident the first time and it runs fine upon restarting, the incident still exists for that instance. It does not seem to be resolved automatically by the engine, and it never gets transformed into a HistoricIncident either. Unfortunately, the API documentation is very vague here. We do not want to handle the incident when it occurs.

We want to allow to restart such an instance - once the external, underlying problem has been fixed - from a suitable point before that incident, and resolve that incident if it does not re-occur. Preferably, such incidents should appear as HistoricIncidents after that. An idea would be to check for existing instances for the current processInstanceId in every delegate implementation, but that does not seem nice. How would you go about this?

Cheers

The given solution is for the case where you are not in the context of a delegate!
(You can always access the CommandExecuter in this way)

How do you “restart” the failed instance, what do you mean with this? Normally a successful retry of the failed instance should also delete the incident.

I think you just will have historic incidents if you really cancel a failed instance. (But I’m not sure)

Best Regards,
Patrick

Hi @patrick.schalk,

I’m from fbos team.
we need to “restart” a process instance programatically at any point of the execution by calling
runtimeService.createProcessInstanceModification(processInstanceId)
.startBeforeActivity(beforeActivity)
.execute();

In this case we need to mark all Incidents that occured in Activities after the “beforeActivity” as resolved, so that they won’t show up any more.

Currently, the codesnippet you provided throws a NullpointerException when we call
CommandExecutor executor = Context.getProcessEngineConfiguration().getCommandExecutorTxRequired();
here
Context.getProcessEngineConfiguration()
appears to be null

Best Regards

Hi Sebastian,

ok, and why do you want to to this by instance modification?
I think because of this the “old” incident will not be deleted.
Maybe moving the token to some task bevor will not delete the failed job. (But I’m not sure about this)
And when running again into the “failed” delegate, a new execution will be created.

I think a better way would be to increasing the retry counter of the Job.
(The same happens when you retry the Job manually in Cockpit)

Are you using a shared engine or a embedded engine?

Best Regards,
Patrick

+1 for finding an API solution over hacking with internal classes and commands.

Hi @patrick.schalk,

thanks for your answer.

Handling everything with retries is not an option for us, since we’re dealing with some send- and receive task patterns when talking to external services. So we need to get back to the send task in order to start over.

We could model this on BPMN level. But it would be a nice technical option to be able to jump back to a task earlier than where an incident was discovered without making it verbose on this level.Could you elaborate on your suggestion to “move the token” - how can this be done on API level?

And we’d still be grateful for some general information on the way incidents are treated by the engine:

  • When and how are they resolved?
  • When will incidents appear as historic incidents?

Cheers

1 Like