How do I store a list/array of classes in a Groovy variable? - groovy

I want to store a list/array of Java exception classes (e.g. NullPointerException, some custom exception classes, etc.) into a Groovy list/array, but I keep running into either casting problems or MissingPropertyException:
class Foo {
Exception[] foo
List bar
def setFoo(Exception[] values) {
this.foo = values
}
def setBar(List values) {
this.bar = values
}
}
f = Foo()
f.setFoo([NullPointerException.class])
f.setBar(Arrays.asList(NullPointerException.class))
But I can't seem to get it right. Any pointer is much appreciated. Thanks!

Changes to
class Foo {
Class[] foo
List bar
def setFoo(Class[] values) {
this.foo = values
}
def setBar(List values) {
this.bar = values
}
}
def f = new Foo()
f.setFoo([NullPointerException.class] as Class[])
f.setBar(Arrays.asList(NullPointerException.class))
foo should be an array of Class rather than Exception. (Exception is the instance of Exception Class)
You need to explicitly cast list to Class array, which does the conversion from list to array for you.

It can be done with just def list = [UserClass1, UserClass2]. In groovy, even .class not required.
You code should as below, isn't this simple?
class Foo {
def bar
}
def f = new Foo(bar: [NullPointerException, RuntimeException])
assert f.bar instanceof List<Class>
assert (f.bar as Class[]) instanceof Class[]
You can quickly try it online demo

Related

Creation of an instance with `with` block causes a type issue

I am using Groovy to create a package that I use in ReadyApi.
In a Groovy script test step, I do the following:
class B {
String value
boolean isSomething
}
class A {
String name
B propB
public A() {
this.name = "Maydan"
}
}
def x = (A) new A().with { propB = new B(value: "Abc", isSomething: true) }
And I get the following error:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'B#6c218cea' with class 'B' to class 'A'
error at line: 15
Does someone know why? It doesn't make any sense to me.
Kind regards.
PS: I would like to create an instance of class A (by using its parameterless constructor) and setting its field propB in a single statement
You need to return your A object from the .with closure. You may do it like that:
def x = (A) new A().with { propB = new B(value: "Abc", isSomething: true); return it}
but to me personally it looks a little bit odd. I would do it like that:
def x = new A(propB: new B(value: "Abc", isSomething: true))
The same effect, but more compact and readable. It doesn't require to change your A and B definitions, this "map constructor" works out of the box in Groovy, it will call your parameterless constructor and then assigns the necessary fields (propB in your case).

get Groovy class' closure property names

Given the following Groovy class:
class MyClass {
def someClosure = {}
def someClosure2 = {}
private privateClosure = {
}
def someVal = 'sfsdf'
String someMethod() {}
}
I need a way to retrieve the names of all public properties that have closure assigned to them, so the correct result for this class would be ['someClosure', 'someClosure2'].
I can assume that all the classes of interest have a default constructor, so if it makes things easier, I could retrieve the properties from an instance via
def instance = MyClass.newInstance()
You can simply check the value of every groovy property:
class Test {
def aClosure = {}
def notClosure = "blat"
private privateClosure = {}
}
t = new Test()
closurePropNames = t.properties.findResults { name, value ->
value instanceof Closure ? name : null
}
assert closurePropNames == ['aClosure']
The private fields are not considered groovy properties, so they won't be included in the results.

What does `ObjectMapper mapper = []` mean in groovy?

