Groovy map, get, variable, Jenkins - jenkins

I have a problem with mapping in Groovy.
I would like to get a value based on a variable.
def function(){
map = [
'test1': '1234',
'test2': '4567'
]
var=test1
def result = map.get.("$var")
return result
}
But, unfortunately. I always get back:
Cannot get property '[test1]' on null object

You are making a HashMap behind the scenes here and the way you are accessing it map.get.["$var"] Groovy is trying to access a key called "get" on your variable map.
You just want map[var]
Updated with BalRog's note below

Related

Groovy- map : every time require new instance

My requirement is to get a NEW instance every time when I access the value in a MAP.
MyObject {
def type
}
def myMap = [
"key1" : new MyObject()
]
def obj1 = myMap.get("key1")
def obj2 = myMap.get("key1")
Can obj1 and obj2 be two different instances?
How will it behave if executed/accessed parallelly?
don't know what your use case is, but I guess I have the answer to your question:
def myMap = [
"key1" : new MyObject()
]
Just first instantiates a new object and then stores this object in the map. So every time you access it, you get the same object.
To create the behavior you describe, you need to add something dynamic to your map - a closure!
def myMap = [
"key2" : {-> new MyObject()}
]
but now a myMap.get("key2") still returns always the same - a closure. But if you execute it by calling myMap.get("key2")() (or short myMap.key2) you get a different object each time!
Unfortunately, this is a close as you will get. I hoped to do a trick with a key called getKey3 - I hoped that Groovy would call this "getter" when accessing key3 but this seems not to be the case.
There are other "tricks" in Groovy which could help you to achieve your goal (like MetaProgramming) but I guess there is a better solution if we would know your use case.

Dart - The setter 'someVar' is not defined for the class 'Map'

I'm trying to 'port' some script to the Dart. To learn how everything work etc.
But there is a problem - in JavaScript we can set and get any variable in the object.
In Dart we have a Map class. And I have no idea how to use it (there is not so many help from Dart API Reference).
Currently I have:
Map settings;
//Then I get an dynamic result of a function that gives either null or object.
settings = result ?? {};
settings.someVar = 5;
And this code produces the following error:
"The setter 'someVar' is not defined for the class 'Map'."
Of course I can just 'invent' a new class Settings, but is there any other solutions?
With a Map, you get and put values with the [] and []= operators. So in this case you would use it like so;
settings['someVar'] = 5;
You can also use the addAll method;
settings.addAll({'someVar': 5, 'someOtherVar': 10});
Dart API References: operator [], operator []=, addAll

Grails YAML list of maps

In my Grails 3 application.yml, I'm defining a list of maps as follows:
tvoxx:
cfpApis:
-
url: http://cfp.devoxx.be/api/conferences
youtubeChannelId: UCCBVCTuk6uJrN3iFV_3vurg
-
url: http://cfp.devoxx.fr/api/conferences
-
url: http://cfp.devoxx.ma/api/conferences
youtubeChannelId: UC6vfGtsJr5RoBQBcHg24XQw
-
url: http://cfp.devoxx.co.uk/api/conferences
-
url: http://cfp.devoxx.pl/api/conferences
But when I try to load this config in my service using the following code, apiConfig is null:
def apiConfig = grailsApplication.config.getProperty("tvoxx.cfpApis")
I don't get any error when the application starts and my YAML code parses correctly on http://yaml-online-parser.appspot.com/ so I don't know what's wrong.
Just to confirm what we discussed on Slack.
Using grailsApplication.config.getProperty("tvoxx.cfpApis"), Grails will try to find value of type String and because your value is a Map null will be returned.
You have to explicitly tell what type you expect, using:
grailsApplication.config.getProperty("tvoxx.cfpApis", Map)
Other way is to use getAt() method, where object is returned, so you can use
grailsApplication.config.tvoxx.cfpApis to get the value.
First one may be better for .java and #CompileStatic but for standard .groovy class latter has easier syntax. Just watch out for keys which does not exist, because it will return empty ConfigObject instead of null, and for example ?.toString() method will result in 'ConfigObject#123123 instead of null

