简体   繁体   中英

Prevent Tomcat from interfering with Jersey/JAX-RS 2 Response Body on HTTP Error Status 4xx or 5xx

I have the following stack for a REST API

  • Jersey 2/JAX RS 2.0
  • Tomcat 7.0.47
  • Jackson 2

My goal is to have a custom response body when an error occurs. I want to be able to send the client an explanation what exactly went wrong for easier debugging.

First I tried to use @Context HttpServletResponse and set the http status code there, but it was ignored by jersey (which is the normal behaviour but this is beyond my understanding)

Then I tryed to use WebApplicationException like this:

@GET
@Path("/myapi")
public BaseResponse getSomething() {
   BaseResponse b = new BaseResponse();
   if(error) {
      b.setStatusDescription("reason for error");
      throw new WebApplicationException(Response.status(Response.Status.CONFLICT).entity(b).build());
   }
   //add content to BaseReponse
   return b
}

But Tomcat returns me somthing like this:

<html>
    <head>
        <title>Apache Tomcat/7.0.47 - Error report</title>
        <style>
            <!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22p

Which is the standard Tomcat html output capped by the contet-length of response body I wanted to return ( .entity(b) - the length of b ). So it is recognized but Tomcat just overwrites it with its own error page.

As a side note I also tried to just return the Response with the same outcome:

return Response.status(Response.Status.CONFLICT).entity(b).build()

So how do I tell Tomcat to leave me alone and let my own responses through?

Just add the following code in the configuration of ResourceConfig class.

property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true");

See jersey.config.server.response.setStatusOverSendError

The problem was that I was using the GzipServlet from ehcache which seems to not work porperly with jersey. During the multiple phases the response wrapper threw exceptions.

This is the dependency of ehcache:

        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-web</artifactId>
            <version>2.0.4</version>
        </dependency>

And the problematic servlet definition in web.xml

<filter>
        <filter-name>GzipFilter</filter-name>
        <filter-class>net.sf.ehcache.constructs.web.filter.GzipFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>GzipFilter</filter-name>
        <url-pattern>/rest/*</url-pattern>
    </filter-mapping>

As an alternative Im using Jetty Servlet now: http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/servlets/GzipFilter.html

<dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlets</artifactId>
            <version>8.1.0.RC5</version>
        </dependency>

web.xml

<filter>
  <filter-name>GzipFilter</filter-name>
  <filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
  <init-param>
    <param-name>mimeTypes</param-name>
    <param-value>text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,image/svg+xml</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>GzipFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

As disclaimer: yes I know I can activate gzip in tomcat config, but Im writing a testserver that must be able to have endpoints with and without gzip.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM