Reputation: 175
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
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