Issue
we have a number of API servlets, each of which implements get/post methods which call a service layer. The service layer can throw 5 or 6 different exceptions.
In each of our servlets, we have a catch for each one to convert them into formatted json error responses.
Each time we write a new servlet to perform a function, we have to cust and past around 30 lines of code to handle these exceptions in the same way.
Is there a strategy to remove this duplication?
E.g. could we create a filter for all these servlets which handles the exceptions? I dont know if filters can catch exceptions from servlets.
Another option would be to have one servlet and use it to route (aka giant if statement). But its too late to rewrite all our servlet apis.
Any other suggestions?
Solution
You should use filters for this behavior. (Protip: filters are an essential concept within Servlet, so you should invest time in it to learn its basics. They will help you with a lot of functionality and patterns. If you understand filters, then your question is easy to solve.)
To give you a short intro in filters: a filter is like a decoration over your servlet. Every other new filter, is another new decoration over the already existing filter. When a HTTP request comes in, it starts with the outer filter (top), which calls the next filter, which calls the next filter, and so on, until the Servlet is reached. The servlet generates HTML body, and return to the last called filter, which will return to the previous filters, and so on, until the top filter finishes, and the response is send back to the client. (This is the most common use-case for filters.) A single filter can be applied to multiple url-patterns and servlets, allowing code reuse.
Here is example using filters for exception handling:
public class ExceptionHandlingFilter implements Filter {
public void init(FilterConfig config) {}
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
try {
chain.doFilter(request, response);
} catch (Exception ex) {
System.out.println("I handle all your exceptions!");
}
}
}
Override the catch
block with your exception handling code.
In your web.xml
add:
<filter>
<filter-name>ExceptionHandlingFilter</filter-name>
<filter-class>com.example.demo.ExceptionHandlingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ExceptionHandlingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Put this xml code before other filter-mapping
definitions, so that it is the first filter in the filterChain, so that it is also able to catch exceptions thrown by other filters. (In case you prefer servlet annotations: you cannot define filter order using annotations, so if you have multiple filters, you'll need to define <filter-mapping>
in web.xml
anyway, otherwise the ExceptionHandlingFilter may skip exceptions thrown by other filters.)
Answered By - Devabc
Answer Checked By - Terry (JavaFixing Volunteer)