users@jersey.java.net

Re: [Jersey] Error Handling...and forwarding

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 14 Jan 2009 13:45:24 +0100

HI Jorge,

Thanks for doing this investigating it helps me a lot to investigate
further. Note that i tried asking on the GF users list but got no
response :-(

So in the bad-resource case the behavior for the Jersey Web app should
be as follows:

  1) Jersey returns a 404 to the URL path "/rest/bla"

  2) The servlet container redirects the 404 to /rest/error"

And i presume it should be the same for a servlet implemented
equivalently to that of the Jersey servlet.

So... I modified the servlet test case. The web.xml was modified as
follows:

   <servlet-mapping>
     <servlet-name>ErrorServlet</servlet-name>
     <url-pattern>/servlet/*</url-pattern>
   </servlet-mapping>
   <error-page>
     <error-code>404</error-code>
     <location>/servlet/error</location>
   </error-page>

and the ErrorServlet was modified as follows:

         if (req.getPathInfo().equals("/error")) {
             PrintWriter out;

             res.setContentType("text/plain");
             out = res.getWriter();

             out.printf("The error has been caught by the error
servlet!\n\n");
             out.printf("Error : %d\n" +
                     "Message : %s\n" +
                     "Exception Type: %s\n",
                      
req.getAttribute("javax.servlet.error.status_code"),
                     req.getAttribute("javax.servlet.error.message"),
                      
req.getAttribute("javax.servlet.error.exception_type"));
         } else {
             res.setStatus(404);
         }

Thus the above models what Jersey does. In such cases the same
behavior results as the Jersey deployed JAX-RS test case.

I think i now know what it is. If i change:

   res.setStatus(404);

to

   res.sendError(404);

then it works. And then i read this:

   Sets the status code for this response. This method is used to set
the return status code when there is no error (for example, for the
   status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error,
and the caller wishes to invoke an error-page defined in the
   web application, the sendError method should be used instead.

Hmm... i am wondering what to do here. The following rule could apply:

   - if the response status is an error >= 400 and there is no
response entity and no response headers set (the application has not set
     anything other than the status code or Jersey has set just the
status code) then the servlet response mapping calls sendError.

IMHO this is something we need to clarify in the JAX-RS specification.

Paul.

On Jan 14, 2009, at 9:23 AM, Jorge L. Williams wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi Paul,
>
> Wow, I can't believe it took me a month to get back to you. Sorry,
> holiday, deadlines, you know how it is.
>
> Anyway, I did put together a simple app for you. I noticed while
> testing it that the behavior is slightly different between
> application servers. To rule out an application server problem vs a
> jersey problem I also tested my approach with the RestEasy JAX-RS
> implementation (no offense guys :-) I'm sending the source for the
> ear file.
>
> There are three web modules:
>
> 1. error-servlet : Our old approach of catching errors using a
> servlet as an error page.
> 2. error-jaxrs : The Jersey implementation
> 3. error-resteasy : The Rest-easy implementation
>
> I tested with three application servers
>
> 1. glassfish : 9.1_02 (build b04-fcs)
> 2. jboss : 5.0.0.GA
> 3. weblogic : 10.3
>
> Each webapp is setup to forward a 404 to a resource (or servlet). If
> you visit context root of each of the web apps you'll see a couple of
> links
>
> 1. direct : A direct link to the error resource (just to make sure
> we're getting to it)
> 2. bad : A bad link within the context root (this should generate
> 404 and forward to the error resource)
> 3. bad-resource : A bad link within the JAX-RS servlet mapping
> (this should should also forward to the error resource)
>
> Here's the results I get for Jersey
>
> glassfish (direct : works, bad : works, bad-resource : wrong error
> page )
> jboss (direct : works, bad: works, bad-resource: wrong error page)
> weblogic (direct: works, bad : empty result, bad-resource: empty
> result)
>
> I use weblogic which displays the behavior I described in my initial
> email. I'm guessing the behavior there may indeed be an application
> server issue. None the less, Jersey doesn't seem to be behaving
> correctly with the other app servers. The RestEasy implementation
> handles all three cases correctly -- in JBoss, I couldn't get it
> deployed on the other app servers though I didn't spend too much time
> fighting with it :-)
>
> Hope this helps...It would be really nice if I could get this feature
> to work or if there were at least an alternative to it.
>
> Let me know,
>
> jOrGe W.
>
>> Hi Jorge,
>>
>> Would it be possible to create a simple example application. That
>> would help me understand better your use-case and help debug what is
>> going on.
>>
>> My suspicion is the error resource is deployed at a URL that is
>> different to what you expect.
>>
>> What is the error resource class you are using, specifically the
>> @Path
>> value? and what is the URL pattern for the error servlet?
>>
>> Paul.
>>
>> On Dec 12, 2008, at 12:32 AM, Jorge L Williams wrote:
>>
>>>
>>> Hey guys,
>>>
>>> I know we covered this topic earlier, but I have a slightly
>>> different question, I think.
>>>
>>> We want to make sure that regardless of what sort of error condition
>>> occurs (whether it's generated by one of our JAX-RS resources or
>>> whether it's an internal server error of some kind) that we return a
>>> correct entity. In our case we have a JAXB object called
>>> WebserviceFault that our clients expect should anything go wrong.
>>>
>>> To catch every case we created an ErrorServlet that mapped to say /
>>> error and setup our web.xml...
>>>
>>> <error-page>
>>> <error-code>400</error-code>
>>> <location>/error</location>
>>> </error-page>
>>> .
>>> .
>>> .
>>> <error-page>
>>> <error-code>500</error-code>
>>> <location>/error</location>
>>> </error-page>
>>>
>>> The error servlet itself simply gets details from the request...
>>>
>>> Integer code = (Integer) request.getAttribute
>>> ("javax.servlet.error.status_code");
>>> Exception e = (Exception) request.getAttribute
>>> ("javax.servlet.error.exception");
>>> String msg = (String) request.getAttribute
>>> ("javax.servlet.error.message");
>>>
>>> and wraps it around a WebserviceFault which it serializes to the
>>> response.
>>>
>>> Very tedious and maybe a little goofy (If there's a better way I'll
>>> take it), but it's been working well for us thus far and this method
>>> allows us to catch absolutely all error conditions including 401s
>>> etc..that I don't think make it into Jersey.
>>>
>>> We've been transitioning our ReST services from using vanilla
>>> servlets to Jersey over the last couple of months. I decided to
>>> replace the ErrorServlet that we've been using with an error
>>> resource since we've become interested in receiving error conditions
>>> not just in XML but also in JSON and I figured converting the Error
>>> servlet would be the easiest way to accomplish this.
>>>
>>> One problem: it doesn't work. When an error condition hits and the
>>> application server forwards to the error resource, I get nothing but
>>> a blank request no entity at all -- though the Error code is
>>> correctly transmitted ie:
>>>
>>>
>>> HTTP/1.x 404 Not Found
>>> Date: Thu, 11 Dec 2008 22:34:21 GMT
>>> Content-Length: 0
>>>
>>> I suspect that this is because the request is being forwarded and
>>> the URI is not what Jersey is expecting(?).
>>> For example we get...
>>>
>>> GET /bla/bla/bla
>>>
>>> but something goes wrong and the application server forwards to
>>>
>>> /error
>>>
>>> probably via a request dispatcher(?). I believe the request URI in
>>> this case should be /bla/bla/bla and not /error -- is this what's
>>> confusing things?
>>>
>>> So, should I stick with my error servlet? If so what's the best
>>> way to utilize Jersey to handle the request -- parse the Accept
>>> header myself and get a MessageBodyWriter from MessageBodyWorkers?
>>>
>>> Thanks,
>>>
>>> jOrGe W.
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v2.0.9 (GNU/Linux)
>
> iEYEARECAAYFAkltoQEACgkQ72r0i/n44hPv9wCfdrRjk7MmDJe8TucA4c3oA4rD
> 3ioAoJjrOsE2mtMqJFzzOpCgUz+Q3Xml
> =GtV5
> -----END PGP SIGNATURE-----
>
> <error-test.tgz><error-
> test
> .tgz
> .sig
> >---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net