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
-
Hello World in Groovy print, println
-
Reading from STDIN in Groovy Console, System, readLine, System.in.newReader().readLine() as Integer
-
Groovy types boolean, int, byte, Integer
-
Groovy: Undeclared variable - runtime exception - groovy.lang.MissingPropertyException def, MissingPropertyException
-
Groovy: Number guessing game Random, nextInt, System.in.newReader().readLine
-
Determine type of an object in Groovy instanceof, getClass
-
Lists in Groovy List, ArrayList, LinkedList, size, for, each, eachWithIndex, count
-
Sum of numbers File, readLines, LineNumberReader, newReader, readLine
-
Read CSV file in Groovy @Grab, import, File, getText, parseCSV, separators, readFirstLine
-
reading and writing files - appending content in Groovy File, getText, readLines, newReader, readLine, write, append
-
listing the content of a directory, traversing a directory tree eachFile, eachFileRecurse
-
Groovy map (dictionary, hash, associative array.md) map, containsKey, key, value, keySet, sort (keys, values)
-
Groovy: Random numbers, random selection from list of values
-
Groovy: remove spaces from a string (replaceAll)
-
Groovy: temporary file with auto delete (File, createTempFile, deleteOnExit, absolutePath)
-
Groovy: relative path (SourceURI, Path, Paths, get, getParent, resolveSibling)
-
Groovy variable scope (def)
-
Command line parameters
-
Groovy file and directory attributes File, canExecute, isFile, isDirectory
-
Exception handling (try, catch, Exception)
-
Casting Integer, String, ...
-
STDOUT/STDERR
-
Read/Write YAML files
-
Read/Write INI files
-
Read/Write XML files
-
HTTP request
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
- Interpolation can be used
- matcher.matches vs being null ?
- \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
- 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
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
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
timestamp: 2018-08-02T08:30:01 tags:
- JSON
- JsonSlurper
- parseText
Groovy: Date, Time, Timezone
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
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