8.5 Interceptors 6.0.0

(Quick Reference) # 8.5 Interceptors Version: 6.0.0 ## Table of Contents ## 8.5 Interceptors Grails provides standalone Interceptors using the create-interceptor command:
    $ grails create-interceptor MyInterceptor
The above command will create an Interceptor in the `grails-app/controllers` directory with the following default contents:
    class MyInterceptor {

      boolean before() { true }

      boolean after() { true }

      void afterView() {
        // no-op
      }

    }
#### Interceptors vs Filters In versions of Grails prior to Grails 3.0, Grails supported the notion of filters. These are still supported for backwards compatibility but are considered deprecated. The new interceptors concept in Grails 3.0 is superior in a number of ways, most significantly interceptors can use Groovy’s `CompileStatic` annotation to optimize performance (something which is often critical as interceptors can be executed for every request.) ## 8.5.1 Defining Interceptors By default interceptors will match the controllers with the same name. For example if you have an interceptor called `BookInterceptor` then all requests to the actions of the `BookController` will trigger the interceptor. An `Interceptor` implements the Interceptor trait and provides 3 methods that can be used to intercept requests:
    /**
     * Executed before a matched action
     *
     * @return Whether the action should continue and execute
     */
    boolean before() { true }

    /**
     * Executed after the action executes but prior to view rendering
     *
     * @return True if view rendering should continue, false otherwise
     */
    boolean after() { true }

    /**
     * Executed after view rendering completes
     */
    void afterView() {}
As described above the `before` method is executed prior to an action and can cancel the execution of the action by returning `false`. The `after` method is executed after an action executes and can halt view rendering if it returns false. The `after` method can also modify the view or model using the `view` and `model` properties respectively:
    boolean after() {
      model.foo = "bar" // add a new model attribute called 'foo'
      view = 'alternate' // render a different view called 'alternate'
      true
    }
The `afterView` method is executed after view rendering completes. If an exception occurs, the exception is available using the `throwable` property of the Interceptor trait. ## 8.5.2 Matching Requests with Interceptors As mention in the previous section, by default an interceptor will match only requests to the associated controller by convention. However you can configure the interceptor to match any request using the `match` or `matchAll` methods defined in the Interceptor API. The matching methods return a Matcher instance which can be used to configure how the interceptor matches the request. For example the following interceptor will match all requests except those to the `login` controller:
    class AuthInterceptor {
      AuthInterceptor() {
        matchAll()
        .excludes(controller:"login")
      }

      boolean before() {
        // perform authentication
      }
    }
You can also perform matching using named argument:
    class LoggingInterceptor {
      LoggingInterceptor() {
        match(controller:"book", action:"show") // using strings
        match(controller: ~/(author|publisher)/) // using regex
      }

      boolean before() {
        ...
      }
    }
You can use any number of matchers defined in your interceptor. They will be executed in the order in which they have been defined. For example the above interceptor will match for all of the following: when the `show` action of `BookController` is called when `AuthorController` or `PublisherController` is called All named arguments except for `uri` accept either a String or a Regex expression. The `uri` argument supports a String path that is compatible with Spring’s AntPathMatcher. The possible named arguments are: `namespace` - The namespace of the controller `controller` - The name of the controller `action` - The name of the action `method` - The HTTP method `uri` - The URI of the request. If this argument is used then all other arguments will be ignored and only this will be used. ## 8.5.3 Ordering Interceptor Execution Interceptors can be ordered by defining an `order` property that defines a priority. For example:
    class AuthInterceptor {

      int order = HIGHEST_PRECEDENCE

      ...
    }
The default value of the `order` property is 0. Interceptor execution order is determined by sorting the `order` property in an ascending direction and executing the lowest numerically ordered interceptor first. The values `HIGHEST_PRECEDENCE` and `LOWEST_PRECEDENCE` can be used to define filters that should should run first or last respectively. Note that if you write an interceptor that is to be used by others it is better increment or decrement the `HIGHEST_PRECEDENCE` and `LOWEST_PRECEDENCE` to allow other interceptors to be inserted before or after the interceptor you are authoring:
    int order = HIGHEST_PRECEDENCE + 50

    // or

    int order = LOWEST_PRECEDENCE - 50
To find out the computed order of interceptors you can add a debug logger to `logback.groovy` as follows:
    logger 'grails.artefact.Interceptor', DEBUG, ['STDOUT'], false
You can override any interceptors default order by using bean override configuration in `grails-app/conf/application.yml`:
    beans:
      authInterceptor:
        order: 50
Or in `grails-app/conf/application.groovy`:
    beans {
      authInterceptor {
        order = 50
      }
    }
Thus giving you complete control over interceptor execution order. | Quick Reference (hide)