I have been trying over the past few days to come up with a good way to trap errors. It is not so much that we are having trouble trapping the errors, as we can’t stop error emails from being generated even if we handle the error within the catch block.
We use a sequence like the following:
[SIZE=2]SEQUENCE1 (exit on SUCCESS)
…SEQUENCE2 (TRY - exit on FAILURE)
…Service1
…Service2
…SEQUENCE3 (CATCH - exit on DONE)
…pub.flow:getLastError
…errorHandleService
So for instance, Service1 throws a service exception. We catch it and return an error back to the client or update a db table, etc. However, it will also send an email off to our admins notifying them of an issue. Currently they are getting several thousand emails a day making it nearly impossible to actually work the real issues.
I tried utilizing the exit flow statement in conjunction with a branch, but when you exit, you cannot get the error information.
SEQUENCE1 (exit on SUCCESS)
…SEQUENCE2 (TRY - exit on FAILURE)
…Service1
…Branch /Service1Output
…Exit TRY - signal Failure
…Service2
…SEQUENCE3 (CATCH - exit on DONE)
…pub.flow:getLastError
…errorHandleService
I tried setting error variables within the branch, but when you exit out of the SEQUENCE2 block, those variables are removed from the pipeline, and you do not have access to the failure message via getLastError. This makes it impossible to report on what is actually wrong with Service1.
By using a custom java service, we can generate a ServiceException that contains the proper error message, or you can wrap Service1 and the branch into a separate flow using Exit $flow from the sub flow (generating a FlowException versus the ServiceException). With these methods you can get access to the entire pipeline and the specified failure messages. Both of these approaches will generate error emails even if the code properly handles the error.
The another possibility is to have nested flow like the following:
SEQUENCE1 (exit on SUCCESS)
…SEQUENCE2 (TRY - exit on FAILURE)
…Service1
…Branch /Service1Output
…SEQUENCE (error)
…errorHandleService
…SEQUENCE (nonerror)
…Service2
…Branch /Service2Output
…SEQUENCE (error)
…errorHandleService
…SEQUENCE (nonerror)
…Service3
…etc
…SEQUENCE3 (CATCH - exit on DONE)
…pub.flow:getLastError
…errorHandleService
This approach allows us to recover better from expected from expected errors. For instance Service1, would return an errorMessage on the pipeline instead of using the build in Exit steps. However, this method is much more time consuming and makes the flow very difficult to follow as you get 10-20 service calls deep(not to mention all the branch steps and error pipeline values involved).
Yet another solution that appears to work is to wrap error generating services inside of a custom java service that uses the doInvoke calls. This way you can trap any exception via standard java try/catch and only pass through unexpected exceptions. This works for most scenarios, but the idea of wrapping all of our services in a custom java service just seems hacky.
The only other thought I have is to disable the error email generation all together and only send errors in the catch block when appropriate. My concern here is that there is no fail safe. If something happens that the developer did not expect, then no email will be sent. I would prefer to send emails by default, but give the developer the ability to supress known conditions.
How are other people handling these situations? We have 20+ IS’s in production not counting the HA and DR sites with hundreds of flows. The current flows are generating thousands of emails a day making it nearly impossible to support the real issues.[/size]