Question

(I moved this question here, as StackExchange fits better, originally I posted it on StackOverflow.)

This is not a question about a particular piece of code, rather I ask what is the right design approach in such situations.

More on the situation:

I am developing a sort of exception handling framework for a Spring Boot REST application. Although this is a bit grandiose naming for introducing the standard Spring @ControllerAdvice + @ExceptionHandler mechanism to the project, also a custom (parent) exception is introduced to mark the functional problems for the project.

I might be overthinking it, but is it OK to explicitly throw exceptions from the private methods of the business functional classes? Keep in mind that the business functional classes form something like an API for the Business Domain, as in DDD. This is the approach with less code, also most clear from a developer point of view, because I throw the exception exactly where the problems comes up. But if I wait (try-catch-finally) for the problem in public method, I might gain the ability to document it with throws declaration, also the clients of that business functionality with benefit from the increased readability.

Also, is throwing exceptions, especially, deliberately from private methods a sort of security risk? As it would expose the methods call stack in the stacktrace in the log?

Was it helpful?

Solution

What a public method documents as the exceptions that can be propagated out of it (throws declaration) and where the exception actually gets generated are two completely different and independent things.

As soon as a method or function detects that it cannot fulfil its contract, that is the point where an exception should be thrown. This is completely independent of the visibility (private, public, etc.) of the method or function.

The throws declaration on a public method should document all the exceptions that a caller of that method might have to deal with (or at least be aware of). That is not just the exceptions thrown by the method itself, but also the exceptions thrown by functions/methods that it calls and which are not handled.

OTHER TIPS

Ask not why you want to throw an Exception but why would you want to catch one!

The most important part of Structured Exception Handling is that last bit - handling the Exception. In my book, that means catching it and doing something "useful" with it.

What's "useful"? Well (as ever) it depends.

If your own code can catch an Exception, "deal" with it and make it "go away", so that your caller knows nothing whatever about it - that's useful!

  • In this case, having as much detail as possible (i.e. a custom Exception) would be a Good Thing.

If your own code can catch an Exception, log the details away somewhere and then construct a new, sanitised, Exception that is suitable for public consumption (as you should do at your component Boundaries) - that's useful.

  • Again, details are useful for you to diagnose the issue but other people don't need to know them (or, indeed, see the internal structure of your code).

If your caller's code can catch the Exception, reliably determine a course of action to rectify the problem ("try again" being a perfectly valid one), then that's useful.

  • Here a custom Exception is essential because no-one should ever try to interpret an Exception's message property. Always use it's class and/or custom properties.

If your caller's code can catch the Exception, log it and display a generic, "Oops, something went wrong" message to the User, well, that's useful too. Just not very useful.

  • A custom Exception is probably overkill here.

If your caller's code can catch the Exception, bamboozle the User by dumping the whole thing on the screen before the Application crashes and burns - well, that's just rubbish.

Sadly, though, this seems to be the sum extent of "Structured Exception Handling" to some Developers.

Either the caller, in the same class, catches the exception, then there is no problem. Or the exception is passed to the outside, then it will become a normal part of the public method’s contract.

If I call your public method and receive an undocumented exception, that is obviously rubbish.

Licensed under: CC-BY-SA with attribution
scroll top