4

Oracle summarises the purpose of unchecked exceptions as:

The next question might be: "If it's so good to document a method's API, including the exceptions it can throw, why not specify runtime exceptions too?" Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way. Such problems include arithmetic exceptions, such as dividing by zero; pointer exceptions, such as trying to access an object through a null reference; and indexing exceptions, such as attempting to access an array element through an index that is too large or too small.

Ok, so unchecked exceptions are for any errors caused by programmer error. Sure.

Spring's documentation for the HttpClientErrorException (which extends RuntimeException) says the exception is for:

Exception thrown when an HTTP 4xx is received.

I can't see that this is a 'programmer error' exception.

In the scenario I'm testing, I'm making a query to a Spring RestTemplate, but the server it's querying may be down, and return a 404. This seems like a perfectly normal state of affairs, not a programming error.

Am I perhaps interacting with the Spring Framework incorrectly (ie. I should be detecting the 404 before using the RestTemplate?) or is there something else I'm not considering?

  • Spring and several other important Java libraries simply have taken the stance that checked exceptions were a design mistake in the language, and therefore exclusively use unchecked exceptions for everything. I was absolutely sure there used to be a rationale for that in the Spring docs, but I can't find it anymore. – Sebastian Redl May 17 '18 at 8:19
4

I think you are doing well.

See it from this point of view. Unchecked Exceptions - Controversy.

If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.

It's a handicap due to the above premise. Spring Rest Client doesn't expect to recover itself from a 404 so it leverages the decision to catch and handle the error in the upper layers. It's your system's responsibility to decide what to do when connections to external services end with 4xx or 5xx errors. The way to don't compromise the whole Spring Web and core architecture with useless try/catch/final blocks and refactor countless components adding the throw to their method's signature, is typing errors not supposed to handle as RuntimeExceptions.

In consequence, Spring user is involved in such eventuality. Spring delegate to us to take care and to recover from such error, or let it go (like they do) up to the next layers... And so on...

To your question

ie. Should I be detecting the 404 before using the RestTemplate?

It depends whether you can recover yourself from such error. Can you? Is there something to do when the external service is not available? If that's the case, I would catch HttpClientErrorException. If not, I would probably catch it anyways in order to log it and (maybe) wrap into a service or business exception just to provide the client with more information regarding the failure of its request. Where it happened, why it happened, what to do, etc.

Regardless to what others do, Spring allows us to handle response errors in a graceful way through ErrorHandlers. Or to overwrite the method handleResponse

| improve this answer | |
2

No one got to the root of the problem. In spring-web, this is fine. The problem is that Spring Rest uses it, too. The purpose of the two are very different.

When spring-web is doing it's thing to serve up my paths, that's great! I'll use the ControllerAdvice and what-not to handle those exceptions properly before sending a response to my user.

However, when using rest client to make my own requests to a 3rd party site, I could be inside an Async task, where there is no user to display the ControllerAdvice response to. Even if there is a user, I'd want to give them something better than my local spring's exception handler (like integrate it into the form they submitted). This is not unreasonable. This is not rare. So, why does spring rest not provide a more intuitive and expected error handler?

The root of the problem is the interdependence of these 2, when they have completely different purposes in the life-cycle of a spring app. Having to ALWAYS override the error handling when using it from spring rest is not acceptable.

If that's the case, I would catch HttpClientErrorException.

This is not acceptable, as you may not even know that you can until the problem shows up. Checked exceptions alert the developer they need to do something. Hiding them behind Runtime exceptions removes this helpful alert and discourages proactive error handling. It's removing knowledge from the developer. I can't see that as a good thing, in any context. This is one of the main problems with humans - we tend to find, accept, and propagate workarounds much more than we are willing to actually make things better.

Snide Remark: Why doesn't HttpClient do it? They work with the Apache guys. I think I'd trust them over Oracle, Spring, or StackExchange randos any day.

Eh, what do I care. I've been using http client for a decade...

| improve this answer | |
0

I am assuming that Spring considered 404 an "unrecoverable" scenario.

I believe that the concept of "recovering from a 404" is not in-line with what Oracle meant with "recoverable".

Oracle's "unrecoverable" means that shit went seriously wrong. As in NullPointerException, or similar. As in a bug in the source code. That's where unchecked exceptions come in play.

My understanding is that all HTTP codes are considered a valid scenario of the HTTP spec. They are documented, expected, and have known mitigations.

I'm afraid that Spring is on the wrong side of this.

For instance RestTemplate#doExecute, wraps the http client's checked exception in an unchecked exception. This is bad...


I am currently facing a very similar problem.

I need to write a custom ResponseErrorHandler that throws some very specific exceptions (that could extend IOException, because it's in the interface's signature).

Then RestTemplate hides this by wrapping the IOException in an unchecked exception.

It would be nice of Spring to give an explanation, or if there is none, fix this.

| improve this answer | |
  • 1
    "the API client code cannot reasonably be expected to recover from them or to handle them in any way" The thing about HTTP 4xx errors is the CLIENT can't do anything but retry. Also consider: "Having to add runtime exceptions in every method declaration would reduce a program's clarity. Thus, the compiler does not require that you catch or specify runtime exceptions (although you can)." HTTP errors occur a LOT, and can bubble up in many places. Perhaps the designers felt Client Exception was like Null Pointer Exceptions, and better done as an unchecked. – Kristian H Oct 15 '16 at 5:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.