UnsupportedOperationException when using Method Pointer Operator and MockFor - groovy

I had a test. It was using mockFor and was working and I was happy. Until something changed and I was forced to use a method pointer operator, and then my happiness was a just a memory.
Here a constricted example of the problem
import groovy.mock.interceptor.*
// I am testing againts a interface, not an actual class
// this is not negociable.
interface Person {
void sayHello(name);
}
// Setup (can do whatever I need)
def personMock = new MockFor(Person)
personMock.demand.sayHello { name -> println "Hello $name" }
def person = personMock.proxyInstance()
// End Setup
// Exercise (can not change)
def closureMethod = person.&sayHello.curry("Groovy!")
closureMethod()
// End Exercise
personMock.verify(person)
Which would be the safest and simplest way to fix the test?
Currently, the test fails with java.lang.UnsupportedOperationException

Even when I am testing against a Interface, nothing prevents me from creating a mock class that implements the interface and do a poor-men verify demands.
import groovy.mock.interceptor.*
// I am testing against a interface, not an actual class
// this is not negociable.
interface Person {
void sayHello(name);
}
class PersonMock implements Person {
def calls = []
void sayHello(name) { calls << "sayHello" }
}
// Setup (can do whatever I need)
def person = new PersonMock()
// End Setup
// Exercise (can not change)
def closureMethod = person.&sayHello.curry("Groovy!")
closureMethod()
// End Exercise
assert person.calls == ['sayHello']

Related

Groovy - interceptor of ProxyMetaClass does not affect inner methods calls

