I had a scenario (I don’t really want to get into it) where I needed to implement a proper servlet filter which would run before the Grails dispatcher got involved in the request. The Grails documentation says it can be done, but the instructions are ridiculously vague, and seem more centered on plugins rather than just a webapp.
I finally managed to work it out, and I wanted to show the source code involved for posterity, and anyone else who might stumble upon this solution.
First off, create your filter in /src/main/java/myPackage:
package myPackage; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Nathan Crause <nathan@crause.name> */ @WebFilter(filterName = "testFilter", urlPatterns = {"/*"}) public class TestFilter implements Filter { private FilterConfig filterConfig; public TestFilter() { } /** * @param request The servlet request we are processing * @param response The servlet response we are creating * @param chain The filter chain we are processing * * @exception IOException if an input/output error occurs * @exception ServletException if a servlet error occurs */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; for (int i = 0; i < 100; ++i) { for (int c = 0; c < 80; ++c) { System.out.print("-"); } System.out.println(); } chain.doFilter(request, response); } /** * Destroy method for this filter */ @Override public void destroy() { } /** * Init method for this filter * @param filterConfig */ @Override public void init(FilterConfig filterConfig) { this.filterConfig = filterConfig; } }
Now the really poorly documented part – where the hell do you tell Grails to load the damned thing? Turns out you just use /grails-app/conf/spring/resources.groovy:
import org.springframework.core.Ordered import org.springframework.boot.web.servlet.FilterRegistrationBean import myPackage.TestFilter beans = { testFilter(FilterRegistrationBean) { filter = bean(TestFilter) urlPatterns = ['/*'] // we want all other Grails filters to have loaded first order = Ordered.LOWEST_PRECEDENCE } }
Now, I originally opted for using pure Java for the speed, but it did expose the problem that none of my domain classes were accessible, which I did require. So, I re-implemented the filter as a Groovy class in the /grails-app/controllers/myPackage directory.
It’s also worth noting that you will be required to create a new hibernate session in order to perform queries.
package myPackage import javax.servlet.Filter import javax.servlet.FilterChain import javax.servlet.FilterConfig import javax.servlet.ServletException import javax.servlet.ServletRequest import javax.servlet.ServletResponse import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse /** * @author Nathan Crause <nathan@crause.name> */ class TestFilter implements Filter { FilterConfig filterConfig void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { for (int i = 0; i < 10; ++i) { println("-" * 80) } Account.withNewSession { println(Account.last().inspect()) } chain.doFilter(request, response) } void destroy() { } void init(FilterConfig filterConfig) { this.filterConfig = filterConfig } }