the sample progame when i try to run using the expandometaclass technique it give me two output one the desired result second one "null" as output, from where null is picked up ?
class testA {
static def X(def var) {
Y(var)
}
static def Y(def var) {
println var
}
}
testA.metaClass.static.newMethod = {z_var -> X(z_var) }
println testA.newMethod("anish")
output:
anish
**null**
why this progranme also print null as output
The null is the return value from newMethod. In case you don't want this to be printed remove the println from your line
println testA.newMethod("anish")
Related
Is there a way to skip MissingPropertyException while using GroovyShell.evaluate?
def sharedData = new Binding()
def shell = new GroovyShell(sharedData)
shell.evaluate("a=5; b=1") // works fine
// How to not get MissingPropertyException, or silently ignore property 'a'
shell.evaluate("a; b=1") // MissingPropertyException for 'a'
I know about the Expando solution, is there a way to do it without defining a class?
A very minimal approach would be to override Binding.getVariable.
Note that this is very straight forward: "all exceptions" are ignored - you might want to have better logging or more accurate error handling.
import groovy.lang.*
class NoOpBinding extends Binding {
#Override
Object getVariable(String name) {
try {
return super.getVariable(name)
}
catch (Throwable t) {
println "Ignoring variable=`$name`"
return null
}
}
}
def shell = new GroovyShell(new NoOpBinding())
shell.evaluate("a; b=1") // MissingPropertyException for 'a'
// → Ignoring variable=`a`
println shell.getVariable('b')
// → 1
You could do something like this:
def binding = [:].withDefault { }
def shell = new GroovyShell(binding as Binding)
shell.evaluate 'a; b=1'
I am trying to make my own Dsl and was playing around with different styles of closures in groovy.
I've stumbled upon follwing snippet:
myClosure {
testProperty: "hello!"
}
But can't figure out if this a valid code and how can I access then this testProperty. Is it valid? How can I read "hello!" value?
For now, lets put aside closures, consider the following code:
def f1() {
testProperty : 5
}
def f2() {
testProperty : "Hello"
}
println f1()
println f1().getClass()
println f2()
println f2().getClass()
This compiles (therefor the syntax is valid) and prints:
5
class java.lang.Integer
Hello
class java.lang.String
So what you see here is just a labeled statement (groovy supports labels see here)
And bottom line the code of f1 (just like f2) is:
def f1() {
return 5 // and return is optional, so we don't have to write it
}
With closures its just the same from this standpoint:
def method(Closure c) {
def result = c.call()
println result
println result.getClass()
}
method {
test : "hello"
}
This prints
hello
class java.lang.String
as expected
Usually in DSL you have either this:
mySomething {
a = 42
b = 84
}
which corresponds to property setting
or this:
mySomething( a:42, b:84 ){
somethingElse{}
}
which is a method call with Map-literal.
The code you shown is not used as #mark-bramnik explained.
I'm looking for a way to avoid having to check for the property first with hasProperty().
Ideally I would like to have something like
def a = myobj.getPropertyOrElse("mypropname", "defaultvalueifpropertymissing')
I see that gradle has a findProperty() but I can't find a similar thing for plain groovy.
The hasProperty method returns a MetaProperty instance that you can use to retrieve the value by passing the original instance:
def a = myobj.hasProperty('mypropname')?.getProperty(myobj) ?:
'defaultvalueifpropertymissing'
And then use the Safe navigation operator(?.) and Elvis operator (?:) to avoid the if/else.
The shortest version I could think of is
def a = if (a.hasProperty("mypropname")) a.getProperty("mypropname") else "defaultvalueifmissing"
which obviously repeats the property name twice. Creating your own method is possible but it's limited to your current class.
class MyClass {
String name = "the name"
}
def a = new MyClass()
def getProperty(Object theInstance, String propName, Object defaultValue) {
if (theInstance.hasProperty(propName)) theInstance.getProperty(propName) else defaultValue
}
assert "the name" == getProperty(a, "name", "")
assert "default value" == getProperty(a, "method", "default value")
One can use getProperties() of MetaClass or getProperty() of GroovyObject:
class Test {
String field1
String field2
}
def test = new Test(field1: "value1", field2: null)
// using MetaClass.getProperties()
println test.properties["field1"] // value1
println test.properties["field2"] // null
println "field2" in test.properties.keySet() // true
println test.properties["field3"] // null
println "field3" in test.properties.keySet() // false
// using GroovyObject.getProperty()
println test.getProperty("field1") // value1
println test.getProperty("field2") // null
println test.getProperty("field3") // groovy.lang.MissingPropertyException
I'm using Grails XML Parser to parse an XML string and after getting the parsed NodeChild instance, I'm adding dynamic methods on that instance like below:
import grails.converters.XML
import groovy.util.slurpersupport.NodeChild
NodeChild result = XML.parse("<root></root>")
result.getMetaClass().methodA = { return "a" }
result.getMetaClass().methodB = { return "b" }
println rootNode.methodA()
println rootNode.methodB()
Now the line where I'm calling methodA() and expecting "a" to be printed, I'm getting MissingMethodException that methodA() not found.
I investigated on this for some time and found that the all dynamic methods getting replaced with the last dynamic method we add, i.e. in this case: methodB() is replacing (or doing something) methodA(), so I call & print methodB() first, it prints "b" properly.
This strikes me to another test as following:
import grails.converters.XML
import groovy.util.slurpersupport.NodeChild
String result = "any-other-data-type-instance-here-to-inject-dynamic-methods"
result.getMetaClass().methodA = { return "a" }
result.getMetaClass().methodB = { return "b" }
println rootNode.methodA()
println rootNode.methodB()
In this case, both statement prints fine. So the problem is only with the classNodeChild. I'm using exando metaclass feature for long time and I faced such kind of problem. Any idea, that why this is happening?
You need to assign the metaclass methods before the instance is returned, otherwise it will have the old metaclass and not the new one with the new methods. Also, assign to the class, not the instance - I'm not sure if you wanted to only affect this instance's metaclass but that's not the syntax.
This works:
import grails.converters.XML
import groovy.util.slurpersupport.NodeChild
NodeChild.metaClass.methodA = { return "a" }
NodeChild.metaClass.methodB = { return "b" }
NodeChild result = XML.parse("<root></root>")
println result.methodA()
println result.methodB()
Note that you're defining methods with an implicit it argument, but passing nothing, so Groovy passes a null. If you intend for the methods to have no arguments, use this syntax:
NodeChild.metaClass.methodA = { -> return "a" }
NodeChild.metaClass.methodB = { -> return "b" }
In groovy 1.8.6, I was trying to do something like this:
class Greeter {
def sayHello() {
this.metaClass.greeting = { System.out.println "Hello!" }
greeting()
}
}
new Greeter().sayHello()
This didn't work:
groovy.lang.MissingPropertyException: No such property: greeting for class: groovy.lang.MetaClassImpl
After a bit of trying, I found that passing a reference to self to the method did work. So, basically what I came up with was this:
class Greeter {
def sayHello(self) {
assert this == self
// assert this.metaClass == self.metaClass
self.metaClass.greeting = { System.out.println "Hello!" }
greeting()
}
}
def greeter = new Greeter()
greeter.sayHello(greeter)
The strangest thing is that the assert this == self actually passes, which means they are the same instance... right? The default toString also seems to confirm this.
On the other hand, the assert this.metaClass == self.metaClass fails:
assert this.metaClass == self.metaClass
| | | |
| | | org.codehaus.groovy.runtime.HandleMetaClass#50c69133[groovy.lang.MetaClassImpl#50c69133[class Greeter]]
| | Greeter#1c66d4b3
| false
groovy.lang.MetaClassImpl#50c69133[class Greeter]
Why is self.metaClass wrapped in a HandleMetaClass, while this.metaClass isn't? Also, how can the first example be made to work without passing in a reference to self?
I figured out the 2 questions:
groovy.lang.MissingPropertyException: No such property: greeting for class: groovy.lang.MetaClassImpl
why this.metaClass == self.metaClass
See this link: https://stackoverflow.com/a/45407488/42769
You can implement methodMissing in the class as below to answer your last question:
class Greeter {
def sayHello() {
//this.metaClass.greeting = { System.out.println "Hello!" }
greeting()
goodNight()
}
def methodMissing(String name, args){
if(name == 'greeting'){
println "Hello!"
} else
println "Good Night"
}
}
new Greeter().sayHello()
Also note that == in groovy actually means equals() (that is value comparison) if you want to compare identity then is() can be used like
a.is(b) //Corresponds to == in Java
a == b //Corresponds to equals() in Java
UPDATE
Can use metaClass as below
Greeter.metaClass.greeting = { println "Hello"}
def greet = new Greeter()
//or
//greet.metaClass.greeting = { println "Hello"}
greet.sayHello()