Lately I had a chat with some colleagues if to use an exception-mechanism for some specific logic.

There was some rest request handler written in Java which returns some result which then is converted to a REST response. This request handler also validates user input and throws bad request responses at the user if he’d dared to push invalid content.

The question is: Should Java exceptions be used to indicate invalid user input or should a complex result object be used which either holds error information or a valid result? Both solutions could be converted to the same 400 Bad Request response.

Simple problem, simple solution right? Yeah, probably … but software engineers tend to overengineer problems. Well, let’s dive into the discussion.

First, let’s setup a simple REST request which will fail:

{

"name": "Tom",

"age": "INVALID_CONTENT"

}

The above request should result in a bad request response since age is not a number. Now, let’s talk about the exception-approach.

If you’re coming from the Java environment then you probably have already read or heard about ‘Effective Java’ in which Joshua Bloch states:

Exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow.

Ok, with that in mind … let’s see, would exceptions in our use-case be used for control flow?

As we find out that age is not a number an exception is thrown. The REST response converter handles the exception with an explicit try-catch-handler. As we run into the catch-clause an explicit conversion to a bad request exception is made. On the first look I would claim that it indeed changes the control flow. What could otherwise be implemented as an if-statement (if user input is valid…) is implemented as a try-catch-clause.

However, let’s look at it from another point of view. We are using REST. A REST API is still an API and if you think about it, a 400 Bad Request response is quite similar to a Java exception right? It is kind of like an exception in the REST environment. It’s still not the same but it’s similar.

Let me quote another statement from ‘Effective Java’:

Higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction

An example from the JDK:

public E get(int index) {

ListIterator<E> i = listIterator(index);

try {

return i.next();

} catch(NoSuchElementException e) {

throw new IndexOutOfBoundsException(“Index: “ + index);

}

}

Now, let me ask you, isn’t this similar to our problem in our REST case? Wouldn’t it be correct to say that we are doing no different? An exception is caught and it is “thrown” as a 400 Bad Request response. It sounds pretty similar …; also, from user perspective, it may be classifiable as an exceptional-condition.

I’ll give you another reason why exceptions could be the correct solution for our REST case.

In our situation we already had a REST framework in place which offers some exception-to-error-response mapping (JAX-RS). Of course you want to use the solution which is already supported by the framework you have in place, right? Why do we even discuss …

Well, let me quote another statement from ‘Effective Java’:

A well-designed API must not force its clients to use exceptions for ordinary control flow.

Is JAX-RS well-designed? Actually, I don’t care about that, I’ll leave that up to you. I want to elaborate on something different. I claim, only because a framework is offering a convenient way to write bad code, you should not just do it™. Either use a different framework or build some wrapper-functionality around the one which is in place.

Ok, let’s recap a bit. If we are viewing the problem strictly from the developer’s perspective then exceptions are a bad choice as we are definitely changing control-flow. Only if we view the problem with a more open mindset we are able to come up with reasons why it is not a bad choice to use exceptions.

Consider another detail: Let’s say, we want to return statistics for all REST requests; regardless of success. To accomplish that with exceptions in Java we have to add the statistics object to the actual result class and additionally to the exception class(es). Code duplication, mhm … This kind of code duplication is not necessary with a single result object which also holds error information as it would just additionally hold the statistics data.

Puhh … ok … so, which solution should we choose? We went for exceptions. Why? IT IS BAD. Or is it? In this case it’s so hard to tell if it’s bad or ok. Now, coming from the view of an experienced senior developer (not me of course …), it’s ok to talk about such things, but don’t let overengineering be an impediment for productivity. In our case our REST API is only a single feature of many. The time which would be needed to create a wrapper around JAX-RS for error-handling without exceptions should be instead invested in a more important feature. Normally, you would want to avoid that as a single piece of bad code could result in a domino-effect with many more pieces of bad code; spaghetti code. However, in this case it’s not even completely clear if it is bad, so the decision has been made to accept exceptions as a solution.

To use or not to use exceptions … At the end I still don’t have an accurate answer to this question.