users@jersey.java.net

Re: [Jersey] Jersey client and exceptions

From: Craig McClanahan <Craig.McClanahan_at_Sun.COM>
Date: Thu, 12 Feb 2009 08:07:24 -0800

Denis AH-KANG wrote:
>
>
> On Thu, Feb 12, 2009 at 10:17 AM, Paul Sandoz <Paul.Sandoz_at_sun.com
> <mailto:Paul.Sandoz_at_sun.com>> wrote:
>
>
> On Feb 12, 2009, at 12:46 AM, Denis AH-KANG wrote:
>
> Hi all,
>
> I have some questions about the jersey client and its exceptions.
> Why does the client only throw runtime exceptions
> (ClientHandlerException and
> UniformInterfaceException)?
>
>
>
> ClientHandlerException is thrown is there is an error
> reading/writing the response e.g. an IOException.
>
> UniformInterfaceException is thrown when status code of the HTTP
> response indicates a response that is not expected. And in your
> example below you need to refer to UniformInterfaceException.
>
>
> Actually, the problem is that these exceptions extend a runtime
> exception and Java typechecking doesn't force to catch that kind of
> exceptions. According to me, HTTP errors must be mapped to java
> exception that we have to deal with (e.g. force catching).
> That
> article http://scv.bu.edu/Doc/Java/tutorial/java/exceptions/runtime.html
> shows you what i think.
>
>
>
A personal reflection, based on almost ten years of experience in Java
development:

It's pretty clear that designers of early Java APIs were big believers
in checked exceptions ... the I/O and JDBC APIs are pretty classic
examples of that. This *forces* apps using these to build try/catch
blocks, and leaves them (for some exception cases) thinking "what the
heck am *I* supposed to do with this thing? If I am in a webapp, for
example, I would like to only deal with things where the user made a
mistake (and return an appropriate 4xx status), and let any other
exception percolate up to the servlet container (and trigger a 500).

I'm not quite in the extreme camp of saying "adding checked exceptions
to Java was a mistake" ... but I very much prefer the current trend in
Java API design that uses RuntimeException (as is the case with JAX-RS)
so I can catch the things I want, and let other things filter through.

So, how do I know what kinds of exceptions I *might* need to handle? My
practice is to use a Javadoc @throws clause, even for a RuntimeException
that is not listed in a "throws" clause.

By the way, lots of other languages (such as Ruby, Python, and PHP) seem
to get along just fine with no checked exceptions :-).
>
>
>
> Actually, I need to use the client and manage the most common
> HTTP responses (400, 404, 500...).
> For the moment, I catch the client exception and get the
> status code from it. It means I need
> to create a switch case to handle each case. For instance:
>
> catch(ClientHandlerException e) {
> switch(e.getResponse().getResponseStatus()):
> case 400:
> //some code
> case 404:
> //some code
> ....
> }
>
> Do you know if there's a better way to use the jersey client?
>
My "day job" apps follow this pattern, except that the "some code"
implementation actually throws things like NotFoundException (for a
404), UnauthorizedException (for a 403), and so on. Now that 1.0.2 is
out, I'm going to throw in a contribs module that formalizes this, so
other people can use this pattern if they like it.

Craig

>
> The approach taken by the client API is by default to handle
> common cases are not considered exceptional and uncommon cases
> like response errors as exception cases.
>
> So if i do a:
>
> String s = resource.get(String.class)
>
> then a UniformInterfaceException will be thrown if the response
> has a status code >= 300 and the response contains no entity.
>
> If you do this:
>
> ClientResponse r = resource.get(ClientResponse.class);
>
> then UniformInterfaceException will not be thrown. And it is up to
> you to handle the response status in normal code blocks, for example:
>
> ClientResponse r = resource.get(ClientResponse.class);
> switch(r.getResponseStatus()):
>
> case 400:
> //some code
> case 404:
> //some code
> ....
> }
>
> See the JavaDoc for more details:
>
> https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/jersey-1.0.1/api/jersey/com/sun/jersey/api/client/UniformInterface.html
>
>
> Don't you think it'll useful to extends the UniformInterfaceExceptions
> for the common HTTP error codes?
> For instance:
>
> try {
> ...
> } catch (NotFoundException nfe) {
> //HTTP 404
> } catch (InternalSystemException ise) {
> // HTTP 500
> } catch (UniformInterfaceException)
> // Don't need to use getResponseStatus: typechecking has already
> given the information
> }
>
> If you agree, I can contribute on this part.
>
>
>
>
> Paul.
>
>
>