Groovy Maven

Moved here from Code Maven

See the pages on the side.

Groovy

Groovy is a general purpose language that runs on the top of the JVM, the Java Virtual Machine that seems to allow developers to be a lot more productive than using Java.

My primary reason for looking into it is that it is the language used for the Jenkins Pipelines.

Oh and you can also grab my Groovy book.

Articles

Other resources

enum planets {
   Mercury,
   Venus,
   Earth,
   Mars,
   Jupiter,
   Saturn,
   Uranus,
   Neptune
}

println("hi")

println(planets)
println(planets.Earth)

Elapsed time

import groovy.time.TimeCategory
import groovy.time.TimeDuration

def start = new Date()
println(start)
print("Press any key ...")
def name = System.in.newReader().readLine()
def stop = new Date()
println(stop)
diff = stop - start
println(diff)


TimeDuration td = TimeCategory.minus( stop, start )
println td


Groovy regex

  1. Interpolation can be used
  2. matcher.matches vs being null ?
  3. \b to mark end of word
def exp = 'line'

def matcher = (text =~ /\b$exp\b/)
println("hi")
if (matcher) {
    println("match")
}

groovy time duration - elapsed time

import groovy.time.TimeDuration

tdx = new TimeDuration(0, 0 , 0, 2000)
println(tdx)

http://docs.groovy-lang.org/2.4.9/html/gapi/groovy/time/TimeDuration.html

duration:

println(currentBuild.getClass()) //  class org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper  https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html
println("duration: ${currentBuild.durationString}") // duration: 0.35 sec and counting
println(currentBuild.getDuration()) //  397   (miliseconds)
println(currentBuild.getDurationString()) // 0.4 sec and counting

https://stackoverflow.com/questions/51788139/how-to-get-jenkins-build-job-duration

Hello World in Groovy

Install Groovy

There are plenty of ways you can download and install Groovy. As I am trying it on Mac OSX and as I already use Homebrew I just ran

brew install groovy

and it installed it for me.

The version of Groovy

Then I ran the following command to see which version o f Groovy do I have and on top of which version of the JVM it runs:

$ groovy -v

Groovy Version: 2.4.15 JVM: 1.8.0_60 Vendor: Oracle Corporation OS: Mac OS X

Hello World in Goovy

Unlike in Java there is not need for a lot of cermony. You can use the print function to print a string to the screen. You can include \n to embed a newline character. There is no need for semi-colon ; at the end of the statement.

print "Hello World!\n"
$ groovy hello_world.groovy

Alternatively you can use the println function that will automatically append a newline to the end of the output.

println "Hello World!"

timestamp: 2018-05-01T07:30:01

  • print
  • println

Groovy: read from console (STDIN, keyboard)

Reading from the Standard Input (aka. STDIN) which is by default connected to the keyboard is somewhere between Java and the dynamic languages in lightness.

Read from STDIN in Groovy

Reading from the Standard Input, normally the keyboard, is also quite easy.

System.in represents the Standard Input channel.

def defines a variable name. There is no need to declare the type of the variable.

println only takes one argument, so instead of passing a list of values we use the + operator to concatenate the values.

print "What is your name? "
def name = System.in.newReader().readLine()
println "Your name is " + name

Read from Console in Groovy

A shorter alternative is to use the Console object, but rumors say that it might not work inside an IDE. It works when running in the terminal.

def name = System.console().readLine 'What is your name? '
println "Your name is " + name

Converting string to Integer

When we read a value from the standard input it arrives as a string. It cannot be used in numerical operations even if the input looks like a number. In order to use it as a number we have to tell Groovy to treat it as a number. For example as an Integer. That's what "as Integer" is for in the next example:

Rectangular

See the rectangular exercise.

print "First number: "
def x = System.in.newReader().readLine() as Integer
print "Second number: "
def y = System.in.newReader().readLine() as Integer
println x * y

timestamp: 2018-05-27T09:00:01 tags:

  • Console
  • System
  • readLine

Groovy value types

The literal values in Groovy are similar to those in Java, but Groovy allows for generic variables that can hold any type and provides no enforcement and it allows you to declare variables with types and then enforce the type.

Declare variables with def

Declaring a varable using def allows for the flexibility most dynamic programming languges provide.

def x = 23
println x            // 23

x = "hello"
println x           // hello

x = 3.14
println x           // 3.14

x = ["abc", "def"]
println x           // [abc, def]
println x[0]        // abc

x = true
println x           // true


Declare variable as Integer

Integer n = 19
println n       // 19

n = 3.14
println n       // 3

n = "world"    // GroovyCastException

// n = [2, 3]  // GroovyCastException

If we declare a variable to be Integer it provides automatic casting from other numbers, but does not allow the assignment of other types. For example it will throw the following exception if we try to assign a string or a list:

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'world' with class 'java.lang.String' to class 'java.lang.Integer'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'world' with class 'java.lang.String' to class 'java.lang.Integer'
	at variable_types_integer.run(variable_types_integer.groovy:4)

byte

byte b = 1
println b  // 1

b = 127
println b  // 127

b++
println b  // -128

b = 200
println b  // -56

b = 3.4
println b  // 3

b = "hello"  // GroovyCastException

Numbers

// primitive types
byte  b = 1
char  c = 2
short s = 3
int   i = 4
long  l = 5

// infinite precision
BigInteger bi =  6


// primitive types
float  f = 1.234
double d = 2.345

// infinite precision
BigDecimal bd =  3.456

Boolean

We can declare a variable as boolean and then it can only hold true or false, but we can assign any type of value to it and it will be automatically converted to either true or false.

boolean b = false
println b    // false

b = true
println b    // true

b = 2 > 3
println b    // false

b = 2
println b    // true

b = 0
println b    // false

b = "abc"
println b    // true

b = ""
println b    // false

b = ["hello"]
println b    // true

b = []
println b    // false


Groovy Truth provides the details of the coercion to boolean values.

Syntax

See the Groovy syntax for more details.

Comments

boolean b = ""; returns false; however not b = "" even with prior declaration and assignment of b as boolean b = false per se within groovysh shell command prompt

timestamp: 2018-05-27T08:30:01 tags:

  • boolean
  • int
  • byte
  • Integer

Groovy: Undeclared variable - runtime exception - groovy.lang.MissingPropertyException

Unlike the "strongly typed" languges, Groovy does not check the existance of all the variables at compile time. This can lead to run-time exceptions such as groovy.lang.MissingPropertyException

print "Input: "
def val = System.in.newReader().readLine() as Integer

if (val > 10) {
   println "bigger than 10"
} else if (value < 10) {
   println "smaller than 10"
} else {
   println "it is 10"
}

In this script we declare and use a variable called val, but in one point, in the second if-statement, we used the variable name value. Presumably by mistake.

If the input is 10 or more the code runs smoothly, but if the input is less than 10 then we get a run-time exception:

Caught: groovy.lang.MissingPropertyException: No such property: value for class: undeclared_variable
groovy.lang.MissingPropertyException: No such property: value for class: undeclared_variable
	at undeclared_variable.run(undeclared_variable.groovy:6)

