Adding properties from Java to groovy objects
I want to be able to add properties to an instance of a string object using the metaprogramming capabilities of groovy from Java
To do this from groovy is simple:
class GroovyClass {
def getDynamicString() {
def myString = "hello"
myString.MetaClass.dynamicProperty = "there"
return myString
}
}
This is my Spock test case:
def "should add dynamic property"() {
GroovyClass groovyClass = new GroovyClass()
when:
def theString = groovyClass.getDynamicString()
then:
theString == "hello"
theString.dynamicProperty == "there"
}
But I want to do the same thing from Java and run it through the same tests As far as I know, groovy adds additional properties and methods (such as getmetaclass) to JDK classes like string, but I'm not sure how and when it does this I found the following solution to work, but initializing the groovy shell and writing the metaprogramming code as a string seems cumbersome
public String getDynamicString()
{
String myString = "hello";
groovyshell shell = new groovyshell();
shell.setVariable("myString",myString);
shell.setVariable("theDynamicPropertyValue","there");
shell.evaluate("myString.MetaClass.dynamicProperty = theDynamicPropertyValue");
return myString;
}
Is there any way to avoid using shell Do this in the case of evaluate – that is, by calling groovy library methods directly from Java?
Solution
So, in view of this groovy script:
def a = 'A String' Decorator.decorate( a,'foo','bar' ) assert a == 'A String' assert a.class == String assert a.foo == 'bar'
Then we can write the Java decorator class like this:
import org.codehaus.groovy.runtime.HandleMetaClass ;
import org.codehaus.groovy.runtime.InvokerHelper ;
public class Decorator {
public static void decorate( Object o,String name,Object value ) {
HandleMetaClass hmc = new HandleMetaClass( InvokerHelper.getMetaClass( o ),o ) ;
hmc.setProperty( name,value ) ;
}
}
Then, if we compile the Java class and run the groovy script, all assertions should pass
