Global error handling & transactions

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Active Member

Global error handling & transactions

Hello,

I am trying to implement a feature but I'm not sure if it is technically possible.
I would like all my process instances to have a has_error variable which just tracks wether a technical error (which I can catch) occurred on the process and let the transaction rollback as it should and let the client handle it.
But how can I save this variable and let the transaction rollback ? Is there a way to force a new transaction just to commit this process instance variable ?
Thanks !
6 Replies
Established Member II

Re: Global error handling & transactions

Hi stephane cosmr ,

This is a good question. I would recommend you to read chapter 7 in the book Activiti in Action.

In order to catch technical error, you would need 'Java Service Task' that implements ActivitiBehavior interface. You can read more about it in chapter 7, section 3 "Implementing error handing using Java logic". 

From your requirement,

I would like all my process instances to have a has_error variable which just tracks wether a technical error (which I can catch) occurred on the process

you would need to implement your services by Activiti's Java Service Task and specify how it should handle error. See user guide for how to handle error within Java Service Task here Activiti User Guide . 

Why do you need 'has_error' variable? What is its purpose?

and let the transaction rollback as it should and let the client handle it.

Activiti by default already handles this by some extent. If you have a diagram such as one below

If the flow was going 1 -> 2 -> 3 -> 4 and failed at service 'Find customer' for some reason, the transaction will be automatically rolled back to 2, which is the user task 'Provide additional customer information'. In case you want to model more complex error handling, such as if 'Find customer' service encounters error, flow to an admin task to check error and fix it, you then can use the 'Java service task error handling' method combining with BPMN Error Handling modelling (read Chapter 7.2). 

But how can I save this variable and let the transaction rollback ? Is there a way to force a new transaction just to commit this process instance variable ?

Again, I don't think you would need this variable. Read chapter 7 to understand how Activiti error handling works. 

I would suggest you to create a unit test to experiment and if it doesn't work, send the unit test to us.

Hope this helps,

Thanks,

Thong Huynh

Highlighted
Active Member

Re: Global error handling & transactions

Hi Thong,

Thank you for your answer !
I understand how I could implement error handling in a standard way.
Actually, I want to propose to my users an interface to let them create their own simple workflows. Activity should be invisible to them. From there I need a view which list their process instances and show if there is some errors to eventually review the process design themselves. In a nutshell, all of my generated workflows needs to inherit common properties/behaviour to integrate them in a common interface.
I can point out three cases where errors can occur :
  1. In my java logic (listeners, custom beans ...)
  2. Script Task
  3. Gateways no outgoing sequence
I came with the following idea. I am able for these three cases to catch the error and create a BpmnError which actually represent a TECHNICAL_ERROR.
  1. In my java logic (listeners, custom beans ...) => Simple try catch do the job
  2. Script Task => Encapsulate every scripts in a common fixed try catch
  3. Gateways => Using my own evaluation logic through a custom bean
Then I thought I would be able to find a way to update the process after catching the BpmnError and re raise an exception to let the process rollback, but the more I am trying the less I think It is possible.
Here is what would like my "base workflow" which implements common behaviours. "My Process 1" represents the workflow designed by my user.
Another solution would be to let the client update the process instance itself with appropriate variables. 
  1. Client complete Task 
  2. If Client receive other than 2XX
  3. Then Client call activiti-rest to update process instance variables.
It is clearly not the dreamed design but I think there is no good solution to manage it fully server side if I dont want to use a total anti pattern.
I am aware this post is not intended to get a clear answer, but if you think you have any good inputs for this kind of problematics, it would be really helpful. Smiley Happy
Thank you for your help.
Highlighted
Established Member II

Re: Global error handling & transactions

Hi stephane cosmr ,

Thank you very much for writing up a great description of your use case. Appreciate it.

Before jumping to solution talking, let's make sure that we are on the same page for the problem statement.

You said:

Then I thought I would be able to find a way to update the process after catching the BpmnError and re raise an exception to let the process rollback, but the more I am trying the less I think It is possible.