timestamp: 2018-05-27T09:30:01 tags:

  • def
  • MissingPropertyException

Groovy: Number guessing game

Number Guessing game exercise

Random random = new Random()
def hidden = random.nextInt(20)

while (true) {
    print "Guess number: "
    def guess = System.in.newReader().readLine() as Integer
    if (guess < hidden) {
        println "Guess was too small"
    } else if (guess > hidden) {
        println "Guess was too hight"
    } else {
        println "Match!"
        break
    }
}

println "Bye"

timestamp: 2018-05-27T10:00:01 tags:

  • Random
  • nextInt
  • System.in.newReader().readLine

Groovy: Determine type of an object

Creating an object called obj of type java.util.ArrayList which implements the java.util.List interface.

instanceof checks if obj is the subclass of some class.

getClass returns the exact type of an object.

def obj = ["question", 42, 'answer']

println obj.getClass()   // class java.util.ArrayList

println (obj instanceof List)                   // true
println (obj instanceof java.util.ArrayList)    // true

println (obj.getClass() == List)                // false
println (obj.getClass() == java.util.ArrayList) // true

timestamp: 2018-06-01T07:30:01 tags:

  • instanceof
  • getClass

Groovy: Lists

Square brackets [] create a list that implements the List interface.

By default it is of type ArrayList though you can create a list of type LinkedList as well.


def a_mess = ["question", 42, 'answer']
println a_mess              // [question, 42, answer]
println a_mess.size()       // 3
println a_mess[0]           // question
println a_mess.getClass()   // class java.util.ArrayList

def names = ['foo', 'bar', 'qux'] as LinkedList
println names               // [foo, bar, qux]
println names.size()        // 3
println names[1]            // bar
println names.getClass()    // class java.util.LinkedList

for (i = 0; i < names.size(); i++) {
   println i + ') ' + names[i]
}
// 0) foo
// 1) bar
// 2) qux


names.each {
    println it
}
// foo
// bar
// qux

names.each { name ->
    println name
}
// foo
// bar
// qux

names.eachWithIndex { name, i ->
    println i +  '] ' + name
}
// 0] foo
// 1] bar
// 2] qux

There are several ways to iterate over the elements of a list.

There is the old-school way of using a for loop. This is like in most of the other languages uses a variable to go over the indexes from 0 to the size-1 and then use this index to access the real value in the list. The name of this internal variable is typically i or j and it does not need to be declared using def.

The each method will also iterate over the elements of the list. For each iteration it will put the current value in a variable called it and then execute the block that follows the each statement. The it is similar to to $_ of Perl and the _ of Python.

