I'm working on a Jetty/RESTEasy app. If I throw a WebApplicationException(myResponse)
from one of my REST endpoints, it sends the given response to the client.
When a filter detects an error, I want the same behavior:
Obviously, just writing to the response stream and return
ing works from within the doFilter
method. But this doesn't work for other methods called by doFilter
.
Throwing any exception will meet condition #1 but I haven't figured out a sane way to meet condition #2 then. (You can see my best attempt at the bottom.)
As Perception explained in his answer, WebApplicationException
s are treated like any other exception in the context of a Filter, and therefore give the user a nice ugly stack trace.
So, to sum up my questions:
throw new WebApplicationException(Response)
? I have this code in one filter and it works, but I'd 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());
}
}
Each error-page element should have either error-code or exception-type element. We define the exception handler servlet in location element. Based on above configuration, if the application throw 404 error or ServletException, it will be handled by AppExceptionHandler servlet.
Q 25 - Which of the following request attributes that an error-handling servlet can access to analyse the nature of error/exception? A - javax.
Specifying Filter Configuration To map a filter to a servlet you: Declare the filter using the <filter> element in the web application deployment descriptor. This element creates a name for the filter and declares the filter's implementation class and initialization parameters.
The specific handling you mention for web application exceptions is only defined within the context of a JAX-RS container, which, by the way, is not the same thing as a Servlet container.
Web filters are handled by the Servlet container, which does not know or care that a JAX-RS container exists within the same application server. It also does not know or care about web application exceptions. So when you throw the WAE from within the filter it is treated just the same as any other exception (server error with a stack trace, or a preconfigured error page if you set one up in your web application).
It would seem to me if you are indicating an error to the client you could simply do so from the filter, by writing directly to the response stream. But if you are trying to leverage some existing JAX-RS logic then a (RESTEasy specific) solution would be to flag the request as error'ed out in your filter, then generate a WAE in JAX-RS, using a 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 JAX-RS land, the web application exception is processed according to the rules of Section 3.3.4 of the JAX-RS specification, and you get the desired response at the client side.
* EDIT:*
The bottom line is, there is no standard Java EE prescribed way (currently) to handle servlet exceptions in a centralized fashion similar to what is available in JAX-RS. Since you are using JBoss/RestEASY though, you could utilize 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. Note that the library is in massive flux right now, so you will want to utilize it only as a last resort.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With