The code snippet is from the book < Groovy in action 2nd >, with minor modifications.
1 this code works as expected
package test
class InspectMe {
int outer(){
return inner()
}
int inner(){
return 1
}
}
def tracer = new TracingInterceptor(writer: new StringWriter())
def proxyMetaClass = ProxyMetaClass.getInstance(InspectMe)
proxyMetaClass.interceptor = tracer
InspectMe inspectMe = new InspectMe()
inspectMe.metaClass = proxyMetaClass
inspectMe.outer()
println(tracer.writer.toString())
output:
before test.InspectMe.outer()
before test.InspectMe.inner()
after test.InspectMe.inner()
after test.InspectMe.outer()
2 but this code's output is different
package test
class InspectMe {
int outer(){
return inner()
}
int inner(){
return 1
}
}
def tracer = new TracingInterceptor(writer: new StringWriter())
def proxyMetaClass = ProxyMetaClass.getInstance(InspectMe)
proxyMetaClass.interceptor = tracer
InspectMe inspectMe = new InspectMe()
proxyMetaClass.use(inspectMe){
inspectMe.outer()
}
println(tracer.writer.toString())
output:
before test.InspectMe.outer()
after test.InspectMe.outer()
It seems TracingInterceptor dosen't intercept inner methods in the second code.
Maybe it's normal behavior, But it seems to me like a bug.
Can somebody please explain this?
I don't know if this is a bug or not, but I can explain why this different behavior happens. Let's start with analyzing what InspectMe.outer() method implementation looks like at the bytecode level (we decompile .class file):
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.BytecodeInterface8;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
public class InspectMe implements GroovyObject {
public InspectMe() {
CallSite[] var1 = $getCallSiteArray();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}
public int outer() {
CallSite[] var1 = $getCallSiteArray();
return !__$stMC && !BytecodeInterface8.disabledStandardMetaClass() ? this.inner() : DefaultTypeTransformation.intUnbox(var1[0].callCurrent(this));
}
public int inner() {
CallSite[] var1 = $getCallSiteArray();
return 1;
}
}
As you can see, the outer() method tests the following predicate
!__$stMC && !BytecodeInterface8.disabledStandardMetaClass()
and if it evaluates to true, it invokes directly this.inner() method avoiding Groovy's MOP (meta-object protocol) layer (no metaclass involved in this case). Otherwise, it invokes var1[0].callCurrent(this) which means that inner() method gets invoked through Groovy's MOP with metaclass and interceptor involved in its execution.
The two examples you have shown in the question present a different way of setting metaclass field. In the first case:
def tracer = new TracingInterceptor(writer: new StringWriter())
def proxyMetaClass = ProxyMetaClass.getInstance(InspectMe)
proxyMetaClass.interceptor = tracer
InspectMe inspectMe = new InspectMe()
inspectMe.metaClass = proxyMetaClass // <-- setting metaClass with DefaultGroovyMethods
inspectMe.outer()
println(tracer.writer.toString())
we are invoking inspectMe.setMetaClass(proxyMetaClass) method using Groovy's MOP layer. This method gets added to InspectMe class by DefaultGroovyMethods.setMetaClass(GroovyObject self, MetaClass metaClass).
Now, if we take a quick look at how this setMetaClass method is implemented we will find something interesting:
/**
* Set the metaclass for a GroovyObject.
* #param self the object whose metaclass we want to set
* #param metaClass the new metaclass value
* #since 2.0.0
*/
public static void setMetaClass(GroovyObject self, MetaClass metaClass) {
// this method was introduced as to prevent from a stack overflow, described in GROOVY-5285
if (metaClass instanceof HandleMetaClass)
metaClass = ((HandleMetaClass)metaClass).getAdaptee();
self.setMetaClass(metaClass);
disablePrimitiveOptimization(self);
}
private static void disablePrimitiveOptimization(Object self) {
Field sdyn;
Class c = self.getClass();
try {
sdyn = c.getDeclaredField(Verifier.STATIC_METACLASS_BOOL);
sdyn.setBoolean(null, true);
} catch (Throwable e) {
//DO NOTHING
}
}
It invokes at the end private method disablePrimitiveOptimization(self). This method is responsible for assigning true to __$stMC class field (the constant Verifier.STATIC_METACLASS_BOOL stores __$stMC value). What does it mean in our case? It means that the predicate in outer() method:
return !__$stMC && !BytecodeInterface8.disabledStandardMetaClass() ? this.inner() : DefaultTypeTransformation.intUnbox(var1[0].callCurrent(this));
evaluates to false, because __$stMC is set to true. And in this case inner() method gets executed via MOP with metaClass and interceptor.
OK, but it explains the first case that works as expected. What happens in the second case?
def tracer = new TracingInterceptor(writer: new StringWriter())
def proxyMetaClass = ProxyMetaClass.getInstance(InspectMe)
proxyMetaClass.interceptor = tracer
InspectMe inspectMe = new InspectMe()
proxyMetaClass.use(inspectMe){
inspectMe.outer()
}
println(tracer.writer.toString())
Firstly, we need to check what does proxyMetaClass.use() look like:
/**
* Use the ProxyMetaClass for the given Closure.
* Cares for balanced setting/unsetting ProxyMetaClass.
*
* #param closure piece of code to be executed with ProxyMetaClass
*/
public Object use(GroovyObject object, Closure closure) {
// grab existing meta (usually adaptee but we may have nested use calls)
MetaClass origMetaClass = object.getMetaClass();
object.setMetaClass(this);
try {
return closure.call();
} finally {
object.setMetaClass(origMetaClass);
}
}
It's pretty simple - it replaces metaClass for the time of closure execution and it sets the old metaClass back when closure's execution completes. Sounds like something similar to the first case, right? Not necessarily. This is Java code and it invokes object.setMetaClass(this) method directly (the object variable is of type GroovyObject which contains setMetaClass method). It means that the field __$stMC is not set to true (the default value is false), so the predicate in outer() method has to evaluate:
BytecodeInterface8.disabledStandardMetaClass()
If we run the second example we will see that this method call returns false:
And that is why the whole expression
!__$stMC && !BytecodeInterface8.disabledStandardMetaClass()
evaluates to true and the branch that invokes this.inner() directly gets executed.
Conclusion
I don't know if it was intended or not, but as you can see dynamic setMetaClass method disables primitive optimizations and continues using MOP, while ProxyMetaClass.use() sets the metaClass keeping primitive optimizations enabled and caused a direct method call. I guess this example shows a corner case no one thought about when implementing ProxyMetaClass class.
UPDATE
It seems like the difference between these two methods exists because ProxyMetaClass.use() was implemented in 2005 for Groovy 1.x and it got updated for the last time in 2009. This __$stMC field was added in 2011 and the DefaultGroovyMethods.setMetaClass(GroovyObject object, Closure cl) was introduced in 2012 according to its javadoc that says this method is available since Groovy 2.0.

Mocking a singleton in Groovy

