Grails 3 – Migrating from Filters to Interceptors

11 / Nov / 2016 by Puneet Behl 0 comments

Grails 3 comes with lots of new features and performance improvements, one of them being Interceptors which is a kind of a replacement for Filters from earlier versions of Grails.

Filters are used to apply logic across the whole group of Controllers, URI, or to a particular action and are used in most of the Grails projects.
Though, you can still have filters in Grails 3 by adding the plugin and making few tweaks(footnote), but I would recommend moving to Interceptors as it offers a number of benefits over filters. One such benefit is including support for CompileStatic which is critical from the performance perspective because an Interceptor is executed for every request. Another advantage is flexible configurability. For example – an Interceptor may define a property by name which matches the configuration in application.yml.

So now, let see how we can create an Interceptor in Grails 3:

    grails create-interceptor DemoInterceptor

The above command will create a groovy class in grails-app/controller/interceptorBlog/DemoInterceptor.groovy.

Similar to filters, interceptors contain code which will be applied to requests before and after calling controller actions. Following is a sample code of DemoInterceptor:

package interceptorBlog

class DemoInterceptor {

    boolean before() { true }

    boolean after() { true }

    void afterView() {
      // no-op
    }
}

  • By default, the interceptor will match the controller with the same name such as – DemoInterceptor that will match every request with DemoController.
  • If the method before and after return true the processing continues, further processing of the request is ignored.
  • The afterView method is executed after view rendering completes. If an exception occurs, the exception is available using the throwable property.

Now, that we understand interceptors a little bit, let’s see how we can replace existing Filters with Interceptors.

Creating an Interceptor which should log every request

Grails 3 takes advantage of traits, a powerful feature of Groovy. All Interceptors implements grails.artefact.Interceptor trait, which provides access to common properties and methods such as – grailsApplication, params, session, request, render redirect etc and match, matchAll methods which come handy while we need to match requests based on patterns or all requests. So, following will be the code inside our Interceptor:

package interceptorBlog

class LogInterceptor {

    LogInterceptor() {
        matchAll()
    }

    boolean before() {
        log.info("INCOMING REQUEST: ${params.toString()}")
        true
    }

    boolean after() { true }

    void afterView() {
        // no-op
    }
}

Note that the default logger name for an interceptor is grails.app.controllers so you also need to configure logging in logback.groovy as:

    logger("grails.app.controllers.interceptorBlog.LogInterceptor", INFO, ['STDOUT'], false)

Create an Interceptor to authenticate my REST call for a valid token

Here we need to match every request except for AuthController against a valid token. If a token is valid then continues processing, otherwise respond 401. So, the following is the code for interceptor.

package demo

import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED

class RestInterceptor {

    RestInterceptor() {
        matchAll()
          .excludes(controller: 'auth')
    }

    boolean before() {
        String token = session.token ?: request.getHeader('token')
        if(!token) { // Please note you could also have your own custom validation logic here
            response.status = SC_UNAUTHORIZED
            return false
        }
        true
    }

    boolean after() { true }

    void afterView() {
        // no-op
    }
}
  • The matchAll method defined in Interceptor API, returns the Matcher instance which can be used to configure how Interceptor matches the request.

I used to authenticate on beforeInterceptor method on older Grails versions, How to do it in Grails 3?.

As you already know that Before and after interceptors were removed. So all beforeInterceptor and afterInterceptor need to be replaced by Stand alone interceptors. For example, the following would not work anymore:

package interceptorBlog

class UserController {
    def beforeInterceptor = [action: this.&auth, except: 'login']

    private auth() {
        if (!session.user) {
            redirect(action: 'login')
            return false
        }
    }
    def login() {
        // display login page
    }
}

Similar functionality in Grails 3 can be achieved by creating a new Interceptor named UserInterceptor.groovy as follows:

package interceptorblog

class UserInterceptor {

    UserInterceptor() {
        match(controller: "user", action: "*")
                .except(action: "login")
    }

    boolean before() {
        if (!session.user) {
            redirect(action: 'login')
            return false
        }
        true
    }

    boolean after() { true }

    void afterView() {
        // no-op
    }
}

To read more about Interceptors please go to Grails Documentation.

If you still feel the need to continue with Filters in Grails 3, there is separate plugin available and you can use it by simply adding following as dependency in your build.gradle.

  compile 'org.grails:grails-plugin-filters:3.0.12'

Please note that you need to move filters out from grails-app/conf directory to any other source directory such as grails-app/controllers folder as grails-app/conf is not considered as source directory anymore.

Hope it helps.

FOUND THIS USEFUL? SHARE IT

Leave a comment -