Retry javadelegate which is triggerable

Hi

We are currently using version 6.4.2 of flowable engine and have an issue with the retry logic.

We implemented a javadelegate which is triggerable and marked as asynchronous and triggerable in the model.

The execute method of the delegate sends a message to a message queue (rabbitmq). Another application then processes this message and sends a message back to our flowable service.

When it receives a message for the execution an async trigger is called for the specific execution. In case of failure the trigger propagates an exception so the service task goes to the deadletter-job queue of flowable.

The problem is when we use the move-job action to retry the job only the trigger part is executed and not the execute part so the job is actually not retried just the trigger.

To make it a bit more clearer

We have a javadelegate which is marked asynchronous & triggerable and post a message to rabbitmq.
Another java process handles the message on this queue and send a message back to flowable. This message contains success/failure.

On failure we thought we could use triggerasync and fail the servicetask by throwing a custom exception.

We do have a deadletter-job when we do this but this job only retries the trigger part and not the reexecution of the full servicetask.

When using a triggerable service task, there’s two jobs: one for the sending and one for the receving. So what you’re saying is that the first job succeeded, but the second one failed?

The job handling indeed takes that job and retries it (as the trigger failed, not the first job). For this particular use case, you probably would need to delete the second job and (re)create the original job programmatically.

We fixed it by calling moveExecutionToActivityId with the same executionId and elementId. (So in fact we restart the task)

If we want to retry 3 times with some interval, this u need to call that method using some Java timer !!!

Instead I broke it as below:
triggerable service = service1 + user_task + service2 (service 2 throws error and is caught by a boundary error that routes the handle with an intermediate timer to the first job so that the first job can retry as per required count)

You could have added the syntax as well on how to use this method. It took me 1 whole day to figure out the syntax without much examples available over the Internet. Adding it,

ActivityInstance activity = processEngine.getRuntimeService().createActivityInstanceQuery()
                        .processInstanceId(procInstId)
                        .activityId(activityId)
                        .singleResult();

processEngine.getRuntimeService().createChangeActivityStateBuilder()
                .moveExecutionToActivityId(activity.getExecutionId(), activity.getActivityId())
                .changeState();

@joram @martin.grofcik

As a followup question, when calling #moveExecutionToActivityId(executionId, activityId)? Since we are not passing procInstanceId (but the executionId), is executionId unique across all the processInstances?

Please confirm this would not result in ambiguity issues.

yes, execution is unique in the whole engine.

1 Like