Object Array Declaration in Groovy - groovy

How come I cannot declare an array of People in Groovy as shown.
Maybe I'm lacking the deeper understanding of classes
class People {
Integer id
}
class Job {
def func() {
People[] p = new People[10]
}
}
I get an error of People[] cannot be applied to app.People[]

The code sample you have shown does not reproduce the error you mentioned in the question above. It's broken actually and does not compile - method func() is missing its body. If you correct the code to e.g.
class People {
Integer id
}
class Job {
def func() {
People[] p = new People[10]
assert p.size() == 10
println p
}
}
new Job().func()​
you will see it produces the expected result - check it out in the Groovy web console here. When you run it you will see following output to the console:
[null, null, null, null, null, null, null, null, null, null]
The difference between Groovy and Java
When it comes to array initialization there is one significant difference between Groovy and Java. In Java you can initialize an array of People[] like this:
People[] p = new People[] { new People(), new People(), /* ... */ new People() };
It wont work in Groovy, because Groovy reserves {} for closures. In Groovy you can initialize such array as:
People[] p = [new People(), new People(), new People()] as People[]

While Szymon Stepniak's answer is correct for Groovy 2.5 and below, Java-style array initialization are part of the enhancements of Groovy 3.0 and 2.6 made possible by the new parrot parser.
Example from the release notes:
def primes = new int[] {2, 3, 5, 7, 11}
assert primes.size() == 5 && primes.sum() == 28
assert primes.class.name == '[I'
def pets = new String[] {'cat', 'dog'}
assert pets.size() == 2 && pets.sum() == 'catdog'
assert pets.class.name == '[Ljava.lang.String;'
// traditional Groovy alternative still supported
String[] groovyBooks = [ 'Groovy in Action', 'Making Java Groovy' ]
assert groovyBooks.every{ it.contains('Groovy') }

Szymon Stepniak's answer is correct. I'll point another example of a real case in some unit test that I've worked (general Object type):
Object[] o = [YourModel] as Object[]
This is sufficient to mock a general Object with your model properties.

Related

How to pass multiple optional parameters and one mandatory parameter in groovy? [duplicate]

I would like to write a wrapper method for a webservice, the service accepts 2 mandatory and 3 optional parameters.
To have a shorter example, I would like to get the following code working
def myMethod(pParm1='1', pParm2='2') {
println "${pParm1}${pParm2}"
}
myMethod();
myMethod('a')
myMethod(pParm2:'a') // doesn't work as expected
myMethod('b','c')
The output is:
12
a2
[pParm2:a]2
a2
bc
What I would like to achieve is to give one parameter and get 1a as the result.
Is this possible (in the laziest way)?
Can't be done as it stands... The code
def myMethod(pParm1='1', pParm2='2'){
println "${pParm1}${pParm2}"
}
Basically makes groovy create the following methods:
Object myMethod( pParm1, pParm2 ) {
println "$pParm1$pParm2"
}
Object myMethod( pParm1 ) {
this.myMethod( pParm1, '2' )
}
Object myMethod() {
this.myMethod( '1', '2' )
}
One alternative would be to have an optional Map as the first param:
def myMethod( Map map = [:], String mandatory1, String mandatory2 ){
println "${mandatory1} ${mandatory2} ${map.parm1 ?: '1'} ${map.parm2 ?: '2'}"
}
myMethod( 'a', 'b' ) // prints 'a b 1 2'
myMethod( 'a', 'b', parm1:'value' ) // prints 'a b value 2'
myMethod( 'a', 'b', parm2:'2nd') // prints 'a b 1 2nd'
Obviously, documenting this so other people know what goes in the magical map and what the defaults are is left to the reader ;-)
You can use arguments with default values.
def someMethod(def mandatory,def optional=null){}
if argument "optional" not exist, it turns to "null".
Just a simplification of the Tim's answer. The groovy way to do it is using a map, as already suggested, but then let's put the mandatory parameters also in the map. This will look like this:
def someMethod(def args) {
println "MANDATORY1=${args.mandatory1}"
println "MANDATORY2=${args.mandatory2}"
println "OPTIONAL1=${args?.optional1}"
println "OPTIONAL2=${args?.optional2}"
}
someMethod mandatory1:1, mandatory2:2, optional1:3
with the output:
MANDATORY1=1
MANDATORY2=2
OPTIONAL1=3
OPTIONAL2=null
This looks nicer and the advantage of this is that you can change the order of the parameters as you like.
We can Deal with Optional parameters in 2 ways
Creating the method parameter with null values:
def generateReview(def id, def createDate=null) {
return new Review(id, createDate ?: new Date()) // ?: short hand of ternary operator
}
generateReview(id) // createDate is not passed
generateReview(id, createDate) // createDate is passed
Using Java Optional.of()
def generateReview(def id, Optional<Date> createDate) {
return new Review(id, createDate.isPresent() ? createDate.get() : new Date())
}
generateReview(id, Optional.empty()) // createDate is not passed
generateReview(id, Optional.of(createDate)) // createDate is passed