Optionally we can set the name of this internal variable by providing it right after the opening { of the block, followed by an arrow.

Finally, we can also use the eachWithIndex in which case we need to define the name of two variables. The first one will get the current value, the second one will get the index of the current value.

Read more about lists in Groovy.

Is element in list? How many times?

The count method will count how many times a values appears in a list. It can be used to check if the values is in the list at all.

def myList = ["Apple", "Banana", "Apple", "Carrots", "Apple"]

println myList.count("Apple")   // 3
println myList.count("Banana")  // 1
println myList.count("Peach")   // 0

timestamp: 2018-06-01T09:00:01 tags:

  • List
  • ArrayList
  • LinkedList
  • size
  • for
  • each
  • eachWithIndex
  • count

Groovy: sum of numbers

Given a file like this where each row is a number, our task is to sum up the numbers.

3
7
23
0
-17
98
12

This is a simple exercise in reading the content of a file.

the File class can open a file for reading and return something that resembles a filehandle in other languages. It is instance of the File class.

It has many methods, the one we are using is called readLines. It will read the whole content of the file and will return a list of the lines. The number of elements in this list is the number of of lines in the file.

We can then iterate over the list using each, convert each value to an Integer (the lines are strings when we read them in) and add them to the sum variable.

sum = 0

fh = new File('examples/data/numbers.txt')
println fh.getClass()        // class java.io.File

def lines = fh.readLines()

lines.each { line ->
    sum += line as Integer
}

println "The sum is: " + sum   // 126


This solution works for small-ish files, but if the files is so big that it cannot fit in memory then either our system starts swapping making the operation very slow or it will just crash.

Read line by line

A better solution that will work both for small and big files is to read the content of the file line-by-line. In this case we only need to hold one line in the memory at any given point of the time. Well, actually the operating system might do some read-ahead and buffering, but that's there for optimizations and you won't run out of memory because of that.

In this solution we the newReader method of the object created by the File() class that will create and return an object of type LineNumberReader. The object, assigned to the reader variable, has a method called readLine that will return the next line in the file or null of there are no more lines.

sum = 0

fh = new File('examples/data/numbers.txt')
reader = fh.newReader()
println reader.getClass()  // class java.io.LineNumberReader

while ((line = reader.readLine()) != null) {
    sum += line as Integer
}

println "The sum is: " + sum   // 126

It is not enough to write this:

while (line = reader.readLine()) {

as this will stop on the first empty row, if there is one in the file.

timestamp: 2018-06-01T11:00:01 tags:

  • File
  • readLines
  • LineNumberReader
  • newReader
  • readLine

Groovy: color selector

Color Selector exercise.

colors = ['Blue', 'Yellow', 'Brown', 'White']

println 'Please select a number:'
colors.eachWithIndex { name, i ->
    println "${i}) ${name}"
}
def selection = System.in.newReader().readLine() as Integer
if (selection < colors.size()) {
    println colors[selection]
} else {
    println "Bad Selection"
}

timestamp: 2018-06-02T08:30:01 tags:

  • eachWithIndex
  • readLine

Groovy: read CSV file

Groovy does not seem to provide a built-in CSV reader, but there are a number of third-party open source implementations.

In this case I am using GroovyCSV that has its source at GitHub.

Read CSV file and add number in the 3rd column

This is the solution to the exercise in which we need to read the file

Tudor;Vidor;10;Hapci
Szundi;Morgo;7;Szende
Kuka;Hofeherke;100;Kiralyno
Boszorkany;Herceg;9;Meselo

and add the numbers in the 3rd column.

In another case we need to read this file:

Budapest,Bukarest,1200,km
Tel Aviv,Beirut,500,km
London,Dublin,300,km
New York,"Moscow, East",6000,km
Local,"Remote
Location",10,km

and again add the 3rd column

The solution for the first file looks like this:

@Grab('com.xlson.groovycsv:groovycsv:1.3')
import static com.xlson.groovycsv.CsvParser.parseCsv

fh = new File('examples/data/process_csv_file.csv')
def csv_content = fh.getText('utf-8')

def data_iterator = parseCsv(csv_content, separator: ';', readFirstLine: true)
// println data_iterator.getClass()  // class com.xlson.groovycsv.CsvIterator

def sum = 0
for (line in data_iterator) {
    sum += line[2] as Integer
}

println sum

The first line tells Groovy to use the Grape dependency management tool and install the package. This will happen the first time we run our code. In subsequent runs it will already use the locally intsalled version of the module.

@Grab('com.xlson.groovycsv:groovycsv:1.3')

The second line tells Groovy to import the parseCsv class from the already installed library.

import static com.xlson.groovycsv.CsvParser.parseCsv

The we open the file using the File class and read in the whole content using the getText method.

fh = new File('examples/data/distance.csv')
def csv_content = fh.getText('utf-8')

The parseCSV function expects the content of the CSV file as its first parameter and then it can also accept configuration options. In our case we set the separator to be ; as our file uses that instead of plain comma , We also set the readFirstLine to be true as we wanted the first row to be treated as data and not as header.

The defaults are , and false respectively. There are some other parameter one can set.

The call to parseCSV return an instance of com.xlson.groovycsv.CsvIterator. We can use that to iterate over the rows.Each iteration line holding an array of the fields of the current line. We can use regular array indexing to access index 2 which is the 3rd column as arrays are 0-based.

@Grab('com.xlson.groovycsv:groovycsv:1.3')
import static com.xlson.groovycsv.CsvParser.parseCsv

fh = new File('examples/data/distance.csv')
def csv_content = fh.getText('utf-8')

def data_iterator = parseCsv(csv_content, readFirstLine: true)

def sum = 0
for (line in data_iterator) {
    sum += line[2] as Integer
}

println sum

The second file uses , as separators which is the default so we don't need to set that explicitly. Other than that the two solutions are identical.

timestamp: 2018-06-02T11:30:01 tags:

  • @Grab
  • import
  • File
  • getText
  • parseCSV
  • separators
  • readFirstLine

Count digits in Groovy

In the count digit exercise we need to take a file like this:

23 34 9512341
3 34 2452345 5353 67 22
42136357013412
42 5 65 64 

and count how many times each digit appears.

counter = [0] * 10
fh = new File('examples/data/count_digits.txt')
reader = fh.newReader()
while ((line = reader.readLine()) != null) {
    for (c in line) {
        if (c in ' ') {
            continue
        }
        counter[ c as Integer ]++
    }
}

for (i=0; i<10; i++) {
    println i + ' ' + counter[i]
}


The expression in the first line creates a list of 10 values of 0.

Then we open the file for reading and create a reader that can read the file line-by-line.

Then we iterate over the lines one-by-one and use the for in construct to iterate over the characters of the string.

Inside the for loop first we check if this is the space charcter. In this solution we assume that the only unwanted character in the whole file is the space.

For every other character we use them as an integer to be the index in the counter list and increment the appropriate number.

At the end we have another for loop to iterate over all the digits and print the number of occurrences.

timestamp: 2018-06-03T12:30:01 tags:

  • File
  • for
  • in
  • continue

Groovy: reading and writing files - appending content

In order to handle files Groovy has a class called File. Let's see some of the basic operations you can do with files.

filename = 'examples/data/count_digits.txt'

// read all the content of the file into a single string
File fh1 = new File(filename)
text = fh1.getText('UTF-8')

// read all the lines into a list, each line is an element in the list
File fh2 = new File(filename)
def lines = fh2.readLines()
for (line in lines) {
    // ...
}


File fh3 = new File(filename)
LineNumberReader reader = fh3.newReader()
while ((line = reader.readLine()) != null) {
    // ...
}

Write a new file

This will remove the content of the old file and start a new file.

File file = new File("out.txt")
file.write "First line\n"
file << "Second line\n"

println file.text

This will append to the end of the file.

File file = new File("out.txt")
file.append("hello\n")
println file.text

Write and Append

If we mix the calls to write and to append we'll get some strange results. For example the following code will only store "third" in the file.

File file = new File("out.txt")
file.write("first\n")
file.append("second\n")
file.write("third\n")

println file.text

Don't do this!

timestamp: 2018-06-03T14:30:01 tags:

  • File
  • getText
  • readLines
  • newReader
  • readLine
  • write
  • append

Groovy: listing the content of a directory, traversing a directory tree

Listing all the files and subdirectories in a given path.

Traversing a directory tree sytarting from a specific path.

dh = new File('.')
dh.eachFile {
    println(it)
}
dh = new File('.')
dh.eachFileRecurse {
    println it
}

timestamp: 2018-06-03T15:30:01 tags:

  • File
  • eachFile
  • eachFileRecurse

Groovy - Regular Expressions - regexes

text = 'Some 42 number #12 more'
def ma = (text =~ /\d+/)
println ma              // java.util.regex.Matcher[pattern=\d+ region=0,23 lastmatch=]
println ma[0]           // 42

def mb = (text =~ /#\d+/)
println mb              // java.util.regex.Matcher[pattern=#\d+ region=0,23 lastmatch=]
println mb[0]           //  #12

def mc = (text =~ /#(\d+)/)
println mc[0]          // [#12, 12]
println mc[0][0]       // #12
println mc[0][1]       // 12
text = '/abc/def/da/de/abc_def_ge.txt'
def m = (text =~ /[^\/]*$/)
println m[0]     // abc_def_ge.txt
url = 'https://10.11.12.13/some_name'
def match = url =~ '^https?://([^/]*)/([^/]*)$'
println match
println match[0]
println match[0][1]
println match[0][2]

timestamp: 2018-07-31T10:30:01 tags:

  • Groovy

Groovy map (dictionary, hash, associative array)

Groovy map access elements

g = [:]       // create map
println(g)

g['name'] = []   // create array
println(g)

g['name'].add("foo")
g['name'].add("bar")
println(g)
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
println colors
println colors.containsKey('red')
println colors.containsKey('black')

for (p in colors) {
    println p.key
    println p.value
}

Get all the keys ina Groovy map

def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']

for (key in colors.keySet()) {
    println(key)
    println(colors[key])
}
red
#FF0000
green
#00FF00
blue
#0000FF

Sorted keys of a Groovy map

def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']

for (key in colors.keySet().sort()) {
    println(key)
    println(colors[key])
}

Values of a Groovy map

def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']

for (key in colors.keySet().sort()) {
    println(key)
    println(colors[key])
}

Return map from a function

def f() {
  return ["a": 2, "b": 3]
}

r = f()
println r['a']
println r['b']

See also maps

timestamp: 2018-07-31T22:30:01 tags:

  • map
  • containsKey
  • key
  • value
  • keySet
  • values

Groovy: JSON - reading and writing

JSON is one of the most popular language-independent formats for data serialization. It is also heavily used for configuration files.

Groovy comes with a module called json to handle various use-cases with JSON.

Parse JSON string

We can use the JsonSlurper class to parse JSON strings.

If we have JSON string in a Groovy variable we can parse it to become a Groovy map:

import groovy.json.JsonSlurper

def json_str = '''{
   "name": "Foo Bar",
   "year": 2018,
   "timestamp": "2018-03-08T00:00:00",
   "tags": [ "person", "employee" ],
   "grade": 3.14 }'''


def jsonSlurper = new JsonSlurper()
cfg = jsonSlurper.parseText(json_str)
println(cfg)          // [name:Foo Bar, year:2018, timestamp:2018-03-08T00:00:00, tags:[person, employee], grade:3.14]
println(cfg['name'])  // Foo Bar
println(cfg.name)     // Foo Bar

Creating JSON string

JsonOutput has several methods. toJson returns a JSON string in one line. prettyPrint returns a nicely formatted JSON string. The latter takes up more space, but it is also human-readable.

import groovy.json.JsonOutput

def data = [
    name: "Foo Bar",
    year: "2018",
    timestamp: "2018-03-08T00:00:00",
    tags: [ "person", "employee"],
    grade: 3.14
]

def json_str = JsonOutput.toJson(data)
println(json_str)

def json_beauty = JsonOutput.prettyPrint(json_str)
println(json_beauty)

In the output you can see both the result of toString and the result of prettyPrint.

{"name":"Foo Bar","year":"2018","timestamp":"2018-03-08T00:00:00","tags":["person","employee"],"grade":3.14}

{
    "name": "Foo Bar",
    "year": "2018",
    "timestamp": "2018-03-08T00:00:00",
    "tags": [
        "person",
        "employee"
    ],
    "grade": 3.14
}

Read JSON from file

import groovy.json.JsonSlurper

if (args.size() < 1) {
    println("Missing filename")
    System.exit(1)
}

filename = args[0]

def jsonSlurper = new JsonSlurper()
data = jsonSlurper.parse(new File(filename))

println(data)

The parse method accepts a File object, reads in the content of the file and then parses it.

Write JSON file

In order to write a JSON file, you need to create the JSON string (either as a plain string or as a beautified string) and then use the File class to save it.

import groovy.json.JsonOutput

if (args.size() < 1) {
    println("Missing filename")
    System.exit(1)
}

filename = args[0]


def data = [
    name: "Foo Bar",
    year: "2018",
    timestamp: "2018-03-08T00:00:00",
    tags: [ "person", "employee"],
    grade: 3.14
]

def json_str = JsonOutput.toJson(data)
def json_beauty = JsonOutput.prettyPrint(json_str)
File file = new File(filename)
file.write(json_beauty)

More JSON

Groovy JSON module

timestamp: 2018-08-02T08:30:01 tags:

  • JSON
  • JsonSlurper
  • parseText

Groovy: Date, Time, Timezone

java.util.TimeZone Date

d = new Date()
println(d)

println(d.getTime())  // epoch

d += 1        // increment days by 1
println(d)

println(d.next())    // next day (incement by 1)
println(d)

println(d.seconds)
println(d.minutes)
println(d.hours)
println(d.day)
println(d.month)
println(d.year)

e = d          // create a copy
e += 3         // increment by 3 days
println(e)
println(d)
z = e-d
println(z)     // 3

Mon Jan 06 20:55:37 IST 2020
1578336937753
Tue Jan 07 20:55:37 IST 2020
Wed Jan 08 20:55:37 IST 2020
Tue Jan 07 20:55:37 IST 2020
37
55
20
2
0
120
Fri Jan 10 20:55:37 IST 2020
Tue Jan 07 20:55:37 IST 2020
3

Adjust Timezone in Groovy

While normally Jeruslame is at UTC+2, during the daylight saving time, it is actually UTC+3. This is reflected in the results.

import java.util.TimeZone

tz = TimeZone.getTimeZone("Asia/Jerusalem")

def ts = new Date()
println(ts)                                 // 12:43:14 UTC 2018
println(ts.format("HH:mm"))                 // 12:43
println(ts.format("HH:mm", timezone=tz))    // 15:43

timestamp: 2018-09-07T16:00:01 tags:

  • Date

Groovy: import and use functions from another file

Code reuse is an important part of programming. The smallest possible way is to create functions and call them several times in the same code. The next step is to have a set of functions in a file and use those functions in several other files.

In these examples we see how to do that with simple functions and methods of classes.

Importing function

In this example we have a very simple "library" file with a simple function:

def greet() {
    println "Hello World!"
}

Next to it there is another file in which we load the former file into memory and then call it.

GroovyShell shell = new GroovyShell()
def tools = shell.parse(new File('function_tools.gvy'))
tools.greet()

We can then run

groovy function_script.gvy

In the code we gave the path to the library so in this version it needs to be next to the code loading it.

Importing class methods

This is the class:

class Tools {
    def greet() {
        println "Hello World!"
    }
}

This is the script:

def tools = new GroovyScriptEngine( '.' ).with {
    loadScriptByName( 'class_tools.gvy' )
}
this.metaClass.mixin tools
greet()

Importing class methods

import tools

t = new tools()
t.hello()            // Hello World

// this also works:
new tools().hello()  // Hello World

class tools {
    def hello() {
        println("Hello World")
    }
}

Import class from a subdirectory

import tools.other
new other().hi()
package tools

class other {
   def hi() {
       println("Hello Again")
   }
}

Import static methods from a class

This is probably the version most similar to importing individual functions.

import static tools.hello as hi
hi()

class tools {
    static hello() {
        println("Hello World")
    }
}

Import static methods from a class from a subdirectory

import static some.other.Tools.hello as hi
hi()

package some.other

class Tools {
    static hello() {
        println("Hello World")
    }
}


timestamp: 2018-09-13T20:30:01 tags:

  • GroovyShell

Groovy: Random numbers, random selection from list of values

In order to generate pseudo-random numbers in Groovy, we can use the Math.random() method or the Random class provided by Java.

Random float

The random method will generate a floating point number between 0 and 1. (0 included 1 excluded).

println(Math.random())

Random integers

Random rnd = new Random()
println(rnd.next(2)) // 2 bits of random number that is, one of the following: 0,1,2,3
println(rnd.nextInt(3)) // random integer in the range of 0, 3  (so one of 0,1, 2)


In the next example we have a list of one-letter strings and we would like to pick one of the elements randomly. So we need an integer between 0 and the size of the array.

We run it in a loop so we can see more values picked.

def z = ["a", "b", "c", "d", "e"]
Random rnd = new Random()

for (i=0; i < 10; i++) {
   println(z[rnd.nextInt(z.size)])
}

timestamp: 2018-09-14T11:00:01 tags:

  • Random
  • next
  • nextInt
  • Math.random

Groovy: Closures

closures

def add = { x, y ->
   //println('add')
   return x+y
}

def multiply = { x, y ->
   //println('multiply')
   return x*y
}


def calc(a, b, f) {
   //println('calc')
   println(f(a, b))
}

calc(4, 5, add)
calc(4, 5, multiply)

timestamp: 2018-09-14T11:30:01 tags:

  • closures

Groovy: remove spaces from a string

Using a regular expression in Groovy to remove all the spaces from a string.

Remove all the spaces from a string. It is like trim, trim-left, and trim-right together.

def input_text = " hello world "
clean_text = input_text.replaceAll("\\s","")
println("'${input_text}'")   // ' hello world '
println("'${clean_text}'")   // 'helloworld'
$ groovy remove_spaces.gvy

' hello world '
'helloworld'

Without the need to doubl-escape using ~//

def input_text = " hello world "
clean_text = input_text.replaceAll(~/\s/,"")
println("'${input_text}'")   // ' hello world '
println("'${clean_text}'")   // 'helloworld'
groovy remove_spaces_no_escape.gvy

timestamp: 2018-10-30T09:30:01 tags:

  • replaceAll
  • ~//
  • trim

Groovy: temporary file with autodelete

File.createTempFile("temp",".tmp").with {
   //deleteOnExit()  // Including this line will cause the temp file to be deleted automatically

   write "Hello world"    // write to the temp file
   println absolutePath   // This is the path to the file
}
File tf = File.createTempFile("temp",".tmp")
tf.write("Hello world")   // write to the file
println(tf.absolutePath)  // path to the file
tf.delete()               // delete the file

Comments

Thank you very much, your answer resolved my issue:

def map1 = [:]
map1.put('jfr_1', "Hello World!")
def i = 1
def x = map1."jfr_$i"
println "x = " + "${x}" ----> x = Hello World!


 def jfr_1 = "Hello World!"
def i = 1
    def x = "jfr_$i"
    println "${x}"

Above code prints: jfr_1 instead of Hello World! What I'm doing wrong?


Nothing. That's the expected behaviour.


Thank you for the reply, how can I print "Hello World!" instead Using PERL print ($$x) will print "Hello World!".


Even in Perl you should not do that and you should "use strict" to make sure you don't do it by mistake. In Perl you'd use a hash in Groovy a map for that kind of data structure.

timestamp: 2018-10-30T10:30:01 tags:

  • File
  • createTempFile
  • write
  • absolutePath
  • delete

Groovy: relative path

import groovy.transform.SourceURI
import java.nio.file.Path
import java.nio.file.Paths

@SourceURI
URI sourceUri

Path scriptLocation = Paths.get(sourceUri)
println(scriptLocation)                     // path to the current executable
println(scriptLocation.getParent())         // parent dir
println(scriptLocation.resolveSibling('tools.gvy'))  //sibling of the current executable

timestamp: 2018-10-30T11:30:01 tags:

  • SourceURI
  • Path
  • Paths
  • get
  • getParent
  • resolveSibling

Return multiple values from a function

def f() {
   return [2, 3]
}

(a, b) = f()
println a
println b

timestamp: 2018-10-30T11:40:01 tags:

  • return

Groovy string length

The length method of a string object in Grooy will return the number of characters in the string:

name = 'Foo Bar Moo'
len = name.length()
println(len)          // 11

hebrew = 'שלום'
println(hebrew.length())  // 4

timestamp: 2019-02-15T22:30:01 tags:

  • length

Groovy: substring

The substring method of a string will return a part of the string.

If given two parameters, thense defined the range of the charactes (beginning included, end excluded). If only one parameter is given this is the beginning of the substring.

The indexing is 0 based so STRING.substring(0,3) means the first 3 characters. and STRING.substring(4,7) means the charcter number, 5,6, and 7. (index 4, 5, and 6).

name = 'Foo Bar Moo'
println(name)                // Foo Bar Moo
fname = name.substring(0, 3)
println(fname)               // Foo

mname = name.substring(4, 7)
println(mname)               // Bar

lname = name.substring(name.length()-3)
println(lname)               // Moo

timestamp: 2019-02-15T23:32:01 tags:

  • substring

Groovy: for loop - break - continue

for (i=0; i < 10; i++) {
    if (i > 2 && i < 5) {
        continue
    }
    if (i > 7) {
        break
    }
    println(i)
}

0
1
2
5
6
7

timestamp: 2019-02-21T21:30:01 tags:

  • for
  • break
  • continue

Groovy code reuse

In programming we care a lot about code reuse. Partly bacause we are lazy and we don't want to write the same code twice. Partially because we know that we will find bugs in our code and we'll need to fix them. If we have written the same code twice we now will have to fix the same problem in two places. Knowing how bad we are in tracking our code we will surelly forget some of the copies.

So here are a number of ways how you can reuse code in Groovy.

  • Groovy Functions. Insides the same file we can create functions and call them from various places in the file. See also Return multiple values from a function
  • Groovy classes provide a better abstraction of certain functionality in our code. Given a class we can create several instances that will all have the same behavior. In this example we are still restricted to a single file.
  • Import and reused functions. We can import functions from other files allowing us to reuse the same functions in several places. Also allowing us to distribute our functions and let other use them as well. Either within the organization or maybe even outside of it.
  • Import variables (or constants). Same as importing functions.
  • Import class. Like importing functions, but provide whole classes.

timestamp: 2019-04-08T20:30:01 tags:

  • Groovy

Groovy functions

Functions are probably the most basic tools for code reuse in Groovy.

Hello World in a function

The def keyword allows use to define a function that we can use in the code.

hi()

def hi() {
    println("Hello World!")
}

After the def keyword we provide the name of the function and then in parentheses the list of expected parameters. In our first example there are no parameters.

Then within curly braces we put the body of the function.

We can put the definition of the function anywhere in the file. A good practice would be to put all the functions in the end of the file and put the main body of the code at the top. That will make it easier to read.

Better yet, you might want to put all your code in functions and leave only a single call to a single function in the main body of your code. That will probably help keeping the code clean.

Passing parameters and returning a result

In this example we created a function that was designed to add two numbers and return the result. We can call it with exactly two numbers and it will return the sum.


def add(x, y) {
    return x+y
}

z = add(2, 3)
println(z)   // 5


// z = add(2)

// z = add(2, 3, 4)

z = add('abc', 'def')
println(z)     // abcdef


z = add('abc', 42)
println(z)      // abc42

If we call it with only one parameter we'll get the following exception:

Caught: groovy.lang.MissingMethodException: No signature of method: add_function.add() is applicable for argument types: (java.lang.Integer) values: [2]
Possible solutions: add(java.lang.Object, java.lang.Object), any(), any(groovy.lang.Closure), wait(), run(), run()
groovy.lang.MissingMethodException: No signature of method: add_function.add() is applicable for argument types: (java.lang.Integer) values: [2]
Possible solutions: add(java.lang.Object, java.lang.Object), any(), any(groovy.lang.Closure), wait(), run(), run()
	at add_function.run(add_function.groovy:10)

If we call it with more than 2 parameters we get this exception:

Caught: groovy.lang.MissingMethodException: No signature of method: add_function.add() is applicable for argument types: (java.lang.Integer, java.lang.Integer, java.lang.Integer) values: [2, 3, 4]
Possible solutions: any(), add(java.lang.Object, java.lang.Object), wait(), run(), run(), find()
groovy.lang.MissingMethodException: No signature of method: add_function.add() is applicable for argument types: (java.lang.Integer, java.lang.Integer, java.lang.Integer) values: [2, 3, 4]
Possible solutions: any(), add(java.lang.Object, java.lang.Object), wait(), run(), run(), find()
	at add_function.run(add_function.groovy:12)

As you can see in the example we can also pass strings to it and then + will concatenate them and we can also pass a string and a number and it will concatenate those too.

If this is the behavior you hoped for then it is great.

Defining the type of the parameters of a Groovy function

In Groovy you can use the Groovy types to specify what kind of values a function is expected to receive. For example here we declare that our add function is expecting two Integer values.


def add(Integer x, Integer y) {
    return x+y
}

println(add(2, 3))      // 5

// add("abc", 3)

If we call it with two integers we get the correct answer. However if we try to pass a string, Groovy will give us an exception like this:

Caught: groovy.lang.MissingMethodException: No signature of method: add_integers.add() is applicable for argument types: (java.lang.String, java.lang.Integer) values: [abc, 3]
Possible solutions: add(java.lang.Integer, java.lang.Integer), any(), wait(), run(), run(), find()
groovy.lang.MissingMethodException: No signature of method: add_integers.add() is applicable for argument types: (java.lang.String, java.lang.Integer) values: [abc, 3]
Possible solutions: add(java.lang.Integer, java.lang.Integer), any(), wait(), run(), run(), find()
	at add_integers.run(add_integers.groovy:8)

timestamp: 2019-04-08T20:10:01 tags:

  • Groovy
  • def
  • Integer

Groovy: evaluate code in another file

Another option in code reuse in Groovy.


println('before')
evaluate(new File("tools.groovy"))
println('after')
println(answer)     // 42

// println(pi)

hi()
println("in tools")

def hi() {
    println('hello')
}

answer = 42

def pi = 3.14

When we run groovy main.groovy

Using the def keyword to define a variable will make it inaccessible from the file that evaluated this code:

Caught: groovy.lang.MissingPropertyException: No such property: pi for class: main
groovy.lang.MissingPropertyException: No such property: pi for class: main
	at main.run(main.groovy:7)

Probably for the same reason functions defined in the other file cannot be accessed from the evaluating file.

Caught: groovy.lang.MissingMethodException: No signature of method: main.hi() is applicable for argument types: () values: []
Possible solutions: is(java.lang.Object), wait(), run(), run(), any(), find()
groovy.lang.MissingMethodException: No signature of method: main.hi() is applicable for argument types: () values: []
Possible solutions: is(java.lang.Object), wait(), run(), run(), any(), find()
	at main.run(main.groovy:9)

timestamp: 2019-04-09T11:30:01 tags:

  • evaluate

Groovy classes

Defined class, create instance, call method

class Example {
    def hello() {
        println("Hello World")
    }
}
e = new Example()
e.hello()

timestamp: 2019-04-09T12:00:01 tags:

  • class
  • new

Groovy function overloading

The primary tool for code reuse in Groovy is the possibility to defined and call functions.

We have already seen that we need to tell Groovy how many parameter a function expects and we can even ask Groovy to verify the type of the parameters.

We have not discussed yet how can you be flexible with this?

Groovy allows you to define multiple versions of the same function with different signatures. That is, different set of expected parameters.

Optional parameter

One of the uses of his facility is to have some of the parameters become optional.

In the following example we have a simple function called prompt that would receive a text and a number. It would prompt the user with the text and check the input against some value. (In our example it is a simple variable. In a more realistic situation we would have the password hashed and probably stored in a database.)

If the user makes a mistake s/he is prompted again and again.

The number of times the user can try is set by the second parameter.

In our example we also have a second definition of the prompt function that only expects a string. It then calls the same name again (prompt passing to it the receives text and the number 3.


def prompt(text, Integer cnt) {
    def pw = 'secret'
    while (cnt > 0) {
        res = System.console().readLine text
        if (res == 'secret') {
            return true
        }
        cnt--
    }
    return false
}

def prompt(text) {
    prompt(text, 3)
}

// println(prompt('Password: ', 2))
println(prompt('Password: '))

If we call prompt with a text and a number, the first version will be executed.

If we call prompt with only a string, the second version will be executed. It will call prompt with the same string and the number 3. This time Groovy will execute the first version of the function.

Same function with different types

In this example you can see how we declared the same function name 3 times. Each time expecting different types of arguments. Then we call the function and we can see Groovy calls the right implementation in each case. The order of the definition is not important, you could put the general case earlier as well, but it seems to be clearer to me to first have the special cases declared and only later the more generic ones.

def add(Integer x, Integer y) {
    println("Add integers")
}

def add(String x, String y) {
    println("Add strings")
}

def add(x, y) {
    println("Add any two things")
}



add(2, 3)             // Add integers
add("abc", "def")     // Add strings
add(2.3, 4)           // Add any two things
add('a', 4)           // Add any two things

timestamp: 2019-04-09T14:30:01 tags:

  • def

Groovy variable scope

The scope of variables is where we can access the variables.

By default variables are global

By assigning value to a new variable name we create that variable. Groovy does not require any special syntax or keyword to declare a variable.

If we access the same variable name within a function (either reading it with println in this case or writing it when we assign a new value to it), we access the same global variable.


x = 42

def f() {
    println(x)  // 42
    x = 23
    println(x)  // 23
}


f()
println(x)     // 23

Create global variable inside a function

We don't need the first global definition. If we assign a value to a variable inside a function, it will create a global variable that will remain in scope even after the function has finished running.


def f() {
    x = 23
    println(x)
}

f()                 // 23
println(x)          // 23

Declare local variable with def

We can use the def keyword to declare a variable local. In the first example we can see that there is a global variable (which was not declared using def) which is then accessible inside the function (println) just as we saw in the first example. Once we use the def keyword to declare the same variable name inside the function it creates a new variable, hiding the global one.

Once we exit the function the local version is destroyed and outside the function we access the global variable again.


x = 42

def f() {
    println(x)      // 42
    def x = 23
    println(x)      // 23
}


f()
println(x)          // 42

If you use def to declare the variable outside of all the functions, you won't be able to access it inside the function. (The first print statement in the next example would throw the exception shown in the comment.)

Assiging to a variable inside the function, even if we don't use def to declare it, will create a new, local variable:


def x = 42

def f() {
    //println(x)  // Caught: groovy.lang.MissingPropertyException: No such property: x for class: scope
    x = 23
    println(x)      // 23
}


f()
println(x)          // 42

The best option is when you declare your variables both inside and outside of functions using the def keyword. That makes it clear both to Groovy and to the reader that your intention was to create locally scoped variables.


def x = 42

def f() {
    // println(x)  // Caught: groovy.lang.MissingPropertyException: No such property: x for class: scope
    def x = 23
    println(x)      // 23
}


f()
println(x)          // 42

Shall we use global or local variables?

Global variables might make it easy to write the first version of the program, but then, as the program grows it becomes harder and harder to maintain it. Not a recommended practice. You are much better off working a bit harder and always declaring your variables in every scope.

Scope in a block?

Some languages (most notably Perl) would create a scope for every block - for every pair of curly braces. This is not the case in Groovy.


def x = 42

if (x > 10) {
    x = 12
}


println(x)   // 12

In this example you can see that you cannot re-declare a variable inside a block as that would cause a compile-time error:


def x = 42

if (x > 10) {
    def x = 12  // Exception
}


println(x)
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
scope_in_a_block.groovy: 6: The current scope already contains a variable of the name x
 @ line 6, column 9.
       def x = 12
           ^

1 error

On the other hand you can declare variables inside a block (but apparently only if they did not exist outsdide the block) and they will cease to exist at the end of the block.

This example prints the 12 and then when it tries to access the variable outside of the block it will raise an exception.



if (true) {
    def x = 12
    println(x)  // 12
}


println(x)
12
Caught: groovy.lang.MissingPropertyException: No such property: x for class: def_only_in_a_block
groovy.lang.MissingPropertyException: No such property: x for class: def_only_in_a_block
	at def_only_in_a_block.run(def_only_in_a_block.groovy:9)

timestamp: 2019-04-12T09:30:01 tags:

  • def

Groovy recursive functions

Recursive functions are functions that call themselves.

In many cases using recursive functions greatly simplifies the code we need to write.

For example when traversing some tree-like data structure.

One critical point in every recursive function is that there most be some stop-condition, that will not create further recursive calls. Otherwise we would end up in an infinite deep black hole.

Factorial in recursive

The mathematical expression n! ( factorial) can be defined in the straigh forward way as: 1 * 2 * ... * n or in the recursive way:

1!     = 1
n!     = n * (n-1)!

In a similar fashion we can implement the calculation of n! in both ways. The second way is called recursive definition and it is implemented with recursive function calls:


def fact(n) {
    if (n == 1) {
       return 1
    }
    return n * fact(n-1)
}

println( fact(5) )  //     120
println( fact(10) ) // 3628800


What we must not forget is that we need to check for the stop-condition (the n == 1) before the recursive call.

## Fibonacci in recursive call

[Fibonacci series](https://en.wikipedia.org/wiki/Fibonacci_number) is usually defined in a recursive formula:

f(1) 1 f(2) 1 f(n) f(n-1) + f(n-2)


It can be implemented in this way:

```groovy


def fibo(n) {
    if (n == 1 || n == 2) {
        return 1
    }
    return fibo(n-1) + fibo(n-2)
}

println( fibo(1) )  // 1
println( fibo(2) )  // 1
println( fibo(3) )  // 2
println( fibo(4) )  // 3
println( fibo(5) )  // 5
println( fibo(6) )  // 8

## Recursive

For this example we have created an imaginary tree-structure. A dependency tree. Each file lists its dependencies.

We start with the "main" file:

a b


c d


d e f


f


The script to traverse the tree in a recursive fashion is this:

```groovy

root = '../data/dependencies/'

def list_dependencies(name) {
    def path = root + name + '.txt'
    def fh = new File(path)
    if (! fh.exists()) {
        return
    }

    def reader = fh.newReader()
    while ((line = reader.readLine()) != null) {
        println(line)
        list_dependencies(line)
    }
}

list_dependencies('main')

timestamp: 2019-04-16T16:30:01 tags:

  • def

Groovy command line arguments (args)

println(args.size())

for (i = 0; i < args.size(); i++) {
    println(i + ' ' + args[i])
}

Run as groovy cli.groovy hello world "hello world" to see how this works.

timestamp: 2019-04-16T14:30:01 tags:

  • args

Groovy exit - System.exit - early exit from Groovy script


if (args.size() < 1) {
    System.exit(42)
}

System.exit(0)
groovy early_exit.groovy
echo $?
42
groovy early_exit.groovy  param
echo $?
0

See also System

timestamp: 2019-04-16T15:30:01 tags:

  • exit
  • System.exit

Groovy file and directory attributes


if (args.size() < 1) {
    println("Missing filename")
    System.exit(1)
}

name = args[0]

fh = new File(name)
println("file      : " + fh.isFile())
println("dir       : " + fh.isDirectory())
println("executable: " + fh.canExecute())

See also File

timestamp: 2019-04-16T15:50:01 tags:

  • File
  • canExecute
  • isFile
  • isDirectory

Groovy: join elements of an array


def names = ['Foo', 'Bar', 'Zorg']

def names_str = names.join('-')
println(names_str)

println( names.join(' ') )

println( names.join('\n') )

The output is:

Foo-Bar-Zorg
Foo Bar Zorg
Foo
Bar
Zorg

timestamp: 2019-04-17T20:30:01 tags:

  • join

Groovy pop push

In Groovy you can use an array as if it was a stack pushing elements to the end and poping elements from the end.

names = []

names.push('Mary')
names.push('Joe')
names.push('Fanny')
names.push('George')
names.push('Liz')
names.push('Peter')

println(names)

first = names.pop()
println(first)
println(names)

[Mary, Joe, Fanny, George, Liz, Peter]
Peter
[Mary, Joe, Fanny, George, Liz]

Pop from empty array raises exception

names = []
names.pop()

Caught: java.util.NoSuchElementException: Cannot pop() an empty List
java.util.NoSuchElementException: Cannot pop() an empty List
	at pop_empty.run(pop_empty.groovy:2)

Check emptyness before calling pop

To avoid the exception we can check the size of the array before calling pop.

names = []

if (names.size()) {
    println(names.pop())
}

timestamp: 2019-04-20T07:30:01 tags:

  • pop
  • push
  • size

Groovy: Formatted printing with printf and sprintf

The function printf can be use to format a string and print to screen.

The function sprintf can be used to format a string for later use.

A few examples:

def x = 66


def res = sprintf("value: %s", x)   // as string
println(res)
println(sprintf("value: %d", x))    // as decimal
println(sprintf("value: %c", x))    // as character


//  padding with 0
printf('%05d\n', x)
println( sprintf('%05d', x)  )


// indicate location of the value
names = ['First', 'Second', 'Third', 'Fourt']
println( sprintf('%2$s %3$s %3$s %1$s', names) )

def v = 65
printf("<%s>\n", v);     // <65>
printf("<%10s>\n", v);   // <      65>
printf("<%-10s>\n", v);  // <65      >
printf("<%c>\n", v);     // <A>
printf("<%d>\n", v);     // <65>
printf("<%05d>\n", v);   // <00065>

timestamp: 2019-04-20T09:30:01 tags:

  • printf
  • sprintf

Groovy System properties

for (key in System.properties.keySet().sort()) {
    printf('%-30s   %s\n', key, System.properties[key])
}
awt.toolkit                      sun.awt.X11.XToolkit
file.encoding                    UTF-8
file.encoding.pkg                sun.io
file.separator                   /
groovy.home                      /usr/share/groovy
groovy.starter.conf              /usr/share/groovy/conf/groovy-starter.conf
java.awt.graphicsenv             sun.awt.X11GraphicsEnvironment
java.awt.printerjob              sun.print.PSPrinterJob
java.class.path                  /usr/share/groovy/lib/groovy-2.4.16.jar
java.class.version               52.0
java.endorsed.dirs               /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/endorsed
java.ext.dirs                    /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext:/usr/java/packages/lib/ext
java.home                        /usr/lib/jvm/java-8-openjdk-amd64/jre
java.io.tmpdir                   /tmp
java.library.path                /usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
java.runtime.name                OpenJDK Runtime Environment
java.runtime.version             1.8.0_191-8u191-b12-2ubuntu0.18.10.1-b12
java.specification.name          Java Platform API Specification
java.specification.vendor        Oracle Corporation
java.specification.version       1.8
java.vendor                      Oracle Corporation
java.vendor.url                  http://java.oracle.com/
java.vendor.url.bug              http://bugreport.sun.com/bugreport/
java.version                     1.8.0_191
java.vm.info                     mixed mode
java.vm.name                     OpenJDK 64-Bit Server VM
java.vm.specification.name       Java Virtual Machine Specification
java.vm.specification.vendor     Oracle Corporation
java.vm.specification.version    1.8
java.vm.vendor                   Oracle Corporation
java.vm.version                  25.191-b12
line.separator                   

os.arch                          amd64
os.name                          Linux
os.version                       4.18.0-16-generic
path.separator                   :
program.name                     groovy
script.name                      /usr/bin/groovy
sun.arch.data.model              64
sun.boot.class.path              /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jfr.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/classes
sun.boot.library.path            /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64
sun.cpu.endian                   little
sun.cpu.isalist                  
sun.desktop                      gnome
sun.io.unicode.encoding          UnicodeLittle
sun.java.command                 org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /usr/share/groovy/conf/groovy-starter.conf --classpath . show_properties.groovy
sun.java.launcher                SUN_STANDARD
sun.jnu.encoding                 UTF-8
sun.management.compiler          HotSpot 64-Bit Tiered Compilers
sun.os.patch.level               unknown
tools.jar                        /usr/lib/jvm/java-8-openjdk-amd64//lib/tools.jar
user.country                     IL
user.dir                         /home/gabor/work/code-maven.com/examples/groovy
user.home                        /home/gabor
user.language                    en
user.name                        gabor
user.timezone                    

timestamp: 2019-04-20T10:30:01 tags:

  • System
  • properties

Groovy path to current executable script

def current_script = getClass().protectionDomain.codeSource.location.path
println(current_script)

This will print the full path to the current Groovy script.

timestamp: 2019-04-20T11:00:01 tags:

  • getClass
  • path

Groovy Exception handling (try, catch, Exception)

def div(a, b) {
    return a/b
}



if (args.size() < 2) {
    println("You need to pass two numbers")
    System.exit(1)
}


def res = div(args[0] as Integer, args[1] as Integer)
println(res)

It works well if the division work well, but:

$ groovy divide.groovy 3 0

Caught: java.lang.ArithmeticException: Division by zero
java.lang.ArithmeticException: Division by zero
	at divide.div(divide.groovy:2)
	at divide.run(divide.groovy:13)

We can use try and catch to catch the exception:

def div(a, b) {
    return a/b
}



if (args.size() < 2) {
    println("You need to pass two numbers")
    System.exit(1)
}


try {
    def res = div(args[0] as Integer, args[1] as Integer)
    println(res)
} catch(Exception e) {
    println("Exception: ${e}")
}

timestamp: 2019-04-21T15:30:01 tags:

  • try
  • catch
  • Exception

Groovy throw (raise) exception

Being able to catch exceptions is important, but so is the ability to raise exceptions (or throw exceptions) as it is called in Groovy.

If you pass a negative number to the Math.sqrt method, it will return a value called NaN Not A Number.


println( Math.sqrt( 4 ))    // 2.0
println( Math.sqrt( -1 ))   // NaN
println('still alive')      // still alive

What if you'd like to write your own sqrt function that will throw an exception if a negative value is passed to it?

Here is a solution:


def sqrt(int n) {
    if (n < 0) {
        throw new Exception("The number ${n} was negative")
    }
    return Math.sqrt(n)
}


println( sqrt( 4 ))    // 2.0
println( sqrt( -1 ))   // exception
println('still alive') // is not executed...
2.0
Caught: java.lang.Exception: The number -1 was negative
java.lang.Exception: The number -1 was negative
	at my_sqrt.sqrt(my_sqrt.groovy:4)
	at my_sqrt$sqrt.callCurrent(Unknown Source)
	at my_sqrt.run(my_sqrt.groovy:11)

The code that would print "still alive" is not executed.

Catch my exception


def sqrt(int n) {
    if (n < 0) {
        throw new Exception("The number ${n} was negative")
    }
    return Math.sqrt(n)
}


println( sqrt( 4 ))    // 2.0
try {
   println( sqrt( -1 ))
} catch(Exception e) {
    println("Exception: ${e}")
}                      // Exception: java.lang.Exception: The number -1 was negative
println('still alive') // still alive

timestamp: 2019-04-21T16:30:01 tags:

  • throw
  • Exception
  • try
  • catch

Groovy casting



def x = "23"

println(x + 4)  // 234

def y = x as Integer
println(y + 4)        // 27

println((x as Integer) + 4)  // 27


def names = ['Foo', 'Bar']
z = names as String
println(names)   // [Foo, Bar]
println(z)       // [Foo, Bar]

println(names.getClass())   // class java.util.ArrayList
println(z.getClass())       // class java.lang.String

timestamp: 2019-04-21T16:50:01 tags:

  • as
  • Integer
  • String

Printing Unicode characters from Groovy

Printing Unicode characters from Groovy Seems to work out of the box. At least on Linux.

def latin_letters = "Hello World"
println latin_letters

def hungarian = "Álom ló és ő egy ügyes ökör."
println hungarian

def hebrew = "שלום עולם"
println hebrew

def arabic = "السلام عليكم"
println arabic

timestamp: 2020-10-03T15:30:01 tags:

  • Groovy

Groovy: import standard libraries

Import and use XML parsing

import groovy.xml.MarkupBuilder
def xml = new MarkupBuilder()
println(xml)


Date

Some classes are imported by default

d = new Date()
println(d)


See more examples with Groovy Date.

TRUE and FALSE

// import Boolean.FALSE  // this does not work
import static Boolean.FALSE
assert !FALSE
println(!FALSE)


Check this out also on the Groovy page about structure

timestamp: 2019-05-07T16:30:01 tags:

  • XML
  • TRUE
  • FALSE

Groovy iterate over map keys

def data = [
    name : 'Foo Bar',
    age : 42,
    email : 'zoo@bor.com',
]

println(data)

for (field in data.keySet()) {
   println(field)
}

my_keys = data.keySet()
println(my_keys.getClass())     // class java.util.LinkedHashMap$LinkedKeySet

If instead of iterating over the keys, you'd like to create an Array from the key, there is another example to convert the LinkedKeySet to and ArrayList.

timestamp: 2019-08-24T08:32:01 tags:

  • keySet
  • getClass

Groovy get the list of keys of a map as an ArrayList

def data = [ name : 'Foo Bar', age : 42, email : 'zoo@bor.com', ]

println(data)

my_keys = data.keySet() println(my_keys.getClass()) // class java.util.LinkedHashMap$LinkedKeySet

our_keys = my_keys as ArrayList println(our_keys.getClass()) // class java.util.ArrayList println(our_keys)

If you only want to iterate over the map keys, you don't need to convert them into and ArrayList.

timestamp: 2019-08-24T08:30:01 tags:

  • keySet
  • ArrayList
  • getClass