In Groovy / Spock I can mock a class by doing:
def theClass = Mock(TheClass.class)
and then wire that instance into the class under unit test. What about if I want to mock a class that has been annotated as a #Singleon
Here is a little tool class you can use:
package de.scrum_master.stackoverflow
import java.lang.reflect.Field
import java.lang.reflect.Modifier
class GroovySingletonTool<T> {
private Class<T> clazz
GroovySingletonTool(Class<T> clazz) {
this.clazz = clazz
}
void setSingleton(T instance) {
// Make 'instance' field non-final
Field field = clazz.getDeclaredField("instance")
field.modifiers &= ~Modifier.FINAL
// Only works if singleton instance was unset before
field.set(clazz.instance, instance)
}
void unsetSingleton() {
setSingleton(null)
}
void reinitialiseSingleton() {
// Unset singleton instance, otherwise subsequent constructor call will fail
unsetSingleton()
setSingleton(clazz.newInstance())
}
}
Just call setSingleton(Mock(TheClass)). For more info see this answer, I do not want to repeat the whole sample code here.
Feel free to ask follow-up questions if there is anything you do not understand.
You can use global mocks
def publisher = new Publisher()
publisher << new RealSubscriber() << new RealSubscriber()
def anySubscriber = GroovyMock(RealSubscriber, global: true)
when:
publisher.publish("message")
then:
2 * anySubscriber.receive("message")

How to access Closure properties from inside closure code?

