Tagged: filter
Extending Filter Implemtations
Let’s say you are going to extend a class implementing Filter interface.
public class MyFilter implements Filter { @Override public void init(final FilterConfig config) throws ServletException { logger = newLogger(); } protected Logger getLogger() { if (logger == null) { // before init() or after destroy(); throw new IllegalStateException("no logger"); } return logger; } @Override public void destroy() { logger = null; } private Logger logger; }
This is how we should override those two important life-cycle methods
public class YourFilter extends MyFilter { @Override public void init(final FilterConfig config) throws ServletException { super.init(config); // do your jobs, after. getLogger().log("init()"); } @Override public void destroy() { // do your jobs, before. getLogger().log("destroy()"); super.destroy(); } }
Adding additional headers on a ServletRequest
References
- Adding Header Information to an existing HTTP Request
- How to modify request headers in a J2EE web application
- Modifying HTTP headers using Java
Problem
Simply, we can’t add or modify request headers on given HttpServletRequest
instances.
Solution
The only solution, at least mentioned in above links, is using HttpServletRequestWrapper
class. I wrote, for my own, a class which wraps additional headers around the actual request instance.
public class RequestHeaderWrapper extends HttpServletRequestWrapper { public RequestHeaderWrapper( final HttpServletRequest request, final Map<String, List<String>> precedingHeaders, final Map<String, List<String>> succeedingHeaders) { super(request); headers = new HashMap<>(); if (precedingHeaders != null) { for (final String name : precedingHeaders.keySet()) { List<String> values = headers.get(name); if (values == null) { values = new ArrayList<>(); headers.put(name, values); } values.addAll(precedingHeaders.get(name)); } } for (final Enumeration<String> names = request.getHeaderNames(); names.hasMoreElements();) { final String name = names.nextElement(); List<String> value = headers.get(name); if (value == null) { value = new ArrayList<>(); headers.put(name, value); } value.addAll(Collections.list(request.getHeaders(name))); } if (succeedingHeaders != null) { for (final String name : succeedingHeaders.keySet()) { List<String> values = headers.get(name); if (values == null) { values = new ArrayList<>(); headers.put(name, values); } values.addAll(succeedingHeaders.get(name)); } } } @Override public String getHeader(final String name) { final List<String> values = headers.get(name); if (values != null && !values.isEmpty()) { return values.get(0); } return null; } @Override public Enumeration<String> getHeaders(final String name) { List<String> values = headers.get(name); if (values == null) { return Collections.emptyEnumeration(); } return Collections.enumeration(values); } @Override public Enumeration<String> getHeaderNames() { return Collections.enumeration(headers.keySet()); } private final Map<String, List<String>> headers; }
Full and latest source code is here and the apidocs is here.
Apache Maven
Please check the central if you’re using Apache Maven.
<dependency> <groupId>com.googlecode.jinahya</groupId> <artifactId>jinahya-ee</artifactId> <version>@@?</version> </dependency>
Usage
There are some factory methods for simple use.
public class MyFilter implements Filter { @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { final ServletRequest wrapper = RequestHeaderWrapper.newPrecedingInstance( requerst, "Accept", "application/xml"); chain.doFilter(wrapper, response); }
Servlet Filter for HTTP
A problem of Filter is that the doChain method is for ServletRequest and ServletResponse.
public class MyFilter implements Filter { @Override public void init(final FilterConfig filterConfig) throws ServletException { } @Override public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { } @Override public void destroy() { } }
It’s not a big deal if you presume that those are actually instances of HTTP version.
@Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest hequest = (HttpServletRequest) request; final HttpServletResponse hesponse = (HttpServletResponse) response; // happy, now? }
I quickly tired of doing this.
public abstract class HttpFilter implements Filter { @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) { doFilter((HttpServletRequest) request, (HttpServletResponse) resposne, chain); return; } chain.doFilter(request, response, chain); } protected abstract void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException; }
Now I can do this.
public class MyFilter extends HttpFilter { @Override protected void doFilter(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException, ServletException { // never bean happier. :) } }
Full source is here.