It seems like this is your problem statement. Correct? You are trying to have Process1 rolled back when error occurs but you can't. Also how would you like Process1 to be rolled back? To its Start Event or to the previous working state?

So would a user story like this describe your goal? "As Activiti system, I would like to catch any error from Process1 and roll it back to its previous working state and capture the error details and let users know what went wrong"

Let me know if my interpretation correct? 

Thanks,

Thong

Highlighted
Active Member

Re: Global error handling & transactions

Hello Thong,

Thank you for answering !

It seems like this is your problem statement. Correct? You are trying to have Process1 rolled back when error occurs but you can't. Also how would you like Process1 to be rolled back? To its Start Event or to the previous working state?

Yes ! That is pretty much it. I would add that Process 1 could be replaced by any process generated via my interface (small and simple modeler). I want it to be a generic behaviour for all my user's processes. The rollback i'm expecting is the classical Activiti rollback (from what i understand), that is to say to the last wait state (manual task or async activiti) if there is one, or do not persist the process instance if it comes from a start event.

So would a user story like this describe your goal? "As Activiti system, I would like to catch any error from Process1 and roll it back to its previous working state and capture the error details and let users know what went wrong"

I would rather say : As Activiti system, I would like to catch any error from Process1 (or any other process) and roll it back to it previous working state and capture the error details to store it in the corresponding process instance. The end user would just have message like "Something went wrong" and my user who has an admin role can see all process instances and on which process instance an error occurred and what was the error.

Thanks !

Stéphane

Highlighted
Established Member II

Re: Global error handling & transactions

Hi Stéphane,

 

Great. Thanks for clarifying. That helps.

I'm not sure how much 'freedom' you allow people to design Process1. I think as long as Process1 is modeled with regard of error handling, then your goal should work. In other words, you cannot catch Process1's error if it is not designed to throw any, right? So to some extent, bpmn error or technical error, they need to be designed to be thrown in Process1. 

I have created a unit test with the following scenario

A process1 (can be any process as long as it throws error properly). As you can see, a service task was attached with an intermediate error event with code 'isbnerror' (an error indicates there's something wrong with the isbn number). This is a BPMN Error. For technical error, you can use Java Service Task implements ActivityBehavior to catch and throw Java error. 

Then the Error Handling Process

This process will catch errors thrown by Process1. Process1 is a Link Activity which was attached also an error intermediate event with an error code. Which error code? 'isbnerror'? No, the error code that I specified with the error end event in Process1. When the process1 error event is thrown, this will catch it and execute the error handling model that you have designed. In this one, I have a service task to catch error details and display it on a user task for further action. Admin can choose to retry or end it. If retry, the Process1 will be started again from the very start.

I have attached a unit test. I have run it successfully.

Hope this helps you one step closer to achieve your goal.

Thanks,

Thong Huynh

Highlighted
Active Member

Re: Global error handling & transactions

Hi Thong

Thanks a lot for taking time to write this unit test. I ran it successfully and I better understand how you would implement it.

I'm not sure how much 'freedom' you allow people to design Process1. I think as long as Process1 is modeled with regard of error handling, then your goal should work. In other words, you cannot catch Process1's error if it is not designed to throw any, right? So to some extent, bpmn error or technical error, they need to be designed to be thrown in Process1. 

People should not have a lot freedom for the design. In the best scenario, I would like to be able to catch the error without letting my users taking care of.

I thought it would be somehow possible to extend a class of the engine or at activiti-rest level (in my application the engine will always be called via activiti-rest) doing something like that:

class CustomProcessFlow extend ProcessFlow {

public void processFlow() {

try {

super.processFlow()

} catch(Exception e) {

my_cuystom_logging_error_method();

raise e;

}

}

I hope you get my "idea" and what I am trying to achieve.

So I guess it will be my last question Smiley Happy Is there somewhere in activiti-rest I can plug into to catch any error raised? I am pretty sure it is not possible via process engine but I have a small hope at activiti-rest level.

Again, thank you for helping !

Stephane