How can I retrieve the build parameters from a queued job?

I would like to write a system groovy script which inspects the queued jobs in Jenkins, and extracts the build parameters (and build cause as a bonus) supplied as the job was scheduled. Ideas?
Specifically:
def q = Jenkins.instance.queue
q.items.each { println it.task.name }
retrieves the queued items. I can't for the life of me figure out where the build parameters live.
The closest I am getting is this:
def q = Jenkins.instance.queue
q.items.each {
println("${it.task.name}:")
it.task.properties.each { key, val ->
println(" ${key}=${val}")
}
}
This gets me this:
4.1.next-build-launcher:
com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty$ScannerJobPropertyDescriptor#b299407=com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty#5e04bfd7
com.chikli.hudson.plugin.naginator.NaginatorOptOutProperty$DescriptorImpl#40d04eaa=com.chikli.hudson.plugin.naginator.NaginatorOptOutProperty#16b308db
hudson.model.ParametersDefinitionProperty$DescriptorImpl#b744c43=hudson.mod el.ParametersDefinitionProperty#440a6d81
...
The params property of the queue element itself contains a string with the parameters in a property file format -- key=value with multiple parameters separated by newlines.
def q = Jenkins.instance.queue
q.items.each {
println("${it.task.name}:")
println("Parameters: ${it.params}")
}
yields:
dbacher params:
Parameters:
MyParameter=Hello world
BoolParameter=true
I'm no Groovy expert, but when exploring the Jenkins scripting interface, I've found the following functions to be very helpful:
def showProps(inst, prefix="Properties:") {
println prefix
for (prop in inst.properties) {
def pc = ""
if (prop.value != null) {
pc = prop.value.class
}
println(" $prop.key : $prop.value ($pc)")
}
}
def showMethods(inst, prefix="Methods:") {
println prefix
inst.metaClass.methods.name.unique().each {
println " $it"
}
}
The showProps function reveals that the queue element has another property named causes that you'll need to do some more decoding on:
causes : [hudson.model.Cause$UserIdCause#56af8f1c] (class java.util.Collections$UnmodifiableRandomAccessList)

How to inspect a Groovy list recursively?

I was going to use Groovy's inspect() methods for quick and dirty object persistence but it didn't work as I expected. More specifically if I inspect() a list then list items are not inspect()ed but rather are toString()ed instead. Consider the following script:
class Foo {
String inspect() { 'new Foo()' }
}
assert new Foo().inspect() == 'new Foo()' // passes as expected
assert [new Foo()].inspect() == '[new Foo()]' // fails
Running this script produces the following output:
Assertion failed:
assert [new Foo()].inspect() == '[new Foo()]'
| | |
| | false
| [Foo#3d52315f]
Foo#3d52315f
at test.run(test.groovy:6)
meaning that inspect() on my Foo instance is never called. Is this a Groovy bug? I'm testing with Groovy 2.4.1.
Try in the following way:
class Foo {
String inspect() { 'new Foo()' }
}
assert new Foo().inspect() == 'new Foo()' // passes as expected
assert [new Foo()]*.inspect().toString() == '[new Foo()]'
You need to call inspect on every element of the list provided and then make to list inspectable itself. But indeed the behavior seems strange when it comes to the docs.
It seems that this is a bug. From DefaultGroovyMethods call to inspect() is redirected to InvokerHelper. Since you pass a collection (list) formatList method will be invoked. This method iterates over the list passed and calls format in the same class. Since formatdoesn't know about Foo it will call toString to the object passed (line 629).
The following example shows how it works:
class Foo {
String inspect() { 'new Foo()' }
String toString() { 'new Foo()' }
}
assert new Foo().inspect() == 'new Foo()'
assert [new Foo()].inspect() == '[new Foo()]'

groovy null safe operator, identifying what was null?

The null safe operator in Groovy is great for reducing code and making things more readable. We can go from this:
def customer = getCustomer(custNo)
if(!customer)
throw new Exception("Invalid customer: ${custNo}")
def policy = customer.getPolicy(policyNo)
if(!policy)
throw new Exception("Invalid policy: ${policyNo}")
def claim = policy.getClaim(claimNo)
if(!claim)
throw new Exception("Invalid claim: ${claimNo}")
..to this...
def claim = getCustomer(custNo)?.getPolicy(policyNo)?.getClaim(claimNo)
But nothing's for free; using null/safe navigation, if claim is null, it's not immediately obvious what caused it: either custNo, policyNo, or claimNo may be invalid.
We could go back and start checking what's null, but that's counterproductive, and actually, it's not even possible since intermediate objects are not stored in variables.
So the question is: Is it possible to identify what was null when chaining method calls using null/safe navigation?
UPDATE
I took another stab at this using dynamic method invocation. It takes an init target (usually a dao) to initialize the object (customer in this case), and a map containing method names as strings (with arguments as values). Using an iterator, invokeChain simply traverses the map (chain); if anything in the chain returns null, identifying the method that caused it becomes trivial.
def invokeChain = { initTarget, chain ->
def obj
chain.eachWithIndex{ it, idx ->
//init obj from dao on first iteration only,
//remaining iterations get from obj itself
obj = (!idx) ? initTarget."$it.key"(it.value) : obj?."$it.key"(it.value)
if(!obj)
throw new Exception("${it.key}(${it.value}) returned null")
}
obj
}
Usage
Mock a customer dao for initTarget...I've inserted null as return type for getClaim(), which should throw an exception.
def static getCustomer = { custNo ->
[ getPolicy: { p ->
[getClaim:{ c ->
null //"Claim #${c}"
}]
}]
}
..using invokeChain, easy as pie:
def claim = invokeChain(this, [getCustomer:123, getPolicy:456, getClaim:789])
...throws exception, as expected:
Exception in thread "main" java.lang.Exception: getClaim(789) returned null
I like this approach because it's compact, readable, and easy to use; what do you think?
I think there is no clear way to do so.
I can be wrong, will check sources later, but safe navigation is a syntax sugar for if statement.
As a hack you can wrap your code with interceptor, trace last method call inside, and then use that info to proide error message.
It will not be cheap, and will cost you some code to realize interception and some performance while running. But you can achieve something like
mayFail("getCusomer", "getPolicy", "getClaim") {
getCustomer(custNo)?.getPolicy(policyNo)?.getClaim(claimNo)
} == "getPolicy" // failed on second step
EDIT: As #tim_yates proved, ?. is a syntax sugar with if construction behind. Thanks Vorg van Geir for the link, I have copied it here, to an answer. He say, it's outdated, and it looks like he is right. I have managed to make ProxyMetaClass work(in Groovy 2.0.6), so given way isn't totally broken. Now I need to specify exact classes to intercept, and I can not find a way to catch inherited method calls.(to simply intercept java.lang.Object)
def logInterceptor = new TracingInterceptor()
logInterceptor.writer = new StringWriter()
def intProxy = ProxyMetaClass.getInstance(Integer)
def stringProxy = ProxyMetaClass.getInstance(String)
intProxy.setInterceptor(logInterceptor)
stringProxy.setInterceptor(logInterceptor)
intProxy.use {
stringProxy.use {
println(("Hello" + "world").size().hashCode())
} }
println(logInterceptor.writer.toString())
All that hell may be wrapped in some utility code, but I highly doubt in necessarity of this. Performance overhead will be awful and some boilerplate code will remain.
The game is not worth the candle.
What about attributions and asserts?
def policy = customer?.policy
def claim = policy?.claim
def number = claim?.number
assert customer, "Invalid customer"
assert policy, 'Invalid policy'
assert claim, 'Invalid claim'
UPDATE:
You already found the solution, but i'd like to contribute with an interceptor idea:
The mock:
def dao = [
getCustomer : { custNo ->
[ getPolicy: { p ->
[getClaim:{ c ->
null //"Claim #${c}"
}]
}]
}
]
The interceptor:
class MethodCallInterceptor {
def delegate
def invokeMethod(String method, args) {
def result = delegate.invokeMethod(method, args)
if (result == null) {
throw new RuntimeException("$method returned null")
}
else {
new MethodCallInterceptor(delegate: result)
}
}
def getProperty(String property ) {
delegate[ property ]
}
void setProperty(String property, value) {
delegate[ property ] = value
}
}
The test:
def interceptedDao = new MethodCallInterceptor(delegate: dao)
try {
interceptedDao.getCustomer(123).getPolicy(456).getClaim(789)
assert false
} catch (e) {
assert e.message.contains( 'getClaim returned null' )
}

groovy Object and primitive confusion

Here's a part of (groovy) class that stores some data in Mongodb:
long save(Object data) {
def customerReference = getNextCustomerReference()
def map = ['customerReference': customerReference, 'data': data, 'created': new Date()]
BasicDBObject basicDBObject = new BasicDBObject(map)
collection.insert(basicDBObject)
customerReference
}
private long getNextCustomerReference() {
1234
}
even though I have explicitly said i want a primitive long, what ends up in the database is an object:
{ "_id" : ObjectId("52f3c0597d844b0fcee29013"), "customerReference" : NumberLong(1234), "data" : "original data", "created" : ISODate("2014-02-06T17:03:21.411Z") }
However, if I change the return type to def for the private method this happens:
{ "_id" : ObjectId("52f3c1477d84698725f50fe5"), "customerReference" : 1234, "data" : "data", "created" : ISODate("2014-02-06T17:07:19.055Z") }
which the behaviour I want (a primitive stored in the db).
Can someone explain this because its baffling. Surely if I go out of my way to define a type, Groovy should try and honour it?
Groovy almost always automatically autoboxes primitive types to their number reference type-equivalent:
long test_long() { 123l }
int test_int() { 123 }
def test_def() { 123 }
def test_def_long() { 123l }
long l = 42l
assert test_long().class == Long.class
assert test_int().class == Integer.class
assert test_def().class == Integer.class
assert test_def_long().class == Long.class
assert l.class === Long.class
If you remove the long return type, the object is autoboxed to java.lang.Integer. Seems your code handles the Integer like a "primitive".
Some time ago Groovy 1.8 introduced primitive type optimization, an internal fallback to use primitive types under the hood in certain situations. This can help in some situations but is an internal performance optimization you can't directly make use of (by using some syntax construct or something like that).
Sometimes you can force a primitive by an explicit cast, but chances are high it will be converted to a reference type along the way through methods calls and stuff.

Resources