I'm banging my head against this wall for more than a week now, let me explain briefly what I'm trying to achieve.
I have a DSL defined like this (brief example)
TestingSpec
.newInstance()
.sayHello() --> print "Hello "+something
.sayGoddbye() --> print "Goddbye"+something
Note the something in there that is not passed anywhere intentionally, because I want to limit the scope of use of my DSL by the will be users, so what I actually want is to somehow "inject" the something in that DSL instance programmatically. This is being done by using a Closure.
Myscript.execute( {
TestingSpec
.newInstance()
.sayHello() --> print "Hello "+something
.sayGoddbye() --> print "Goddbye"+something
})
and MyScript will invoke it by passing the something value to it, either by passing a parameter, or by adding a property or by adding a Binding (don't know what's the best, really)
close.call("Toni")
close.metaClass.something = "Toni"
def binding = new Binding()
binding.setVariable("something", "Toni")
close.setBinding(binding)
But now I'm stuck in what I thought it was going to be easy, how from the TestingSpec code can I access the Closure something? For instance
public newInstance() {
def instance = new TestingSpec()
instance.something = *MY CLOSURE SOMETHING*
return instance
}
I've tried several options, like messing with the this, owner and delegate of the closure, but couldn't do it.
Any hint will be very welcome...
Cheers.
I don't think that's doable. TestingSpec is too high on the stack to be aware he is being invoked from a closure. I'd like to suggest two solutions
1. Pass something to TestingSpec programmatically.
Myscript.execute( {
TestingSpec
.newInstance(something)
.sayHello() --> print "Hello "+something
.sayGoddbye() --> print "Goddbye"+something
})
2. Make the TestingSpec instance be created by MyScript
I like this solution more. It is about MyScript.execute({}) being responsible for creating and handling the lifecycle of TestingSpec:
class TestingSpec {
def something
def sayHello() {
println "Hello " + something
this
}
def sayGoddbye() {
println "Goddbye " + something
this
}
}
class Myscript {
static TestingSpec testingSpec
static execute(closure) {
def binding = new Binding(something: 'test for echo')
testingSpec = new TestingSpec(something: binding.something)
binding.testingSpec = testingSpec
closure.binding = binding
closure()
}
}
Myscript.execute( {
testingSpec // this is an instance, and not a static call
.sayHello() // print "Hello "+something
.sayGoddbye() // print "Goddbye"+something
})
Output:
$ groovy Spec.groovy
Hello test for echo
Goddbye test for echo
3. Delegate the closure to testingSpec
If you set the closure delegate to testingSpec, you can invoke its methods without referencing testingSpec directly, providing a very clean code. Note i also updated the example to remove MyScript:
class TestingSpec {
static TestingSpec testingSpec
static execute(closure) {
def binding = new Binding(something: 'test for echo')
testingSpec = new TestingSpec(something: binding.something)
binding.testingSpec = testingSpec
closure.delegate = testingSpec
closure.binding = binding
closure()
}
def something
def sayHello() {
println "Hello " + something
this
}
def sayGoddbye() {
println "Goddbye " + something
this
}
}
TestingSpec.execute( {
sayHello() // print "Hello "+something
sayGoddbye() // print "Goddbye"+something
})
4. Inject testingSpec as a parameter into your closure
As per your answer, a simple suggestion: consider giving a testingSpec var that you've built yourself to the user, since it allows more control and customization to you. Think a simple inversion of control (this allows testingSpec to see dynamic variables in the closure's binding):
.withDistinctNames({ testingSpec ->
testingSpec
.from(name)
.withAddress(email)
.sendEmail(template)
})
With a full test:
class TestingSpec {
def commands = []
static newInstance(listOfNames) {
new TestingSpec()
}
def sayHello() { commands << "sayHello"; this }
def waveGoddbye() { commands << "waveGoddbye"; this }
def withAddress(address) { commands << "withAddress $address"; this }
def sendEmail(template) { commands << "sendEmail $template"; this }
def withDistinctNames(closure) {
commands << "withDistinctNames"
closure.binding = new Binding(address: "sunset boulevard", template: 'email is $email')
closure(this)
this
}
}
test = TestingSpec
.newInstance([:])
.sayHello()
.withDistinctNames({ me ->
me
.withAddress(address)
.sendEmail(template)
})
.waveGoddbye()
assert test.commands == [
'sayHello',
'withDistinctNames',
'withAddress sunset boulevard',
'sendEmail email is $email',
'waveGoddbye'
]
I finally reach a solution to my problem that while not ideal it's "elegant" enough and "easy" to understand by would-be users of my DSL. So, what I want to do is allow the DSL users to write things like this:
TestingSpec
.newInstance()
.from(listOfNames)
.sayHello()
.withDistinctNames({
TestingSpec
.newInstance()
.from(*****) <---- problem
.withAddress()
.sendEmail(template)
})
.waveGoddbye()
There could be a number of with methods that basically serve as a filter+loop, so in this example it will filter the names to be unique and then apply the Closure to each name in turn. Of course this would be extremely easy to do by just doing
.withDistinctNames({
TestingSpec
.newInstance()
.from(it)
.withAddress()
.sendEmail(template)
})
or for more complicated cases
.withDistinctNames({ name, email, template ->
TestingSpec
.newInstance()
.from(name)
.withAddress(email)
.sendEmail(template)
})
The prob is I don't know who is going to use this DSL, it may not be people familiar with closures, parameters, functions, whatnots, it may be people even from outside my organization, so my goal was to keep it simple by passing the needed variables from the outer Spec to the inner Spec. In my TestingSpec implementation I would have:
public TestingSpec withAll(Closure k, Closure f) { // withAll is used by all with* methods
def result = k.call(root) // root is the entire listOfNames
def results = result
.collect {
// HERE'S THE PROBLEM, HOW TO INJECT ALL THE PARAMETERS INTO THE INNER SPEC?
f.call(it) // this line passes vars to the Closure, not the inner Spec, and I found no way for the Closure itself to inject them in the Spec
}
return this;
}
After I saw it was impossible to inject params in the inner Spec itself (that is yet to be instantiated) I tried to pass them to the Closure and from there to the Spec, like this:
.withDistinctNames({
TestingSpec
.newInstance()
.from(this) <-------------------
.withAddress()
.sendEmail(template)
})
I supposed that this would be the outer Spec that contains all the info I need, but it was not. I tried with this, this.thisObject, this.owner, this.delegate.
But then, with the help of the 3rd above suggestion I ended up doing this:
public TestingSpec withAll(Closure k, Closure f) {
f = f.rehydrate(f.getDelegate(), f.getOwner(), this)
def result = k.call(root)
def results = result
.collect {
this.parameters = [whatever I need]
f.call()
}
return this;
}
This way the this in the DSL is actually the outer Spec, so the users can now use the more intuitive "this" keyword. To avoid confusion I got rid of the .from() method, like this:
TestingSpec
.newInstance(listOfNames)
.sayHello()
.withDistinctNames({
TestingSpec
.newInstance(this) // my newInstance implementation can parse all the parameters as it wishes
.withAddress()
.sendEmail(template)
})
.waveGoddbye()
While it's not ideal is close enough, from the perspective of the potential users, I think. If somebody has suggestions please let me know.
Thanks Will P and all.
After working on a small similar Groovy DSL tool recently and digging a bit into griffon and swing and other material I currently ended with the following, that I submit as another suggestion to the answer.
Any comment/suggestion will be greatly appreciated.
IMHO a clear separation between the domain model (a Model class) , and the support classes (building, aggregation , context sharing, and filtering part of the model, at least a Builder class) is one of the key elements
to have a simple and efficient model. This is the pattern used in groovy swing and griffon and showed to be very flexible.
It allows constructs with each {}, with {} and collection operations which are clean and understandable enough,
and mostly without chaining operations (ie adding an annoying return this at the end of each operation).
Like here for example (source code at the end, MSys is a Facade to the underlying system):
MSys.with {
model.each {
it.sayHello
it.sayGoodBye
it.setAddress randomAddress(it.name);
it.sendEmail
}
println " Hello counts"
model.each {
def key = it.name
def value = MSys.context[key]
println "Counter for ${key} = ${value}"
}
}
or
MSys.model.each {
it.with {
sayHello
sayGoodBye
setAddress randomAddress(name) ;
sendEmail
}
}
or
MSys.eachModelDo {
sayHello
sayGoodBye
setAddress randomAddress(it.name);
sendEmail
}
or ...
(lot of possibilities)
It also allows to have some shared context very easily (in the example , context is a Map shared between all the Model elements where almost anything could be put, connection information, user preferences, cache etc.),
and to hide all the boiler plate to the user by putting it in another class/script .
The responsibilities would be :
SpecModel : Domain model : say hello, goodbye, properties etc
SpecBuilder : creates models (from a list in the example), holds shared context (a map) and eventually take care of the closure delegate context for some operations
This separation is important to deal with set operations on one side and entity (model) operations on the other.
Apart from beeing a builder, from a user POV it is a facade
and from a developer POV BTW it should be a Facade to several classes including the builder -but better start simple.
The next step would be to integrate FactoryBuilderSupport in this builder in order to benefit from Groovy DSL builder facilities, but this one big step beyond and I'm not comfortable with that yet ... (WIP right now)
Few Groovy recaps that you certainly already know but part of the problem if you want a light syntax :
In Groovy , , ; and () are optional except when there is a conflict.
Even where there is no direct conflict, the delegation strategy is not always direct and
run time errors are not always clear (see link on closures doc below)
Having a public getter method for properties, allows the use of property like access methods without the (),
the get and set prefixes are inferred
ie with a method like
public getSendEmail() {
println "email for ${name}"
}
you can use the syntax :
myObject sendEmail
Groovy assumes a property getter call and do the rest.
This helps removing the () in the dsl syntax.
The context is the delegate context of the closure it not the this
When you use closures, you use it to reference the object you are working on in the closure
(ie the receiver of the message).
Example:
[1, 2, 3].each { println it }
is ok
If you haved used
[1, 2, 3].each { println this }
you would have print a reference to the outer object, the console in groovy console
(Which IIRC was one of the problem you had in your first post)
This is well explained in the Groovy Closures doc :
(excerpt:)
this : the enclosing class where the closure is defined
owner : the enclosing object where the closure is defined, a class or a closure
delegate : third party object where methods calls or properties are resolved whenever the receiver of the message is not defined
The message delegation strategy (explained in the same document) is not always direct and this was your real problem I think.
That said, another key point in a DSL is the coherence from a user POV.
This means consistence in data access patterns and here the standard Groovy collections (Lists, maps each{} etc) can help a lot.
Plus it can be a huge plus for power users.
Syntactic sugar methods like eachModelDo can easily be done on a builder/facade class:
MSys.eachModelDo {
sayHello
sayGoodBye
setAddress randomAddress(it.name);
sendEmail
}
NB: eachModelDo is very simple but a bit tricky to debug
At one point it "worked" well without accessing correct variables :(
I have the feeling that something is wrong here (?) or at least it should be improved (comments welcome)
/**
* syntactic sugar
* direct access without 'it' (optional)
*/
public SpecBuilder eachModelDo(closure) {
model.each {
closure.delegate = it;
closure(it)
}
}
Bellow is the source code of a small test I did that you can cut and paste in a groovy console
The only part visible to the user should be the method Demo.run()
All the other stuff should be hidden
Any comments are welcome
/**
* The builder build Specs and defines utility methods, filters
* It shares its context with all elements in the domain
*/
class SpecBuilder {
/** the context will be shared with all domain model objects */
private context
/** model = all the domain model objects */
private model
/** getters / setters */
public getModel() { return model }
public getContext() {
return context
}
/** constructors and helpers */
public SpecBuilder(aContext) {
context = aContext
}
/** Default constructor forbidden */
private SpecBuilder() {}
public from(aList, closure) {
from(aList);
model.each { closure(it) }
return this
}
public from(aList) {
model = aList.collect { new SpecModel(it, context) }
return this
}
/* TODO filters etc */
/** stats: print counters */
public stats() {
println " Hello counts"
model.each {
def key = it.name
def value = this.context[key]
println "Counter for ${key} = ${value}"
}
}
/**
* syntactic sugar
* direct access without 'it' (optional)
*/
public SpecBuilder eachModelDo(closure) {
model.each {
closure.delegate = it;
closure(it)
}
}
}
/**
* The Spec Domain Model
*/
class SpecModel {
/** the shared context */
private context;
/** other properties */
private name;
public address;
/** getters and setters */
public getName() { return name }
public void setAddress(a) { address = a }
public getAddress() { return address }
public sayHello() { return getSayHello }
public sayGoodBye() { return getSayGoodBye }
public sendEmail() { return getSendEmail }
/** constructors */
public SpecModel(aName, aContext) {
name = aName
context = aContext
}
/** Default constructor forbidden */
private SpecModel() {}
/** method used like properties, without 'get' and ()*/
public getSayHello() {
println "(!) hello ${name}"
context[name] = context.get(name,0) +1;
}
public getSayGoodBye() {
println "goodBye ${name} !"
}
public getSendEmail() {
println "email for ${name}"
if (address)
println "Address ${address}"
}
public getPrintContext() {
println context
}
/**
* Returns info to caller
*/
public gatherInfo() {
"info for ${name} : ${new java.util.Random().nextInt(50000)}"
}
}
class Demo {
// several Groots here to test uniques ...
def customers = ['Groot', 'Gamora', 'Groot', 'Groot', 'Groot', 'Star-Lord']
/**
* Utility function who generates a random address
* #param name will prefix the address
* #return the address
*/
public randomAddress(def name) {
// good places ... :)
def places = [
"Grande Rue",
"Cours Emile Zola",
"Place Antonin Poncet",
"Rue de la République",
"Boulevard de la Croix Rousse",
"Place Bellecour"
]
def random = new java.util.Random();
return new StringBuilder().append(name).append(" ... ")
// why not 42?
.append( random.nextInt(155)).append(" ")
.append( places[random.nextInt(places.size())] )
.toString();
}
/**
* ======================== Main user program =========================
*/
def run() {
/** the shared context */
def context = [:].asSynchronized() // In case of multi threading access
/** The whole system From a user POV : a big façade */
def MSys = new SpecBuilder(context).from(customers) ;
println "*** 1 ==================== "
/** First form */
MSys.model.each {
it.with {
sayHello
sayGoodBye
setAddress randomAddress(name) ;
sendEmail
}
}
/** other forms
* MSys.with{ is handy
* one could write MSys... on each line
*/
MSys.with {
println "*** 2 ==================== "
model.each { it.sayHello };
println "*** 3 ==================== "
model.with { println " a Model entry = ${it.name} + ${it.address}" }
println "*** 4 ==================== "
/** false not to mutate the model !!! */
model.unique(false, { a, b -> a.name <=> b.name }).each { it.sayHello }
println "*** 5 ==================== "
context['aKey'] = 42
// verify that each entity has the same context
model.with { println " a shared context for ${it.name} : " + it.context }
println "*** Stats ================ "
/** stats on the shared context */
stats()
}
println "*** 6 Info to process ======== "
/** Gather info to process (addresses)*/
def data = MSys.model.inject([:]) { result, entity ->
result[entity.name] = entity.address
result
}
println data
MSys.with {
println "*** 7 ==================== "
model.each {
it.sayHello
it.sayGoodBye
it.setAddress randomAddress(it.name);
it.sendEmail
}
println "*** 8 ==================== "
println " Hello counts"
model.each {
def key = it.name
def value = MSys.context[key]
println "Counter for ${key} = ${value}"
}
}
println "*** 9 ==================== "
MSys.eachModelDo {
sayHello
sayGoodBye
setAddress randomAddress(it.name);
sendEmail
}
}
}
new Demo().run()
/* end of script */

Groovy Copying / Combining MetaMethods From Multiple Objects

I have two classes. At runtime, I want to "clone" the methods of one object, over to another. Is this possible? My failed attempt using leftshift is shown below.
(Note: I also tried currMethod.clone() with the same result.)
class SandboxMetaMethod2 {
String speak(){
println 'bow wow'
}
}
class SandboxMetaMethod1{
void leftShift(Object sandbox2){
sandbox2.metaClass.getMethods().each{currMethod->
if(currMethod.name.contains("speak")){
this.speak()
this.metaClass."$currMethod.name" = currMethod
this.speak()
}
}
}
String speak(){
println 'woof'
}
}
class SandboxMetaMethodSpec extends Specification {
def "try this"(){
when:
def sandbox1 = new SandboxMetaMethod1()
def sandbox2 = new SandboxMetaMethod2()
sandbox1 << sandbox2
then:
true
}
}
//Output
woof
speak
woof
Per Request, I am adding background as to the goal / use case:
It's very much like a standard functional type of use case. In summary, we have a lot of methods on a class which applies to all of our client environments (50-100). We apply those to process data in a certain default order. Each of those methods may be overridden by client specific methods (if they exist with the same method name), and the idea was to use the approach above to "reconcile" the method set. Based on the client environment name, we need a way to dynamically override methods.
Note: Overriding methods on the metaclass is very standard (or should i say, it's the reason the amazing capability exists). And it works if my method exists as text like String currMethod = "{x-> x+1}", then i just say this.metaClass."$currMethodName" = currMethod. My challenge in this case is that my method is compiled and exists on another class, rather than being defined as text somewhere.
The goal of having all the custom methods compiled in client-specific classes at build time was to avoid the expense of compilation of these dynamic methods at runtime for each calculation, so all client-specific methods are compiled into a separate client-specific JAR at build time. This way also allows us to only deploy the client-specific code to the respective client, without all the other clients calculations in some master class.
I hope that makes sense.
New Approach, in Response to Jeremie B's suggestion:
Since I need to choose the trait to implement by name at runtime, will something like this work:
String clientName = "client1"
String clientSpeakTrait = "${clientName}Speak"
trait globalSpeak {
String speak() {
println 'bow wow'
}
}
trait client1Speak {
String speak() {
println 'woof'
}
}
def mySpeaker = new Object().withTraits globalSpeak, clientSpeakTrait
A basic example with Traits :
trait Speak {
String speak() {
println 'bow wow'
}
}
class MyClass {
}
def instance = new MyClass()
def extended = instance.withTraits Speak
extended.speak()
You can choose which trait to use at runtime :
def clientTrait = Speak
def sb = new Object().withTraits(clientTrait)
sb.speak()
And dynamically load the trait with a ClassLoader :
def clientTrait = this.class.classLoader.loadClass "my.package.${client}Speak"
def sb = new Object().withTraits(clientTrait)

Groovy - can a method defined in an Interface have default values?

If the following is entered in Eclipse/STS (with groovy):
interface iFaceWithAnIssue {
def thisIsFine(a,b,c)
def thisHasProblems(alpha='va')
}
The only line that complains is the one trying to use a default value. I can not tell from the codehaus site if this is supported or not.
The IDE error is:
Groovy:Cannot specify default value for method parameter
So this makes me think it is not supported. As there will be multiple implementations, I wanted to use an interface here. I don't really need the default value in the interface, but there is an error trying to fulfill the interface contract if the implementation class then tries to default this argument. Is there any way?
No, you cannot.
When you define a default value, Groovy actually creates multiple methods in your class, so for example:
class Test {
void something( a=false ) {
println a
}
}
Actually creates
public void something(java.lang.Object a) {
this.println(a)
}
and
public void something() {
this.something(((false) as java.lang.Object))
}
This can't be done as it stands in Interfaces.
You could do:
interface iFaceWithAnIssue {
def thisHasProblems()
def thisHasProblems(alpha)
}
Then
class Test implements iFaceWithAnIssue {
// This covers both Inteface methods
def thisHasProblems(alpha='va') {
// do something
}
}

Resources