Optional parameter in Groovy Script - groovy

I have a script that simply does
// TODO: assign default value if not defined
println optionalParameter
When I invoke it using:
new GroovyShell(new Binding([optionalParameter: 'text'])).evaluate(script)
it works fine. But if I run it without a parameter like below:
new GroovyShell().evaluate(script)
it fails with MissingPropertyException.
How can I assign default value for optionalParameter so that I don't get MissingPropertyException?

Adding this code to script works for me:
String value
if (binding.hasVariable('optionalParameter')) {
value = binding.getVariable('optionalParameter')
} else {
value = 'defaultValue'
}
println value

Related

Groovy closure without preceding equal sign prop = {} vs prop {}

I'm trying to create a config file for my java app that can have lazy evaluation, for instance, contain an e-mail template with current date time. I use ConfigSlurper to parse the config file.
For some reason I can't find at https://groovy-lang.org/closures.html the description of the commonly used form (see build.gradle): prop1 { ... } prop2 { ... }. Am I looking at the wrong place?
My tests show that such closures are evaluated immediately and the example above can be rewritten as: prop1 = { ... }() prop2 = { ... }() (notice the parentheses, without them the evaluation is lazy).
I also don't understand why using dots in property without the equal sign cause MissingMethodException: No signature of method: groovy.util.ConfigObject.URL() if I use: server.URL { System.out.println('ccc'); 'asd' } in the example below.
It's disappointing that the choice is completely transparent for Groovy, but you have to check that a value is instance of Closure or GString when using java.
I used this article as the starting point https://blog.mrhaki.com/2009/08/grassroots-groovy-configuration-with.html
// We can group settings.
// The following settings are created:
// app.version, app.setting1, app.setting2, app.setting3, app.date, app.active
app {
System.out.println('aaa')
version = "1.0"
// We can write code to set up settings.
[1, 2, 3].each {
this."setting${it}" = it * 10
}
// We can use Java objects
date = new Date()
active = true
}
server.URL = "http://default"
// Environment specific settings override settings with the
// same name.
environments {
development {
server = { System.out.println('ccc'); 'asd' }
// server.URL = "${-> System.out.println('bbb');new Date()}http://localhost"
}
test {
server.URL = 'http://test:9080'
}
integrationtest {
server.URL = 'http://integrationtest/url'
}
production {
server.URL = 'http://prod/url'
}
}
My tests show that such closures are evaluated immediately and the
example above can be rewritten as: prop1 = { ... }()
Closures are not evaluated immediately. The parens above are causing the closure to be evaluated.
For some reason I can't find at https://groovy-lang.org/closures.html
the description of the commonly used form (see build.gradle): prop1 {
... } prop2 { ... }.
prop1 {} is invoking a method named prop1 and passing a closure as a parameter That code is equivalent to this:
def myClosure = {}
prop1(myClosure)
I also don't understand why using dots in property without the equal
sign cause MissingMethodException: No signature of method:
groovy.util.ConfigObject.URL()
Something like server.URL = 'http://test:9080' is assigning a value (http://test:9080) to a property (server.URL). If you remove the equal sign you are changing the expression fundamentally and then would be invoking a method named URL on an object named server and passing http://test:9080 as a parameter.

Method return wrong type of value in Groovy

I'm working on a groovy method to look for a custom attribute and return the value if the key is found.
The problem is that the method is returning the type of value instead of the value.
// There is more code before, but its not involved with this issue.
def UUIDca = 'UUID'
String customAttributeValue = grabCustomAttribute(UUIDca, event_work)
appendLogfile("\n\nTest grabCustomAttribute: ${customAttributeValue}\n")
}
// Grab the Custom Message Attribute values by name
String grabCustomAttribute (String findElement, OprEvent event){
appendLogfile("""\nIN grabCustomAttribute\nElement to look: ${findElement}\n""")
def firstItem = true
if (event.customAttributes?.customAttributes?.size()) {
event.customAttributes.customAttributes.each { ca ->
// Define each CMA to catch here
appendLogfile("""\nElement: ${ca.name} - """)
appendLogfile("""Valor: ${ca.value}\n""")
if ("${ca.name}" == findElement) {
String customValue = ca.value
appendLogfile("""Custom Attribute Found\n""")
appendLogfile(customValue)
return customValue
}
}
}
}
appendLogfile is basically a print to a log file :)
This is the output I'm getting.
IN grabCustomAttribute Element to look: UUID
Element: UUID - Valor: c3bb9169-0ca3-4bcf-beb1-f94eda8ebf1a
Custom Attribute Found
c3bb9169-0ca3-4bcf-beb1-f94eda8ebf1a
Test grabCustomAttribute: [com.hp.opr.api.ws.model.event.OprCustomAttribute#940e503a]
Instead of returning the value, it returns the type of object. It's correct, but I'm looking for the value.
I believe the solution is really simple, but I'm very new to Groovy.
Any help will be appreciated.
Thanks.
In this case the return statement is for the closure, not for the method, so your method is actually returning the list that "each" is iterating over
The easiest approach you can take here is to use Groovy find method to find the element you are searching for. Something like this:
String grabCustomAttribute (String findElement, OprEvent event) {
return event.customAttributes.customAttributes?.find { ca -> ca.name == findElement }.value
}

How I could create a table model with closure put multiple variable form loop

I see this code for how create a table with closure
https://varomorf.wordpress.com/2014/09/22/update-jtable-using-groovy/
but now I need create a table with closure
but using a text title for create all closure variable
like this; this code get the table but using the last value of xbn in this case 4
theTable = table(){
tableModel(){
var1="fecha"
xbn=0
stx="date;product;quant;weight;price".split(";")
println it
while(xbn<4) {
closureColumn(header:stx[xbn], read:{it[stx[xbn]]}) ;xbn=xbn+1 }
}
}
normally my code without loop
look like this
theTable = table(){
tableModel(){
var1="fecha"
xbn=0
stx="date;product;quant;weight;price".split(";")
println it
closureColumn(header:"date", read:{it["date"]})
closureColumn(header:"product", read:{it["product"]})
closureColumn(header:"quant", read:{it["quant"]})
closureColumn(header:"weight", read:{it["weight"]})
closureColumn(header:"price", read:{it["price"]})
}
}
please help me
Most DSLs don't prevent you from using the regular groovy stuff. So you can iterate multipl times, but you have to name your closure loop vars (e.g. your outer loop is the tableModel and it's implicitly named it).
...
tableModel() { // it ->
...
"date;product;quant;weight;price".split(";").each { hdr -> // name the loop var
closureColumn(header:hdr, read:{it[hdr]})
}
...
}
...

