Due to backwards compatibility issues, I sometimes have the problem that a FlowableException or more precisely an ELException can occur in my process. In that case, I want to send an email and afterwards terminate the process. Is this somehow possible?
I already experimented with mapException, but as I understand, it can only handle BPMNErrors. Is there a way to handle any Throwable? I also tried registering an event listener, which seems more promising, but how do I get the business key and the variables of the process that failed?
I’ve implemented something similar to this using mapException and an Event sub-process (https://flowable.org/docs/userguide/index.html#bpmnEventSubprocess).
Use a mapException element which matches all Java Exceptions:
<serviceTask id="servicetask1" name="Service Task" flowable:class="...">
<extensionElements>
<flowable:mapException errorCode="myErrorCode1"/>
</extensionElements>
</serviceTask>
And then have an event sub-process embedded in your process that has an error start event (matching your error code) and is interrupting. In the event subprocess you can send an email (and perform other business logic) and when the event subprocess ends the parent process will complete (as it was interrupting).
Thanks for the tip. On which serviceTask do I have to set mapException? On the error handler or on some serviceTask outside the subprocess?
Edit: Turns out, mapException is not even necessary, my subprocess is started by any exception with this definition:
<subProcess id="eventsubprocess1" name="Event sub Process" triggeredByEvent="true">
<serviceTask id="errorHandler" name="Error Handler" flowable:async="true" flowable:expression="#{globalErrorHandler.execute(execution)}"></serviceTask>
<startEvent id="errorstartevent1" name="Error start">
<errorEventDefinition errorRef="bla"></errorEventDefinition>
</startEvent>
<sequenceFlow id="flow18" sourceRef="errorstartevent1" targetRef="errorHandler"></sequenceFlow>
<endEvent id="endevent2" name="End"></endEvent>
<sequenceFlow id="flow19" sourceRef="errorHandler" targetRef="endevent2"></sequenceFlow>
</subProcess>
Edit 2: I was wrong, it doesn’t work. I forgot to switch back to a plain RuntimeException after testing with a BPMNError. The subprocess is not triggered by a RuntimeException.
The solution above works quite well. However, I would also like to log the stack trace of the exception that caused the error event. How would I go about doing that?
Edit: It doesn’t really work, see above.
The mapException would be on the serviceTask outside of the event subprocess. That is the ServiceTask that throws the Java exception in the parent process. The mapExecution will then map this to a BpmnError which then is caught by the event subprocess.
this works, but I don’t want to manually add this to every serviceTask in all my bpmns. Is there a way to configure this as a default for all service tasks?
Also, I would also like to have this behaviour for sequence flows with a conditionExpression and timer intermediateCatchEvents. Is this possible? I tried adding mapException like the following but it wasn’t triggered:
<sequenceFlow id="flow14" sourceRef="task1" targetRef="task2">
<extensionElements>
<flowable:mapException errorCode="bla" includeChildExceptions="true"/>
</extensionElements>
<conditionExpression xsi:type="tFormalExpression">${foo.bar()}</conditionExpression>
</sequenceFlow>
I’m afraid your usecase is more complex then my was, so I can’t really answer your questions. I only had a couple of ServiceTasks which needed the error handling.
Hopefully someone else has a litte more insight into how to achieve this.