Persisting date and nested with JSON

I'm trying to save nested person, which is json array and complains about requiring a Set.
Another problem I encountered, is that another field date cannot be null, but contains value already.
What I need to do before for adding params into my object or I have to change my json is built? I'm trying to save json post like this:
// relationship of Test
//static hasMany = [people: Person, samples: Sample]
def jsonParams= JSON.parse(request.JSON.toString())
def testInstance= new Test(jsonParams)
//Error requiring a Set
[Failed to convert property value of type 'org.codehaus.groovy.grails.web.json.JSONArray' to required type 'java.util.Set' for property 'people'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.Person] for property 'people[0]': no matching editors or conversion strategy found]]
//error saying its null
Field error in object 'com.Test' on field 'samples[2].dateTime': rejected value [null]; codes [com.Sample]
//...
"samples[0].dateTime_hour":"0",
"samples[0].dateTime_minute":"0",
"samples[0].dateTime_day":"1",
"samples[0].dateTime_month":"0",
"samples[0].dateTime_year":"-1899",
"samples[0]":{
"dateTime_minute":"0",
"dateTime_day":"1",
"dateTime_year":"-1899",
"dateTime_hour":"0",
"dateTime_month":"0"
},
"people":[
"1137",
"1141"
], //...
First off, ths line is unnecessary:
def jsonParams= JSON.parse(request.JSON.toString())
The request.JSON can be directly passed to the Test constructor:
def testInstance = new Test(request.JSON)
I'm not sure what your Person class looks like, but I'm assuming those numbers (1137, 1141) are ids. If that is the case, then your json should work - there's a chance that passing the request.JSON directly could help. I tested your JSON locally and it has no problem associating the hasMany collection. I also used:
// JSON numbers rather than strings
"people": [1137, 1141]
// using Person map with the id
"people: [{
"id": 1137
}, {
"id": 1141
}]
Both of these worked as well and are worth trying.
Concerning the null dateTime, I would rework your JSON. I would send the dateTime in a single field, instead of splitting the value into hour/minute/day/etc. The default formats are yyyy-MM-dd HH:mm:ss.S and yyyy-MM-dd'T'hh:mm:ss'Z', but these can be defined by the grails.databinding.dateFormats config setting (config.groovy). There are other ways to do the binding as well (#BindingFormat annotation) but it's going to be easiest to just send the date in a way that grails can handle without additional configuration.
If you are dead set on splitting the dateTime into pieces, then you could use the #BindUsing annotation:
class Sample{
#BindUsing({obj, source ->
def hour = source['dateTime_hour']
def minute = source['dateTime_minute']
...
// set obj.dateTime based on these pieces
})
Date dateTime
}
An additional comment on your JSON, you seem to have samples[0] defined twice and are using 2 syntaxes for your internal collections (JSON arrays and indexed keys). I personally would stick with a single syntax to clean it up:
"samples": [
{"dateTime": "1988-01-01..."}
{"dateTime": "2015-10-21..."}
],"people": [
{"id": "1137"},
{"id": "1141"}
],

[Grails/Groovy]minimum value of Map entries

Query: how can i pull minimum value from a map in Grails
So far i have found following code to get minimum value from a map in groovy
["Java":1, "Groovy":4, "JavaScript":2].min{it.value}
but it donot work in Grails
i have tried following piece of code
def map = ["Java":1, "Groovy":4, "JavaScript":2]
println map.min{it.value}
assert map.min{it.value}==1
Thanks in advance
If you want the minimum value from the map, you can do:
def map = ["Java":1, "Groovy":4, "JavaScript":2]
println map.values().min()
assert map.values().min() == 1
edit
Also, the closure accepting version of map.min has been in Groovy since 1.7.6, and Grails (as of v1.3.6) uses Groovy 1.7.5
min() doesn't return a minimum value returned by argument closure, it returns the element of a collection for which the closure returns minimum.
map.min {it.value} is valid call, but it's not a value. It's a MapEntry, with key and value properties. So map.min{it.value}.value would do.

Resources