My understanding is that there are two obvious places in a Grails app where one can do meta-programming:
init
closure of Bootstrap.groovy
doWithDynamicMethods
closure of a pluginThe meta-programming I'm referring to here should be visible throughout the application, typical examples include adding (or replacing) methods of 3rd party classes.
String.metaClass.myCustomMethod = { /* implementation omitted */ }
The disadvantage of (1), is that the metaprogramming won't be applied when the application is dynamically reloaded. The disadvantage of (2) is that I need to create and maintain an entire plugin just for the sake of a little metaprogramming.
Is there a better place to do this kind of metaprogramming?
Following Ted's suggestion below, I added the following class to src/groovy
package groovy.runtime.metaclass.java.lang
/**
* Adds custom methods to the String class
*/
class StringMetaClass extends DelegatingMetaClass {
StringMetaClass(MetaClass meta) {
super(meta)
}
Object invokeMethod(Object object, String method, Object[] arguments) {
if (method == 'hasGroovy') {
object ==~ /.*[Gg]roovy.*/
} else {
super.invokeMethod object, method, arguments
}
}
}
Then restarted the app and ran the following code in the Grails console:
assert 'mrhaki loves Groovy'.hasGroovy()
I got the following exception
groovy.lang.MissingMethodException: No signature of method:
java.lang.String.hasGroovy() is applicable for argument types: () values: []
Am I doing something wrong or is there a reason this doesn't work in a Grails app?
Runtime metaprogramming enables us to alter the existing properties and methods of a class. Also, we can attach new properties and methods; all at runtime. Groovy provides a few methods and properties that help to alter the behavior of a class at runtime.
semicolons are optional in Groovy, you can omit them, and it's more idiomatic to remove them.
To create an object by using positional parameters, the respective class needs to declare one or more constructors. In the case of multiple constructors, each must have a unique type signature. The constructors can also added to the class using the groovy. transform.
Check out the Delegating MetaClass, it's part of groovy and makes your metaclass changes part of the metaclass that's used on every instance of that class right from the start. It operates on a simple convention and even works outside of grails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With