Retry only for Specific Exceptions otherwise Just Open Incident

I have a ServiceTask which I want to retry R12/PT15M on failure before automatically opening an incident but only for specific exception i.e. RetryException.

I dont want to do any retry if i get NonRetryException and would like it to open an incident immediately.

So, how can I tell the JobExecutor not to retry for NonRetryException exception?

@cute1boy retry configuration in camunda will retry for configured number if exception occurs. So If you want to retry for certain exceptions, you can use Spring retry template in your Java Delegate/ Listeners.

Take a look at this:

I think Spring Retry inside delegate wont be much useful as it will block job scheduler thread unless all spring retries exhaust and it will cause the task to fail.

Hi,

This thread (Fail Fast) may be of interest. Not precisely what you want, but might provide some inspiration…

regards

Rob

You can configure backoff strategy & number of retries

Hi,

I havent tested this, but perhaps this code snippet will work…

  try {
  	//
  	// Your code which throws Retry and Non Retry exceptions
  	//
  }
  catch (NonRetryException ex) {
  	//
  	// Set retry to zero and rethrow the exception. An incident is created due to the exception
  	Context.getJobExecutorContext().getCurrentJob().setRetries(0);	
  	throw ex;
  }

See if that works…

regards

Rob

That’s what I initially tried. However it doesn’t work :frowning:
It neither opens incident nor ends the retries.

I suspect the set retries to zero is not flushed to the db (or it does nothing)… In the mean time have a look at my fail fast pattern…

That fail fast helps in a different situation where we want to continue on a different path.
Here, we just want to open an incident, stay on the same node and wait for someone to take action.

Hi,

Thats true, however you could create an open incident and route the process to a user task pending operator intervention. Thus when the incident is resolved, an operator claims the user task for completion. The user task can then route back to the original service task.

So in summary, throwing a BpmnError gets around the retry strategy, use a user task to halt progress until the incident is resolved…

Perhaps not as elegant as you desire, but it is a feasible work around…

regards

Rob

@Niall @StephenOTT
do you have any suggestion on this issue?

Hi,

Late response, but it can be useful for others.
It is possible by overriding the FailedJobCommandFactory class. Create you own class that return a customized DefaultJobRetryCmd.
For example
@Component
public class MyFailedJobCommandFactory implements FailedJobCommandFactory {

    public MyFailedJobCommandFactory() {
    }

    @Override
    public Command<Object> getCommand(String jobId, Throwable exception) {
        return new MyJobRetryCmd(jobId, exception);
    }
}

Then, the MyJobRetryCmd could look like this
public class TalosJobRetryCmd extends DefaultJobRetryCmd {

public TalosJobRetryCmd(String jobId, Throwable exception) {
    super(jobId, exception);
}

    @Override
    protected FailedJobRetryConfiguration getFailedJobRetryConfiguration(JobEntity job, ActivityImpl activity) {
        // if exception is marked as no retry, we return a configuration with 1 retry, otherwise default    behaviour.
        if (this.exception instanceof NoRetryException) {
            return new FailedJobRetryConfiguration(1, List.of("PT0M"));
        } else {
            return super.getFailedJobRetryConfiguration(job, activity);
        }
    }
}

It is now just a matter to plug the factory into Camunda configuration.
public class MyFailedJobConfiguration extends SpringProcessEnginePlugin implements CamundaFailedJobConfiguration {

    private FailedJobCommandFactory failedJobCommandFactory;

    public MyFailedJobConfiguration(FailedJobCommandFactory failedJobCommandFactory) {
        this.failedJobCommandFactory = failedJobCommandFactory;
    }

    @Override
    public void preInit(ProcessEngineConfigurationImpl configuration) {

        if (configuration.getCustomPostBPMNParseListeners() == null) {
            configuration.setCustomPostBPMNParseListeners(new ArrayList<>());
        }

        configuration.getCustomPostBPMNParseListeners().add(new DefaultFailedJobParseListener());
        configuration.setFailedJobCommandFactory(failedJobCommandFactory);
    }
}

@Configuration
public class BpmnConfiguration {

    @Bean
    public static CamundaFailedJobConfiguration failedJobConfiguration(MyFailedJobCommandFactory myFailedJobCommandFactory) {
        return new MyFailedJobConfiguration(MyFailedJobCommandFactory);
    }
}

Regards,

Alain

2 Likes