Accessing variable outside of a closure in Groovy

Is there a way, i can access a variable outside the closure. The closure here is a stage in the Jenkinsfile. So, the snippet looks like this:
node('pool'){
try{
stage('init'){
def list = []
//some code to create the list
}
stage('deploy'){
//use the list create in the above stage/closure
}
}
catch(err){
//some mail step
}
}
With this code, i cannot access the list which was created in the first stage/closure.
How can i set to get this newly created list accessible to the next stage/closure?
#tim_yates.. with your suggestion. This works. It was easy at the end :)
node('pool') {
try {
def list = [] //define the list outside of the closure
stage('init') {
//some code to create/push elements in the list
}
stage('deploy') {
//use the list create in the above stage/closure
}
} catch (err) {
//some mail step
}
}
I know it's late, but worths mentioning that when you define a type or def (for dynamic resolution) you're creating a local scope variable that will be available only inside the closure.
If you omit the declaration the variable will be available to the whole script:
node('pool'){
try {
stage('Define') {
list = 2
println "The value of list is $list"
}
stage('Print') {
list += 1
echo "The value of list is $list"
}
1/0 // making an exception to check the value of list
}
catch(err){
echo "Final value of list is $list"
}
}
Returns :
The value of list is 2
The value of list is 3
Final value of list is 3

Groovy: evaluate a property with a variable in it

A bit new to groovy, I am trying to match a variable string to a property pulled from a file using ConfigSlurper. I have the slurper part working fine, but can't seem to figure out the right way to evaluate a property with a variable in it. I think I was getting warm when I found evaluating-code-dynamically-in-groovy but I am not entirely sure.
//properties.groovy
jobs {
foo {
email="foo#email.com"
}
}
//myscript.groovy
def config = new ConfigSlurper().parse(new File('properties.groovy').toURI().toURL())
List jobs = (ArrayList) BazAPI.getArtifacts(bucket) // list of objects, foo is one
ListIterator jobIterator = jobs.listIterator();
while (jobIterator.hasNext()) {
Object j = jobIterator.next();
job_name = "${j.name}" //
email = config.jobs."${job_name}".email /* NEED TO FIGURE OUT HOW TO EVAL */
foo_email = config.jobs.foo.email //evaluates to the correct property in properties.groovy
//these values get fed to a DSL but to illustrate
println "${job_name}" // prints foo
println "${email}" // prints [:]
println "${foo_email}" // prints foo#email.com
}
Have you tried
config.jobs[ j.name ].email

Resources