How to handle error states in servlet filters without showing the user a stack trace?

I am working on a Jetty / RESTEasy application. If I throw a WebApplicationException(myResponse) from one of my REST endpoints, it will send this response to the client.

When the filter detects an error, I want the same behavior:

  • He must stop the execution, and
  • It should give the user a clear JSON format error that does not include stack tracing.

Obviously, only writing to the response stream and return ing works from the doFilter method. But this does not work for other methods called doFilter .

Throwing any exception will meet condition No. 1, but I did not understand a reasonable way to fulfill condition No. 2. (You can see my best attempt below.)

As explained in its answer, WebApplicationException treated like any other exception in the context of the filter, and therefore gives the user a good ugly stack trace.

So, to summarize your questions:

  • Do serveltt containers have the equivalent of throw new WebApplicationException(Response) ?
  • And, more importantly, how do other java projects handle this?

I have this code in one filter and it works, but I would prefer a more elegant solution that automatically applies to all filters:

 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { try { doFilterOrThrow(request, response, chain); } catch (WebApplicationException e) { Response res = e.getResponse(); ((HttpServletResponse) response).sendError(res.getStatus(), (String) res.getEntity()); } } 
+6
source share
1 answer

The specific processing that you mention for web application exceptions is defined only in the context of the JAX-RS container, which, incidentally, does not match the Servlet container. p>

Web filters are handled by the Servlet container, which does not know and does not care that the JAX-RS container exists on the same application server. He also does not know and does not care about web application exceptions. Therefore, when you drop WAE from a filter, it is handled in the same way as any other exception (a server error with a stack trace or a pre-configured error page if you install it in your web application).

It seems to me that if you indicate an error to the client, you can simply do this from the filter by writing directly to the response stream. But if you are trying to use some existing JAX-RS logic, then a specific solution (RESTEasy) would have to mark the request as erroneous in your filter, and then create WAE in JAX-RS using the provider class. Example:

 @WebFilter(urlPatterns = "*") public class ForwardingFilter implements Filter { @Override public void destroy() { return; } @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { // Add an error response to be processed by the JAX-RS container. // This would obviously be based on some condition. request.setAttribute("errorResponse", Response.status(500).entity("Didn't work out!").build()); chain.doFilter(request, response); } @Override public void init(FilterConfig arg0) throws ServletException { return; } } @Provider @ServerInterceptor @HeaderDecoratorPrecedence @RequestScoped public class ForwardingHandlerProvider implements PreProcessInterceptor { @Override public ServerResponse preProcess(final HttpRequest request, final ResourceMethod method) throws Failure, WebApplicationException { final Response errorResponse = (Response) request .getAttribute("errorResponse"); if (errorResponse != null) throw new WebApplicationException(errorResponse); return null; } } 

Since the provider exists in the JAX-RS territory, the web application exception is handled in accordance with the rules of section 3.3.4 of the JAX-RS specification, and you get the desired response on the client side.

* EDIT: *

The bottom line does not have a standard Java EE that is (currently) required to handle servlet exceptions in a centralized way, similar to what is available in JAX-RS. Since you are using JBoss / RestEASY, you can use the JBoss Seam Catch library to get pretty close.

 @HandlesExceptions public class ExceptionHandler { public void handleServletException( final @Handles @WebRequest CaughtException<ServletException> caught, @Context final HttpServletResponse response) { try { response.sendError(500, "An error occured"); } catch (final IOException ioe) { System.err.println("Dumb IO Exception: " + ioe); } } } 

The above illustrates an exception handler as described in the Seam Catch documentation. Please note that the library is in a huge stream right now, so you will want to use it only as a last resort.

+7
source

All Articles