I am working on a ReST based service which calls other ReST based services and also deals with Persistence in a database. So a typical call might look like
- Get some data from the database.
- Make a call to an external service using a ReSTClient to create a record.
- Persist the response to the database.
- Make another call to another service.
- Return a response back.
The problem being that both the ReSTClient and the DB persistence layer throws only their own custom RuntimeExceptions. I don't want to pollute my code with try catch blocks around each step and so wanted to have a high level exception mapper that basically returned back a 500 error code to the caller with a basic message that the call failed. Some developers say we must put a try catch block around each step and catch the RuntimeExceptions and return back a 500 error code but also the exact reason for the failure. My experience has shown that exact error messages when shown to the user doesn't add much value since the user doesn't actually understand our system and doesn't really know what it means to have the service call fail vs a failure in the database layer, he just knows the operation has failed. Also there is no guarantee that the client calling our service is a human user, could be another service.
Also during development certain situations can happen like for eg. step 2 is successful but step 3 fails because of a database failure. In this case the system is in an inconsistent state where the successful call is not recorded in the DB and if the human user doesn't know this then he make execute the operation again to create two records in the external system. There would be many such cases with regards to DB and disk failures etc. that we can't predict. So do you catch these exceptions at each step and write code and error messages to handle these situations.