An overview of the Groovy language and its awesome ecosystem, advocating Groovy as the language of choice for (a) Java developers that want to dive into dynamic languages or (b) for Javascript, Ruby or Python developers that want to dive into the Java platform.
The presentation was given at the 9th FOSSCOMM (16-17 April 2016) organized by the Software Libre Sociecy of the University of Piraues.
1. Apache Groovy:
the language and its ecosystem
Kostas Saidis, Agapios Avramidis
www.niovity.com
9th
FOSSCOMM
Free and Open Source Software Communities Meeting
April 16, 2016
3. Niovity
We are a software company
using a Java/Groovy/Javascript stack
4. Niovity Butterfly
We offer a web-based repository platform
for end-to-end data management
Our clients include Academic Libraries, Public Benefit Foundations, Research Institutes and Private Companies
8. The Java what?
The Java Platform
1. The Java language
2. The Java development kit (JDK)
3. The Java virtual machine (JVM)
The JVM is the key component!
9. The JVM goes Polyglot
The Java Virtual Machine
A rock-solid, enterprise-grade runtime environment that can
execute multiple languages (not only Java).
Groovy, Javascript, Ruby, Python, Scala, Clojure, Kotlin, Fantom
and many others...
10. Most of the additional JVM languages are dynamic ones!
Dynamic Languages
Execute many common programming behaviors at runtime –in
contrast to static languages that perform them during
compilation.
Dynamic type checking.
Dynamic method dispatch†
.
Support meta-programming (compiled constructs can be
modified programmatically at runtime).
†
made faster with the invokedynamic bytecode instruction introduced in Java 7.
17. Why Groovy #1
Groovy feels like a superset of Java with a simpler syntax
Designed as a companion language for Java: Groovy is
syntactically aligned with Java.
Augments Java with additional features.
Literals for lists, maps, ranges, regular expressions, string
interpolation with GStrings.
GDK libraries extend JDK libraries in so many helpful ways.
Supported by all major Java IDEs (Eclipse, IntelliJ, Netbeans).
18. Groovy is Java on Steroids!
Groovy powerful switch statement
1 switch(val) {
2 case ”String”: //a string
3 break
4 case 10..100: //a range
5 break
6 case Date: //a date instance
7 break
8 case ~/gw+/: //a reg−ex
9 break
10 case [’A’, ’B’]: //a list
11 break
12 case { it instanceOf Number && it > Integer.MAX_VALUE }
13 //a closure
14 break
15 default:
16 //the default, treated as an ”else” in Groovy.
17 }
19. New methods introduced in Java libraries
List files recursively
groovy −e ”new File(’.’).eachFileRecurse { println it }”
The method eachFileRecurse has been added to the
java.io.File class.
Also an example of executing code given directly as text. All
dynamic languages support this.
20. A better syntax for common things
Example
1 //lists
2 List<Integer> list = [1, 2, 3]
3 assert list[0] == 1
4 //operator overloading
5 list << 4
6 assert list.size() == 4
7 //maps
8 Map<String, String> map = [’one’:’1’, ”two”: ”2”, three:’3’]
9 assert list[1] == map[’two’] as Integer
10 map.one = ’none’
11 //GStrings
12 String s = ”string”
13 println ”value of s = $s”
14 //Java ordinary methods are here
15 map.put(s, ’4’)
16 //with optional parentheses
17 map.put s, 4
21. Why Groovy #2
Groovy is Object-oriented
Supports Java Interfaces, Classes and Enums.
With some additional conventions and facilities (e.g. Groovy
properties) that make our life easier.
Supports Traits: a controlled way to implement multiple
inheritance, avoiding the diamond issue.
22. POGOs: Fat-free POJOs
Employee.groovy
1 class Person {
2 String name
3 String surname
4 }
5 Person p = new Person(name:”N”, surname:”S”)
6 assert p.name == ”N”
7 assert p.getName() == ”N”
8 test.surname = ”F”
9 test.setSurname(”F”)
24. Why Groovy #3
Groovy supports Closures smartly and elegantly
A closure is an anonymous function together with a referencing
environment.
Think of closures as anonymous blocks of code that:
can accept parameters or return a value,
can be assigned to variables,
can be passed as arguments,
capture the variables of their surrounding lexical scope.
25. Example
1 //a closure assigned to a variable
2 def multiplier = { Number x, Number y −> x * y }
3 //invocation of the closure
4 assert multiplier(2, 3) == 6
5 //partial application
6 def doubler = multiplier.curry(2)
7 assert doubler(3) == 6
8 //another doubler
9 def otherDoubler = { it * 2 } //it −> the first arg
10 otherDoubler(3) == doubler(3)
11 //closure as the last argument pattern
12 void method(X x, Y y, Closure c)
13 def c = { println ’booh booh’ }
14 //invoke the method
15 method(x, y, c)
16 //alternate, more readable syntax
17 method(x, y) { println ’booh booh’ }
26. Collection Manipulation
1 //a groovy list (ArrayList behind the scenes)
2 def list = [12, 2, 34, 4, 15]
3 //Collection.collect(Closure c) − extra method available in
Groovy JDK
4 //So, given a closure
5 def inc = { it + 1 }
6 //we can invoke
7 list.collect(inc) == [13, 3, 35, 5, 16]
8 //or pass the closure code directly
9 assert list.collect{ it + 1 } == [13, 3, 35, 5, 16]
10 //some more fun
11 list.findAll{ it > 10 }.groupBy{ it % 2 == 0 ? ’even’ : ’odd’ }
== [even:[12, 34], odd:[15]]
27. Owner and delegate
1 class Test {
2 long x = 2
3 def xTimes = { l −> x * l }
4 }
5 Test test = new Test()
6 assert test.xTimes.owner == test
7 assert test.xTimes.delegate == test
8 test.xTimes(3) == 6
9 test.x = 3
10 test.xTimes(3) == 9
11 def map = [x:4]
12 assert test.xTimes.resolveStrategy == Closure.OWNER_FIRST
13 test.xTimes.resolveStrategy = Closure.DELEGATE_FIRST
14 test.xTimes.delegate = map
15 assert test.xTimes(3) == 12
31. Why Groovy #5
Groovy offers seamless integration with Java
Syntactically correct Java will work in Groovy (with some
gotchas).
You get all groovy magic by just adding a jar in the classpath.
Call Groovy from Java == call Java from Java.
Joint compilation: mix Java and Groovy.
32. Mix Java and Groovy
Fetcher.java
1 public interface Fetcher<V> {
2 V fetch();
3 }
Person.groovy
1 @Canonical class Person implements Fetcher<String>{
2 String name
3 String surname
4 @Override
5 String toString() { ”$surname, $name” }
6 @Override
7 String fetch() { toString() }
8 }
33. Mix Java and Groovy
UsingPerson.java
1 public class UsingPerson {
2 public static void main(String[] args) {
3 Person p = new Person(”Theodoros”, ”Kolokotronis”);
4 System.out.println(p.fetch());
5 }
6 }
Joint compilation
> groovyc Fetcher.java Person.groovy UsingPerson.java −j
> java −cp groovy−all.jar:. UsingPerson
> Kolokotronis, Theodoros
34. Why Groovy #6
Groovy is a Java-powered scripting language
Echo.java
1 public class Echo {
2 public static void main(String[] args) {
3 if (args != null && args.length > 0) {
4 //for Java < 8 you need a third−party library
5 System.out.println(String.join(” ”, args));
6 }
7 }
8 }
Echo.groovy (no boilerplate)
1 if (args) {
2 println args.join(’ ’)
3 }
35. Querying a MySQL database using JDBC
db.groovy
1 @GrabConfig(systemClassLoader=true)
2 @Grab(’mysql:mysql−connector−java:5.1.6’)
3 import groovy.sql.Sql
4 try {
5 def sql = Sql.newInstance(args[0], args[1], args[2], ”com.mysql
.jdbc.Driver”)
6 def query=”select count(*) as c, date(cDate) as d from table
group by d order by c”
7 sql.eachRow(query) { row −> println ”${row.c}:${row.d}” }
8 }
9 catch(e) { e.printStackTrace() }
36. Exploit the full power of Java effectively
Isn’t this Groovy or what?
> groovy db jdbc:mysql://localhost:3306/test test test123
Output
1 9427:2004−08−20
2 6615:2004−10−29
3 5498:2004−10−08
4 5103:2004−08−31
5 4864:2004−10−14
6 4675:2004−10−31
7 4583:2004−10−05
8 4570:2004−08−21
9 4339:2004−09−30
10 4235:2004−10−30
37. Why Groovy #7
Groovy is well-suited for implementing custom DSLs
Domain-Specific Languages are tailored to expressing a particular
problem.
For Example
Regular expressions: a DSL for text pattern matching.
SQL: a DSL for querying and managing relational data.
Groovy-based DSLs: builders, template engines and more.
38. FOSSCOMM 2016 Programme
The data
1 def presentations = [
2 [
3 date : ’2016−04−16’,
4 start: ’10:30’,
5 end : ’11:00’,
6 title: ’Welcome’,
7 who : [’Software Libre Society’]
8 ],
9 [
10 date : ’2016−04−16’,
11 start: ’16:00’,
12 end : ’17:00’,
13 title: ’Apache Groovy: the language and the ecosystem’,
14 who : [’Agapios Avramidis’, ’Kostas Saidis’]
15 ]
16 ]
39. FOSSCOMM 2016 Programme
Groovy MarkupTemplateEngine
1 yieldUnescaped ’<!DOCTYPE html>’
2 html(lang:’el’) {
3 head {
4 meta (’http−equiv’:’...’)
5 title (’FOSSCOMM 2016’)
6 }
7 body {
8 [’2016−04−16’, ’2016−04−17’].each { date −>
9 h1 (date)
10 list.findAll{it.date == date}.sort{it.start}.each{ p−>
11 div {
12 span (”${p.start} − ${p.end} − ”)
13 big (p.title)
14 br()
15 strong (p.who.join(’,’))
16 }
17 }
18 }
19 }
20 }
40. FOSSCOMM 2016 Programme
The generated HTML
1 <!DOCTYPE html><html lang=’el’>
2 <head>
3 <meta http−equiv=’...’/><title>FOSSCOMM 2016</title>
4 </head><body>
5 <h1>2016−04−16</h1><div>
6 <span>10:30 − 11:00 − </span><big>Welcome</big><br
/><strong>Software Libre Society</strong>
7 </div><div>
8 <span>16:00 − 17:00 − </span><big>Apache Groovy: the
language and the ecosystem</big><br/><strong>
Agapios Avramidis,Kostas Saidis</strong>
9 </div><h1>2016−04−17</h1>
10 </body>
11 </html>
41. Why Groovy #8
Groovy supports optional type checking and static compilation
In Groovy, most of the type checking is performed at runtime.
Use @TypeChecked & @CompileStatic annotations to maximize
static checks during compilation.
@TypeChecked performs static type checking, yet it
dispatches methods through the MOP (permits runtime
meta-programming).
@CompileStatic = @TypeChecked + “static” method linking (no
MOP); is the closest you can get to javac-generated bytecode
(in both behavior & performance).
42. Default type checking behavior
Example
1 class Test {
2 def s1
3 Integer s2 = 2016
4 void test() {
5 s1 = ”fosscomm”
6 assert s1.class == String.class
7 s1 = 2016
8 s1.class == Integer.class
9 s2 = ”fosscomm” //fails at runtime
10 }
11 }
12 new Test().test()
43. Enable static type checking
Example
1 import groovy.transform.TypeChecked
2 @TypeChecked class Test {
3 def s1
4 Integer s2 = 2016
5 void test() {
6 s1 = ”fosscomm”
7 assert s1.class == String.class
8 s1 = 2016
9 s1.class == Integer.class
10 s2 = ”fosscomm” //fails at compile−time
11 }
12 }
13 new Test().test()
44. Languages and Typing
A statically-typed language resolves the types of variables during
compilation you cannot change the type of a variable. Java, opt.
Groovy
A dynamically-typed language resolves the types of variables at
runtime you can change the type of a variable. Ruby, opt. Groovy
A strongly-typed language guarantees type conformance you
can’t coerce a variable to a wrong type. Java, Ruby, Groovy
A weakly-typed language has type abstractions that leak you can
screw everything up in all possible ways. C
45. Why Groovy #9
Groovy runs on Android
Java on Android is very verbose(i.e. anonymous inner classes)
Use groovy 2.4.+ (smaller core jar, grooid compiler)
Supported by Gradle (plugin groovyx.grood.groovy-android) and
Android Studio
Groovy dynamic features can be used but avoid generating
classes at runtime
Use @CompileStatic and properly configure ProGuard to be safe
47. Why Groovy #10
A mature open source technology that is here to stay!
More than a decade long history‡
.
Free and Open Source Software (Apache License v2).
Joined the ASF in 2015.
‡
Groovy was the first “second language” proposed for the JVM (back in 2004).
48. Why Groovy #10 + 1
Groovy has a vibrant community and ecosystem
Everything that runs on the JVM is part of the Groovy ecosystem.
Including all Java tools, libraries and frameworks out there!
50. Part II
The Groovy Ecosystem
Awesome tools, libraries and frameworks written in Groovy
or for Groovy§
§
We are only including projects with commit activity in 2016. Apologies if we missed some!
51. All things groovy
SysAdmin & DevOps
Building & Testing
Web & Cloud
Desktop & Mobile
Documents & Pages
Concurrency
Other
All projects are licensed under the Apache Software Foundation License v2, expect noted otherwise.
54. At a glance
sdkman
Install, switch, remote and listing candidate SDKs
Inspired by RVM and rbenv
Written in bash and requires curl and unzip
Easy to install ( curl -s http://get.sdkman.io | bash)
Command line client (CLI) and APIs
Website
57. At a glance
Concepts
Modes
Standalone and Attach through attach API of Hotspot JVM)
Embedded (web apps)
Connectors
JVM, SSH, Telnet, Web (requires WebSocket)
Features
Connect to any JVM (ssh, telnet, web)
Completion, help, pipes.
Built-in commands (jmx, jdbc, thread, memory usage)
Extensible (create new commands in java or groovy)
Authentication (simple, Jaas, key-based)
Free and Open Source Software (LGPL v2.1)
Website
59. At a glance
GroovyServ
Quick startup of Groovy scripts (groovyClient)
Utilizes a JVM process running in background (server)
If a server is not running when a client is invoked, the client
runs a server in background
Available in sdkman
Website
60. sshoogr
A DSL for working with remote SSH servers
Example
1 import static com.aestasit.infrastructure.ssh.DefaultSsh.*
2 remoteSession(’user:pass@host:port’) {
3 exec ’ls −la’
4 remoteFile(’/tmp/test.txt’).text = ’test’
5 //uploading
6 scp {
7 from { localFile ”$buildDir/test.file” }
8 into { remoteFile ’/tmp/test.file’ }
9 }
10 }
61. Groovy VFS
A DSL that wraps the Apache Commons VFS
Example
1 def vfs = new VFS()
2 //simple copy
3 vfs.cp ’ftp://foo.example/myfile’, ’sftp://bar.example/yourfile’
4 vfs {
5 // Lists all files on a remote site
6 ls (’http://first.example’) { println it.name }
7 // Streams the output
8 cat (’http://first.example/myfile’) { strm−>
9 println strm.text
10 }
11 // Create a new folder on a remote site
12 mkdir ’sftp://second.example/my/new/folder’
13 }
64. At a glance
Gradle
Combines the best of Ant, Ivy and Maven (files, dependencies,
conventions)
In a smart and extensible way (Deep API, Groovy DSL, Plugins)
Offering clean builds that are easy to read and maintain
Polyglot (not only Java)
Multi-project builds
Incremental and parallel execution
Backed by Gradle Inc
Website
65. Example build script
build.gradle
1 apply plugin: ”java”
2 //Introduces a set of Maven−style conventions
3 //(tasks, source locations, dependency configurations, etc)
4 group = ”org.foo.something”
5 version = ”1.0−SNAPSHOT”
6 repositories {
7 //resolve all external dependencies via Maven central
8 mavenCentral()
9 }
10 dependencies {
11 //each name (compile, testCompile, etc) refers to
12 //a configuration introduced by the java plugin
13 compile ”commons−io:commons−io:2.4”
14 testCompile ”junit:junit:4.11”
15 runtime files(”lib/foo.jar”, ”lib/bar.jar”)
16 }
67. At a glance
Spock
Tool for performing unit/integration/functional tests for Java &
Groovy software.
Combines JUnit, Mockito and JBehave (units, mocks and BDD)
using a Groovy DSL.
Well-structured, given-then-when/setup-expect-where
specifications.
That read like plain English (and generate readable reports, too).
Clear insights of what went wrong.
Parameterized tests, data-driven specifications.
Website
68. Example spock spec
DataDrivenSpec
1 class DataDrivenSpec extends Specification {
2 def ”maximum of two numbers”() {
3 expect:
4 Math.max(a, b) == c
5 where:
6 a << [3, 5, 9]
7 b << [7, 4, 9]
8 c << [7, 5, 9]
9 }
10 def ”minimum of #a and #b is #c”() {
11 expect:
12 Math.min(a, b) == c
13 where:
14 a | b || c
15 3 | 7 || 3
16 5 | 4 || 4
17 9 | 9 || 9
18 }
19 }
70. At a glance
Geb
Tool for functional/web/acceptance testing (integration with
Spock, JUnit, TestNG).
Also, can be used for scripting, scraping and general browser
automation.
Build on top of WebDriver library (Selinium 2.0)
Provides a content definition DSL (jQuery-like)
Website
73. At a glance
Betamax
Mock HTTP resources such as Web services or REST APIs.
Inspired by Ruby’s VCR.
Intercepts HTTP connections, stores their responses to “tapes”,
and replays previously recorded responses from the tape.
Tapes are stored to disk as YAML files. Different tests can have
different tapes.
Works well with Geb, JUnit and Spock. One liner to add it to
Gradle.
Website
74. Example
A Spock spec with Betamax
1 class TwitterServiceSpec {
2 @Rule Recorder recorder = new Recorder()
3 def twitterService = new TwitterService()
4 @Betamax(tape=”twitter”)
5 def ”searches tweets ok”() {
6 when:
7 def tweets = twitterService.search(”#hashtag”)
8 then:
9 tweets.every{ it.text ~= /#hashtag/ }
10 }
11 }
76. At a glance
Codenarc
Analyzes and reports code for defects and inconsistencies
Reporting (HTML, XML)
Contains a predefined set of rules (348)
Provides a framework for creating new rules
Integration with other tools (Gradle, Maven, Grails, Sonar,
Jenkins, Grails, Griffon)
Website
79. At a glance
Lazybones
Project creation tool that helps you bootstrap a project from a
template.
Lazybones templates are like Maven archetypes or Yeoman
generators.
Project templates can incorporate sub-templates.
Simple and effective.
Available in sdkman.
Website
80. Example
Install Lazybones
sdk install lazybones
Use Lazybones to create a project
lazybones create <template name> [template version] <target
directory> [options]
lazybones create java−app my−app −Ppackage=org.foo.bar −−with
−git
lazybones generate controller
82. Mainly Java Projects
Spring IO
The most widely used
Java server-side
framework.
Backed by Pivotal.
Spring Boot supports
Groovy scripts.
Vert.x
The polyglot toolkit for
reactive applications
on the JVM.
Backed by the Eclipse
Foundation.
Full support for Groovy.
ElasticSearch
The Java distributed
cluster for real-time
search.
Backed by Elastic.
Supports Groovy
server-side scripts and a
Groovy client.
84. At a glance
Grails
Convention over configuration, app profiles, reasonable
defaults, opinionated APIs, DSLs and more.
Inspired by Ruby on Rails.
Wraps Spring MVC and offers a GORM supporting Hibernate,
MongoDB, Neo4j, Cassandra & Redis.
Over a 100 plugins.
Available in sdkman.
Website
85. Example
Hello world Web app with Grails
grails create−app helloworld
cd helloworld
grails create−controller hello
1 package helloworld
2 class HelloController {
3 def index() {
4 render ”Hello World!”
5 }
6 }
grails run−app
87. At a glance
Ratpack
A set of libraries that facilitate fast, efficient, scalable and
evolvable HTTP apps.
Flexible and unopinionated.
Inspired by Sinatra, built on Netty networking engine.
Asynchronous, non-blocking, event-driven architecture (like
node.js).
Offers lazybones templates.
Website
88. Example
Hello world Web app with Ratpack
1 @Grapes([
2 @Grab(’io.ratpack:ratpack−groovy:1.2.0’),
3 @Grab(’org.slf4j:slf4j−simple:1.7.12’)
4 ])
5 import static ratpack.groovy.Groovy.ratpack
6 ratpack {
7 handlers {
8 get {
9 render ”Hello World!”
10 }
11 get(”:name”) {
12 render ”Hello $pathTokens.name!”
13 }
14 }
15 }
90. At a glance
Glide
Lets you develop and deploy applications to Google App Engine
Java
Best suited for small-medium complexity apps
Provides a simple Webb App Structure
Has almost zero configuration
Supports hot reloading
Uses Gaelyk
Available in sdkman
Website
93. At a glance
Griffon
Inspired by Grails
Convention over Configuration, Don’t Repeat Yourself (DRY), MVC
Testing supported out of the box
Swing and JavaFX UI toolkits
Extensible via plugins
Website
griffon create−app my−app
95. At a glance
GroovyFX
Aims to simplify the development of Java FX applications
Relies on groovy’s DSL features and AST transformations to
reduce boilerplate.
Provides a SceneGraphBuilder, which supports for all JavaFX
components
Each class in JavaFX has a corresponding GroovyFX node (i.e.
Scene class will be scene node)
Website
98. At a glance
SwissKnife
Based on ButterKnife and AndroidAnnotations
Relies on groovy AST transformations
Inject resources
Inject views dynamically
Add callback methods to actions
Execute in the UI thread or the background
Website
102. At a glance
Grain
Supports compression and minification for sources
Has built-in SASS/SCSS support
Supports Markdown, reStructuredText and AsciiDoctor
Each static resource is represented as a Groovy map.
Resources can be processed with groovy code
(SiteConfig.groovy)
Website
103. Example
Resource mapper closure:Executed upon change
1 resource_mapper = { resources −>
2 resources.collect { Map resource −>
3 if (resource.location =~//blog/.*/) {
4 // Select all the resources which
5 // contain files placed under /blog dir
6 // Rewrite url for blog posts
7 def unParsedDate = resource.date
8 def date = Date.parse(site.datetime_format, resource.date)
9 .format(’yyyy/MM/dd/’)
10 def title = resource.title.toLowerCase()
11 .replaceAll(”s+”,”−”)
12 resource + [url: ”/blog/$date$title/”]
13 } else {
14 resource
15 }
16 }
17 }
104. Groovy Document Builder
A DSL for creating Word & PDF documents
Example
1 @Grab(’com.craigburke.document:pdf:0.4.14’)
2 @Grab(’com.craigburke.document:word:0.4.14’)
3 import com.craigburke.document.builder.PdfDocumentBuilder
4 import com.craigburke.document.builder.WordDocumentBuilder
5 def word = new WordDocumentBuilder(new File(’example.docx’))
6 def pdf = new PdfDocumentBuilder(new File(’example.pdf’))
7 word.create {
8 document {
9 paragraph ’Hello World (Word)’
10 }
11 }
12 pdf.create {
13 document {
14 paragraph ’Hello World (PDF)’
15 }
16 }
107. At a glance
RxGroovy
ReactivX: APIs for asynchronous programming with observable
streams (aka ReactiveExtensions –Rx).
RxGroovy is the Groovy adapter of RxJava.
ReactiveX is a combination of the best ideas from the Observer
pattern, the Iterator pattern, and functional programming.
Website
110. At a glance
GPars
Offers high-level concurrency and parallelism while leveraging
the multi-core hardware.
Map/Reduce
Fork/Join
Actors
Dataflow
Software Transactional Memory
And more..
Website
112. At a glance
Nextflow
Polyglot dataflows on Linux.
Nextflow scripts are defined by composing many different
processes.
Each process can be written in any scripting language
supported by Linux.
Coordinate and synchronize the processes execution by simply
specifying their inputs and outputs.
Requires Java 7, easy to install (curl -fsSL get.nextflow.io |
bash).
Based on GPars.
Website
116. Conclusion
A language that doesn’t affect the way
you think about programming is not
worth knowing.
Alan Perlis (1922 - 1990)
ACM Turing Award, 1966
117. Apache Groovy
The best language for diving into dynamic features
for Java hackers
The best language for diving into the Java platform
for Javascripters, Rubyists and Pythonistas¶
Perl hackers are diving into Perl 6, aren’t they?
¶
after Rhino/Nashorn, JRuby and Jython respectively