I'm new to groovy, and I'm reading the source of a project gretty
import org.codehaus.jackson.map.ObjectMapper
class JacksonCategory {
static final ObjectMapper mapper = []
...
}
I don't understand the code ObjectMapper mapper = [], what does [] mean here? I thought it's a list, but how to assign it to a ObjectMapper?
UPDATE
Depends on Dunes's answer, seems [] means invocation of default constructor. So, it means:
static final ObjectMapper mapper = new ObjectMapper()
But:
String s = []
println s // -> it's `[]` not ``
And
Integer i = []
throws exception:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[]'
with class 'java.util.ArrayList' to class 'java.lang.Integer'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[]' with class
'java.util.ArrayList' to class 'java.lang.Integer'
It's a call to the default constructor of ObjectMapper.
http://mrhaki.blogspot.com/2009/09/groovy-goodness-using-lists-and-maps-as.html
It seems [] is always created as an empty ArrayList, but when assigned to a separate type groovy tries to do type coercion and find an appropriate constructor.
With strings it just calls the toString method on the list and makes that the string. For objects it looks for constructors with the appropriate number and type of arguments.
Groovy does not expect to have to do this for java library classes that extend Number (Integer, BigDecimal, etc) and throws a ClassCastException instead.
Examples:
class A {
String value;
A() { this("value"); }
A(String value) { this.value = value; }
}
def A defaultCons = [];
// equivalent to new A()
def A argsCons = ["x"];
// equivalent to new A("x")
def list = [1,2];
// literal ArrayList notation
def String str = [];
// equivalent to str = "[]"
println "A with default constructor: " + defaultCons.value;
println "A with String arg constructo: " + argsCons.value;
println "list: " + list;
println "str: " + str;

Groovy AST Transformations - How can I figure out the return type of a MethodCallExpression?

With Groovy AST Transformations, how can I figure out the return type of a MethodCallExpression?
MethodCallExpression.getType() always returns java.lang.Object even if I explicitly define the return type of the method in the method definition.
Due to the dynamic nature of groovy, the AST can't know the return type of a method call expression at compile time. For example:
class Example {
String foo() { "foo" }
}
def e = new Example()
assert e.foo() == "foo"
Looks simple enough. foo returns a string, so the MethodCallExpression for e.foo() should have a type of String, right? But what if foo is changed in the metaClass?
class Example {
String foo() { "foo" }
}
def e = new Example()
if (someRuntimeCondition) {
e.metaClass.foo = { -> 42 }
}
assert e.foo() == "foo" // is foo a String or an Int?
The groovy compiler just doesn't have enough information to make any assumptions about the method call since it could change at runtime, so it has to compile it down to an Object.

In groovy, is there a way to check if an object has a given method?

Assuming that I have an object someObj of indeterminate type, I'd like to do something like:
def value = someObj.someMethod()
Where there's no guarantee that 'someObj' implements the someMethod() method, and if it doesn't, just return null.
Is there anything like that in Groovy, or do I need to wrap that in an if-statement with an instanceof check?
Use respondsTo
class Foo {
String prop
def bar() { "bar" }
def bar(String name) { "bar $name" }
}
def f = new Foo()
// Does f have a no-arg bar method
if (f.metaClass.respondsTo(f, "bar")) {
// do stuff
}
// Does f have a bar method that takes a String param
if (f.metaClass.respondsTo(f, "bar", String)) {
// do stuff
}
Just implement methodMissing in your class:
class Foo {
def methodMissing(String name, args) { return null; }
}
And then, every time you try to invoke a method that doesn't exist, you will get a null value.
def foo = new Foo();
assert foo.someMethod(), null
For more information, take a look here: http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing
You should be able to do something like:
SomeObj.metaClass.getMetaMethod("someMethod")
Or you can fall back to the good old Java reflection API.
You can achieve this by using getMetaMethod together with the safe navigation operator ?.:
def str = "foo"
def num = 42
def methodName = "length"
def args = [] as Object[]
assert 3 == str.metaClass.getMetaMethod(methodName, args)?.invoke(str, args);
assert null == num.metaClass.getMetaMethod(methodName, args)?.invoke(num, args);
if class :
MyClass.metaClass.methods*.name.any{it=='myMethod'}//true if exist
if object :
myObj.class.metaClass.methods*.name.any{it=='myMethod'}//true if exist
In very concise way you can use this:
if(someObj.&methodName){
//it means someObj has the method
}

Resources