How to avoid all activities to be rolled back on Flowable Exception

I have a subprocess in which a scriptTask has been added. If the script has a syntax error, the engine stops and everything is rolled back. The process instance is null.

What do i need to do to not roll back but only end with the last activity (Script) completed with the appropriate exception.

For example in my case.
problem evaluating script: ReferenceError: “x” is not defined in at line number 15

Hi,
you can make script task asynchronous. In that case process is started and a new job is created. The job execution fails (3 attempts) and is sent to dead letter job queue.
more info https://flowable.org/docs/userguide/index.html#bpmnConcurrencyAndTransactions

Regards
Martin

Great. Thanks for the quick response Martin.

We are using Java API to define the process. What would be the Java code syntax to achieve the extensionElements. We have included the below code

<serviceTask id="failingServiceTask" flowable:async="true"
    flowable:class="org.flowable.engine.test.jobexecutor.RetryFailingDelegate">

    <extensionElements>
        <flowable:failedJobRetryTimeCycle>R5/PT7M</flowable:failedJobRetryTimeCycle>
    </extensionElements>
</serviceTask>
				ExtensionElement ee = new ExtensionElement();
				ExtensionAttribute ea = new ExtensionAttribute();
				ea.setNamespace("flowable");
				ea.setName("failedJobRetryTimeCycle");
				ea.setValue("R1");
				ee.addAttribute(ea);
				scriptTask.addExtensionElement(ee);

This is the Script definition on publish. We have listeners added, but the extension for retry is missing. Need to know where are we going wrong

  <scriptTask id="Script_345c8416-e3cb-4c21-b807-2e8c55719344" flowable:async="true" scriptFormat="JavaScript" flowable:resultVariable="Script_345c8416-e3cb-4c21-b807-2e8c55719344" flowable:autoStoreVariables="true">
    <extensionElements>
      <flowable:executionListener event="start" class="com.wipro.platform.has.process.listener.ScriptStartExecutionListener"/>
      <flowable:executionListener event="end" class="com.wipro.platform.has.process.listener.ScriptEndExecutionListener"/>
    </extensionElements>
    <script><![CDATA[/* This is the initial input to the script, and it is the output of
  • the last activity. Please do not change it.
    */
    var input_to_script = JSON.parse(LAST_ACTIVITY_OUTPUT);

// Your script code goes here

/* Please assign your script output here, and do not change the

  • variable name.
    */
    output_of_script = “Hello World”]]>

Martin, Thanks

Made the script task asynchronous. Figured it out how to modify count of failed retry
scriptTask.setFailedJobRetryTimeCycleValue(“R0/”);

I want to end with a Java Delegate to be called which builds my final response for the process being executed. Not able to achieve that. Set BoundaryEvents using the needed definition but not getting called. I have shared the XML

scriptTask.setBoundaryEvents(…)

<?xml version='1.0' encoding='UTF-8'?>



<flowable:executionListener event=“end” class=“com.wipro.platform.has.process.listener.TaskEndExecutionListener”/>




<flowable:field name=“requestMethod”>
flowable:expression</flowable:expression>
</flowable:field>
<flowable:field name=“requestUrl”>
flowable:expression</flowable:expression>
</flowable:field>
<flowable:field name=“requestBody”>
flowable:expression</flowable:expression>
</flowable:field>
<flowable:field name=“requestHeaders”>
flowable:expression</flowable:expression>
</flowable:field>
<flowable:field name=“resultVariablePrefix”>
flowable:string</flowable:string>
</flowable:field>
<flowable:field name=“saveResponseParameters”>
flowable:string</flowable:string>
</flowable:field>
<flowable:field name=“requestTimeout”>
flowable:string</flowable:string>
</flowable:field>
<flowable:field name=“failStatusCodes”>
flowable:string</flowable:string>
</flowable:field>
<flowable:field name=“handleStatusCodes”>
flowable:string</flowable:string>
</flowable:field>
<flowable:field name=“saveRequestVariables”>
flowable:string</flowable:string>
</flowable:field>
<flowable:field name=“ignoreException”>
flowable:string</flowable:string>
</flowable:field>
<flowable:executionListener event=“start” class=“com.wipro.platform.has.process.listener.HttpStartExecutionListener”/>
<flowable:executionListener event=“end” class=“com.wipro.platform.has.process.listener.HttpEndExecutionListener”/>











<bpmndi:BPMNDiagram id=“BPMNDiagram_P_c0abf0ee-4261-4150-a6d2-fd6e09480059”>
<bpmndi:BPMNPlane bpmnElement=“P_c0abf0ee-4261-4150-a6d2-fd6e09480059” id=“BPMNPlane_P_c0abf0ee-4261-4150-a6d2-fd6e09480059”/>
</bpmndi:BPMNDiagram>

Hi there could be a problem with the encapsulation of extension elements.
The pull request:


should put the elements into correct place.

Regards
Martin

Thanks Martin

Our current concern is on how to instruct Flowable to call a JavaDelegate when an asynchronous activity fails. For example, a ScriptTask added with a script that has syntax error. The process execution stops. But how to get that failure response and also instruct flowable via a Boundary Event to call a Java Delegate

We are creating processs and executing them using the Java API of flowable. Not using flowable UI

