I have been having this dilemma from time to time whenever I have to design or start a new project from scratch.
I particularly like how Spring framework is organised in terms of classic software patterns like services, repositories, etc. By reading and going through community projects written in Spring and for example Node.js (two absolutely different environments), the APIs differ in several points but the one this post is about is exception handling.
Imagine we are hitting a specific resource by HTTP request. It will first go to the controller, assuming no middleware in place, service, repository if any and back to the controller. But what happens if the service needs to throw an error or the custom implementation of the repository needs to throw an error?
I have seen implementations of both types:
- Inside the service/repository, throwing the actual HTTP error wrapped in a
new BadRequestException(statusCode, message)
- Let the exception or error bubble up until a global middleware catches it, and returns it back to the client.
I personally believe that mixing the logic layer (service) and data layer-ish (repository) with the transport layer (HTTP controller) is a mistake or a wrong choice since you are mixing conceptually different things. And on the latter, reliance on a global middleware will make you specify the status code or instantiate a class that internally uses the needed status code and message, again, no point on there.
In frameworks or environments that different such Spring and Node.js, I've seen both implementations, especially on Node.js. Nest uses more like a Spring approach and Express more like the second one.
What would you rather do or which is your preferred way of handling this exception handling?