Marcin
Marcin

Reputation: 175

Replacing invokeMethod to intercept Controller methods

I would like intercept all methods in all controllers by replacing the invokeMethod closure of the ExpandoMetaClass.

I created a new grails Project (2.3.5). Created a new Controller, called AccountController:

package com.invoke.test
class AccountController {
    def index() {
        System.out.println("Index Called")
    }
}

Then created an additional BootStrap called SecurityBootStrap:

class SecurityBootStrap {

def grailsApplication

def verifyMethodAccess = { String name, args ->
    log.info "Called method ${name}"
    def method = delegate.metaClass.getMetaMethod(name, args)
    if (method) {
        return method.invoke(delegate, args)
    }
    return null
}

def init = { servletContext ->
    grailsApplication.controllerClasses.each { controllerClass ->
        controllerClass.clazz.metaClass.invokeMethod = verifyMethodAccess
        log.info "Replaced the invokeMethod closure on ${controllerClass.clazz}"
    }
}
}

After starting the application, the log is looking promising:

|Running Grails application
2014-06-26 15:07:26,476 [localhost-startStop-1] INFO  conf.SecurityBootStrap  - Replaced the invokeMethod closure on class grails.plugin.databasemigration.DbdocController
2014-06-26 15:07:26,477 [localhost-startStop-1] INFO  conf.SecurityBootStrap  - Replaced the invokeMethod closure on class com.invoke.test.AccountController
|Server running. Browse to http://localhost:8080/InvokeTest

But, when calling http://localhost:8080/InvokeTest/account/index the log look like:

Index Called

I expected it to be:

Called method index
Index Called

Thanks in advance

Upvotes: 0

Views: 322

Answers (1)

Jeff Scott Brown
Jeff Scott Brown

Reputation: 27255

You could do this with compile time meta programming but you can't do this with runtime metaprogramming. A limitation of Groovy's runtime metaprogramming is that it only applies to method calls which are initiated from Groovy. Much of the Grails framework is written in Java.

Example:

class Widget {
    def getTheAnswer() {
        42
    }
}

Widget.metaClass.getTheAnswer = { ->
    2112
}

When Groovy code invokes new Widget().getTheAnswer() the result will be 2112. When Java code invokes new Widget().getTheAnswer(); the result will be 42.

Upvotes: 1

Related Questions