This is the syntax to create a Script Task

				ScriptTask scriptTask = new ScriptTask();
				scriptTask.setId(scriptId);
				scriptTask.setScript(aActivity.getScript());
				scriptTask.setScriptFormat(scriptFormat);
				scriptTask.setAutoStoreVariables(true);
				scriptTask.setResultVariable(scriptId);
				scriptTask.setExecutionListeners(lList);
				scriptTask.setAsynchronous(true);
				scriptTask.setFailedJobRetryTimeCycleValue("R0/");
				scriptTask.setBoundaryEvents(createBoundaryEvents(scriptTask, subProcess));

This is part of the process XML that gets defined

R0/



<flowable:executionListener event=“end” class=“com.wipro.platform.has.process.listener.TaskEndExecutionListener”/>


Hi,

The job is failed ad added to dead letter queue. You can find it there.

Regards
Martin

Thanks Martin,

Finding it dead letter queue is fine and we have done that. We can read the dead letter queue to get the Exception message but the read call needs to be tied automatically to the end of execution. Flowable is abruptly stopping and due to that we have the following concerns

  1. On a java script error, is it possible for flowable not to abruptly stop process execution and rather call a Boundary Event. We have attached a boundary event to the sub process within which the script is being executed. Boundary event gets called on HttpTask failure but not on Script failures

We have listeners attached to activities. Script also has a few listeners. The listeners have been implemented by using implements ExecutionListener.
We see a class called org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener. What is this for and how can we use it

  1. In the dead letter queue, how to know for which activity it failed. What is the relation in the DB schema of flowable that will lead us to the activity which failed. How to get the same via Java SDK

  2. Flowable abruptly ends with the exception in dead letter queue. All History variables are not committed. Even the updates done to our entities are lost. We can control this via REQUIRES_NEW or other transaction type though.

  3. Even the DB calls made to update entities defined by application are being rolled back. These DB calls are made in the end listeners attached to every activity.

  4. On failures, at most times the Update Table (For an entity defined in application) gets locked and a deadlock is reached.

Before diving into the points, one thing to note is that Flowable will transactionally move the process execution from one stable state to another stable state. If an exception happens during job execution, the engine will roll back to the previous stable state.

  1. How did you configure that boundary event? You probably will need to configure the script to throw a BpmnError when an exception is catched.

  2. The deadletter job has executionId, processInstanceId and processDefinitionId. The executionId can be used to fetched the Execution which points to the activity where the job failed.

  3. That is most likely because the transaction has been rolled back to the previous stable state.

  4. Correct, everything part of the same transaction will be rolled back.

  5. Can you elaborate on that, not sure what you mean?

Hi Joram, really appreciate the quick response. I was off work and replying as soon as i joined

  1. Added a Boundary event to the Subprocess within which all the activities are tied. Looks like a good suggestion to have the try and catch in the Script itself and makes sense. Leave it to the designer of the process to handle the flow that follows the script

  2. How is this done using SDK. Which manager do we use to get this? Is it the same that is used to read DeadLetterQueues

  3. We have start and end listeners attached to every activity in the flow. In the end listener if we attempt to update a table defined by the application with the consolidated response of the process, that table is getting locked and the process is stuck and all other process executions attempted are stuck as well. We are not able to Autowire our beans into the Listener classes. We have used the application context to get the bean by its name and calling the required implementation for the update. I assume since each end listener gets the bean from a pool, the update is happening in a different transaction context

We have made the Start Event of the Subprocess as Asynchronous. Would you suggest that we made each activity as Asynchronous.

Thank
Sunil

Hi

Kindly revert on my earlier post. Also i need to understand how to get the message from the script failure in case we add try and catch

The code of the script is below. We do have a log that gets printed and is detailed below the script, but how to get the same info via program (SDK). End Listeners attached to script are not called. BoundaryDelegate attached to sub process gets called but how to extract the exception as displayed in the log below

In the below script, x is added to cause an exception for demo purpose

try {
var input_to_script = JSON.parse(LAST_ACTIVITY_OUTPUT);
output_of_script = "Good Morning " + x;
} catch (err) {
var BpmnError = Packages.org.flowable.engine.delegate.BpmnError;
throw new BpmnError(err.message);
}

WARN org.flowable.engine.impl.bpmn.behavior.ScriptTaskActivityBehavior [85] - Exception while executing Script_a52eb3b0-d398-4e7b-b7f0-75eca7ff9965 : problem evaluating script: org.flowable.engine.delegate.BpmnError: in at line number 19 at column number 0

Hi,

Does
org.flowable.job.api.JobInfo#getExceptionMessage
work for you?

Regards
Martin

Martin,

The BoundaryEventDelegate, the delegate attached to the Sub Process is called. Now the interface we have is as below.

public void execute(DelegateExecution execution) {

In the above implementation, How to use the SDK to get the information of org.flowable.job.api.JobInfo# getExceptionMessage

What is the table name in which this data may be available? all the act_ru_* tables seem to be empty at the end of execution.

engine.getXXX, which service do we use to get org.flowable.job.api.JobInfo# getExceptionMessage

And from that service, which method

Sunil

Use the managementService and then use one of the jobQueries. The returned results will have the exception message.

If they are empty, it means the process has rolled back or the process has been completed.

engine.getManagementService#createDeadLetterJobQuery()

Thanks Joram

If we throw BPMNError in the JavaScript, there is no data in DeadLetterQueue for the process instance. If we avoid the try and catch, we do have an entry in DeadLetterQueue. But then all the variables are lost. There was a suggestion to add try and catch inside the script and throw BPMN error. We did that, but now we do not have any information on the error. The Sequence has reached the boundary delegate we added to the sub process, but how to get the reason for failure (There is no data in dead letter queue, meaning to say there is no row for the process instance id in act_ru_deadletter_job)