SlideShare a Scribd company logo
1 of 151
Download to read offline
Dr Paul King
Groovy Lead for Object Computing Inc.
@paulk_asert
http:/slideshare.net/paulk_asert/awesome-groovy
https://github.com/paulk-asert/awesome-groovy
Apache Groovy:
The Awesome Parts
FRIEND OF GROOVY
Part 1: Introducing Groovy?
What is Groovy?
4
Groovy = Java – boiler plate code
+ closures (1st class FP)
+ extensible type system
+ runtime & compile-time metaprogramming
+ flexible language grammar (DSLs)
+ scripting
+ GDK library
“Groovy is like a super version of Java.
It leverages Java features but adds productivity features
and provides great flexibility and extensibility.”
Why Groovy?
Java
Why Groovy?
Too verbose
Support
functional
programming
Better
concurrency
Evolves
too slowly
I need
feature
XXX
Too complex
for some
situations
More
flexibility
Java
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Good IDE
support
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Good IDE
support
Custom
features
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Support
concurrency
Good IDE
support
Custom
features
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Support
functional
style
Support
concurrency
Good IDE
support
Custom
features
Java
integration
Java code for list manipulation
import java.util.List;
import java.util.ArrayList;
class Main {
private List keepShorterThan(List strings, int length) {
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) {
String s = (String) strings.get(i);
if (s.length() < length) {
result.add(s);
}
}
return result;
}
public static void main(String[] args) {
List names = new ArrayList();
names.add("Ted"); names.add("Fred");
names.add("Jed"); names.add("Ned");
System.out.println(names);
Main m = new Main();
List shortNames = m.keepShorterThan(names, 4);
System.out.println(shortNames.size());
for (int i = 0; i < shortNames.size(); i++) {
String s = (String) shortNames.get(i);
System.out.println(s);
}
}
}
Groovy code for list manipulation
import java.util.List;
import java.util.ArrayList;
class Main {
private List keepShorterThan(List strings, int length) {
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) {
String s = (String) strings.get(i);
if (s.length() < length) {
result.add(s);
}
}
return result;
}
public static void main(String[] args) {
List names = new ArrayList();
names.add("Ted"); names.add("Fred");
names.add("Jed"); names.add("Ned");
System.out.println(names);
Main m = new Main();
List shortNames = m.keepShorterThan(names, 4);
System.out.println(shortNames.size());
for (int i = 0; i < shortNames.size(); i++) {
String s = (String) shortNames.get(i);
System.out.println(s);
}
}
}
Rename
Main.java
to
Main.groovy
Some Java Boilerplate identified
import java.util.List;
import java.util.ArrayList;
class Main {
private List keepShorterThan(List strings, int length) {
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) {
String s = (String) strings.get(i);
if (s.length() < length) {
result.add(s);
}
}
return result;
}
public static void main(String[] args) {
List names = new ArrayList();
names.add("Ted"); names.add("Fred");
names.add("Jed"); names.add("Ned");
System.out.println(names);
Main m = new Main();
List shortNames = m.keepShorterThan(names, 4);
System.out.println(shortNames.size());
for (int i = 0; i < shortNames.size(); i++) {
String s = (String) shortNames.get(i);
System.out.println(s);
}
}
}
Are the semicolons
needed?
And shouldn’t
we us more
modern list
notation?
Why not
import common
libraries?
Do we need
the static types?
Must we always
have a main
method and
class definition?
How about
improved
consistency?
Java Boilerplate removed
def keepShorterThan(strings, length) {
def result = new ArrayList()
for (s in strings) {
if (s.size() < length) {
result.add(s)
}
}
return result
}
names = new ArrayList()
names.add("Ted"); names.add("Fred")
names.add("Jed"); names.add("Ned")
System.out.println(names)
shortNames = keepShorterThan(names, 4)
System.out.println(shortNames.size())
for (s in shortNames) {
System.out.println(s)
}
More Java Boilerplate identified
def keepShorterThan(strings, length) {
def result = new ArrayList()
for (s in strings) {
if (s.size() < length) {
result.add(s)
}
}
return result
}
names = new ArrayList()
names.add("Ted"); names.add("Fred")
names.add("Jed"); names.add("Ned")
System.out.println(names)
shortNames = keepShorterThan(names, 4)
System.out.println(shortNames.size())
for (s in shortNames) {
System.out.println(s)
}
Shouldn’t we
have special
notation for lists?
And special
facilities for
list processing?
Is ‘return’
needed at end?
Is the method
now needed?
Simplify common
methods?
Remove unambiguous
brackets?
Boilerplate removed = nicer Groovy version
names = ["Ted", "Fred", "Jed", "Ned"]
println names
shortNames = names.findAll{ it.size() < 4 }
println shortNames.size()
shortNames.each{ println it }
["Ted", "Fred", "Jed", "Ned"]
3
Ted
Jed
Ned
Output:
Or Groovy DSL version if required
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
// plus a DSL implementation
Or Groovy DSL version if required
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
names = []
def of, having, less
def given(_the) { [names:{ Object[] ns -> names.addAll(ns)
[and: { n -> names += n }] }] }
def the = [
number: { _of -> [names: { _having -> [size: { _less -> [than: { size ->
println names.findAll{ it.size() < size }.size() }]}] }] },
names: { _having -> [size: { _less -> [than: { size ->
names.findAll{ it.size() < size }.each{ println it } }]}] }
]
def all = [the: { println it }]
def display(arg) { arg }
Or Groovy DSL version if required
• Or use GDSL (IntelliJ IDEA) or DSLD (Eclipse)
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
Or typed Groovy DSL version if required
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
…
enum The { the }
enum Having { having }
enum Of { of }
…
class DisplayThe {
DisplayTheNamesHaving names(Having having) {
new DisplayTheNamesHaving()
}
DisplayTheNumberOf number(Of of) {
new DisplayTheNumberOf()
}
}
…
// plus 50 lines
Or typed Groovy DSL version if required
Groovy DSL being debugged
Or typed Groovy DSL version if required
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
Or typed Groovy DSL version if required
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}

@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
Or typed Groovy DSL version if required
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", “Mary", "Jed" and “Pete"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}
Or typed Groovy DSL version if required
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", “Mary", "Jed" and “Pete"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}
Or typed Groovy DSL version if required

What style of language is Groovy?
Groovy Style
• Imperative/OO but somewhat
paradigm agnostic
•Dynamic, optionally static (gradual
extensible typing)
• Extensible language features
through metaprogramming
Part 2: What makes Groovy Awesome?
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain specific
language (DSL) support
• Ecosystem
• Community/Team
Awesome
What makes Groovy Awesome?
• Java integration
• Builds up on Java
• Tight integration
• Polyglot friendly
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Java Integration
• Groovy is Java’s friend
Java
Groovy
Java Integration
• Standing on the shoulders of Giants
• Some limitations inherited but much
gained through new releases of Java
• Rock solid foundation
• Can ease migration to new versions
of Java
Java
Groovy
Java Integration
• Seamless integration
• IDEs provide cross-language compile,
navigation, and refactoring
• Arbitrarily mix source language
• Drop-in replace
any class
• Overloaded methods
• Syntax alignment
• Shared data types
Java
Groovy
Java Integration
• Seamless integration
• IDEs provide cross-language compile,
navigation, and refactoring
• Arbitrarily mix source language
• Drop-in replace
any class
• Overloaded methods
• Syntax alignment
• Shared data types
Java
Groovy
Java Integration
• Polyglot friendly
• Typically integrates well with other
languages which integrate with Java
• JRuby
• Jython
• Scala
• Frege
• Clojure
• R through Renjin
• JavaScript
(Rhino/Nashorn)
Java Integration
• Polyglot friendly
• JSR-223 scripting
to talk to JavaScript
import javax.script.ScriptEngineManager
def mgr = new ScriptEngineManager()
def engine = mgr.getEngineByName('nashorn')
assert engine.eval('''
function factorial(n) {
if (n == 0) { return 1; }
return n * factorial(n - 1);
}
factorial(4)
''') == 24.0
Java
GroovyJavaScript
Java Integration
• Polyglot friendly: R integration
@GrabResolver('https://nexus.bedatadriven.com/content/groups/public')
@Grab('org.renjin:renjin-script-engine:0.7.0-RC7')
import javax.script.ScriptEngineManager
def mgr = new ScriptEngineManager()
def engine = mgr.getEngineByName('Renjin')
engine.with {
eval '''
factorial <- function(x) {
y <- 1
for (i in 1:x) { y <- y * i }
return(y)
}
'''
assert eval('factorial(4)')[0] == 24
}
Java
GroovyR
Grooscript
@Grab('org.grooscript:grooscript:1.2.0')
import org.grooscript.GrooScript
import javax.script.ScriptEngineManager
def groojs = GrooScript.convert '''
def sayHello = { println "Hello ${it}!" }
['Groovy','JavaScript','GrooScript'].each sayHello''',
[initialText: 'var console = { log: print }',
addGsLib: 'grooscript.min']
new ScriptEngineManager().getEngineByName("nashorn").eval(groojs)
Hello Groovy!
Hello JavaScript!
Hello GrooScript!
Jorge Franco, grooscript.org
Convert Groovy subset to JavaScript
Support: Gradle, Grails, NPM
Demos: react.js, node.js, Pollock
Converts: Classes, closures, Date
primitives, ranges, String/GString
Special: builder, templates, gQuery
What makes Groovy Awesome?
• Java integration
• Builds up on Java
• Tight integration
• Polyglot friendly
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Awesome
• Friend of Java
• Integration
• Good JVM Citizen
What makes Groovy Awesome?
• Java integration
• Scripting support
• Simplified scripting
• Separation of concerns
• Security sandbox
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Awesome
Scripting
• Terse format
• Isolation
• Domain-Specific
Languages (DSLs)
• Security
• Flexibility
Scripting
• Leave out surrounding class
• Entire source file:
public class Script {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
println "Hello world"
Scripting
• Various approaches supported
• GroovyShell
• GroovyScriptEngine
• GroovyClassLoader
• Spring
• JSR-223
• Base scripts
• allows predefined methods
• Binding
• allows predefined variables
• Customizers
• add imports, static imports
• lock down AST to a subset
• apply any AST transform transparently
Scripting
Scripting
Scripting
Scripting
class Robot {
void move(dir) {
println "robot moved $dir"
}
}
def robot = new Robot()
Scripting
import static Direction.*
enum Direction {
left, right, forward, backward
}
class Robot {
void move(Direction dir) {
println "robot moved $dir"
}
}
def robot = new Robot()
robot.move left
Scripting
move left
def robot = new Robot()
def binding = new Binding(
robot: robot,
move: robot.&move,
*: Direction.values().collectEntries {
[(it.name()): it]
}
)
def shell = new GroovyShell(binding)
shell.evaluate new File(args[0]).text
Scripting
move left
def robot = new Robot()
def binding = new Binding(/* ... */)
def imports = new ImportCustomizer().addStaticStars('java.lang.Math')
def timeout = new ASTTransformationCustomizer(value: 2, TimedInterrupt)
def secure = new SecureASTCustomizer().with {
closuresAllowed = false
importsWhitelist = []
tokensWhitelist = [ PLUS, MINUS, MULTIPLY, DIVIDE, /*...*/ ]
//...
}
def sysExit = new CompilationCustomizer(CANONICALIZATION) {
void call(SourceUnit src, GeneratorContext ctxt, ClassNode cn) {
new ClassCodeVisitorSupport() {
void visitMethodCallExpression(MethodCallExpression call) {
// check for System.exit()
}
// ...
}.visitClass(cn)
}
}
def config = new CompilerConfiguration()
config.addCompilationCustomizers(imports, timeout, secure, sysExit)
def shell = new GroovyShell(binding, config)
Scripting
move left
move forward at 3.km/h
More
examples
later
What makes Groovy Awesome?
• Java integration
• Scripting support
• Simplified scripting
• Separation of concerns
• Security sandbox
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Awesome
• Simpler scripting
• Separation of concerns
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Object-oriented
• Functional, Closures
• Logic/Dataflow programming
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Multiparadigm
• Imperative roots from Java
• OO abstractions: classes,
interfaces, inheritance
• Properties
• Traits
• First class functional support via closures
• External libraries for advanced features
• Other paradigms via libraries
• Logic, dataflow, reactive
Awesome
Multiparadigm
Imperative/OO
Logic programming
Functional
Rich OO features
• Classes (and scripts, GroovyBeans)
• Fields (and properties)
• Methods, constructors, multi-methods, named and default parameters
• Inheritance (behavior and implementation), interfaces, traits
• Type aliases
• Packages
• Special accessor notation, spread operators, GPath, safe navigation
Traits
/**
* Things that hop
* @author Grace
*/
trait Hopper {
String jump() { "I'm jumping!" }
}
class Kangaroo implements Hopper {}
def skip = new Kangaroo()
assert skip.jump() == "I'm jumping!"
Rich functional features
• Closures
• First-class functions
• Higher-order functions
• Map, reduce, filter
• Mutable & immutable data
• Recursion
• Lazy & eager evaluation
• Advanced FP techniques
• Memoization, Trampolines, Composition, Curry
• Concurrency
map/filter/reduce
@Canonical
class Person {
String name
int age
}
def people = [
new Person('Peter', 45),
new Person('Paul', 35),
new Person('Mary', 25)
]
assert people
.findAll{ it.age < 40 }
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
map/filter/reduce (+ functional style)
@Canonical
class Person {
String name
int age
}
def people = [
new Person('Peter', 45),
new Person('Paul', 35),
new Person('Mary', 25)
]
assert people
.findAll{ it.age < 40 }
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
def young = { person, threshold ->
person.age < threshold
}.rcurry(40).memoize()
assert people
.findAll(young)
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
map/filter/reduce (+ with streams)
@Canonical
class Person {
String name
int age
}
def people = [
new Person('Peter', 45),
new Person('Paul', 35),
new Person('Mary', 25)
]
assert people
.findAll{ it.age < 40 }
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
// requires JRE 8
def commaSep = Collectors.joining(", ")
assert people.stream()
.filter{ it.age < 40 }
.map{ it.name.toUpperCase() }
.sorted()
.collect(commaSep) == 'MARY, PAUL'
Logic/Constraint programming
• Logic programming
• Declarative style
• Logic clauses for example Prolog
• Constraint programming
• Declarative style similar to logic programming but contain constraints which
must be satisfied
• Relations between variables are stated as constraints
• Not a step or sequence of steps to execute, but rather the properties of a
solution to be found
Logic programming example
cranes have 2 legs
tortoises have 4 legs
there are 7 animals
there are 20 legs
How many of each animal?
Constraint programming example
@Grab('org.choco-solver:choco-solver:4.0.4')
import org.chocosolver.solver.Model
def m = new Model()
def totalAnimals = 7
def totalLegs = 20
def numCranes = m.intVar('Cranes', 0, totalAnimals, true)
def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true)
def numCraneLegs = m.intScaleView(numCranes, 2)
def numTortoiseLegs = m.intScaleView(numTortoises, 4)
m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post()
m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post()
if (m.solver.solve())
println "$numCranesn$numTortoises"
else
println "No Solutions" Cranes = 4
Tortoises = 3
ChocoCraneTortoise.groovy
See also: JSR-331 Constraint Programming API
Dataflow programming
• Declarative style
• Emphasizes the movement of data
• models programs as a series of connected tasks
• A task has explicitly defined inputs and outputs
• runs as soon as all of its inputs become available
• Inherently parallel
GPars
• Library classes and DSL allowing
you to handle tasks concurrently:
• Data Parallelism map, filter, reduce functionality
in parallel with parallel array support
• Asynchronous functions extend the Java executor
services to enable multi-threaded closure processing
• Dataflow Concurrency supports natural
shared-memory concurrency model, using
single-assignment variables
• Actors provide Erlang/Scala-like actors
including "remote" actors on other machines
• Safe Agents provide a non-blocking mt-safe
reference to mutable state; like "agents" in Clojure
72
Awesome
Concurrency challenge
• We can analyse the example’s task graph:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
def a = 5
def b = f1(a)
def c = f2(a)
def d = f3(c)
def f = f4(b, d)
assert f == 10
Concurrency challenge
• We can analyse the example’s task graph:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
def a = 5
def b = f1(a)
def c = f2(a)
def d = f3(c)
def f = f4(b, d)
assert f == 10
f2
f3
f1
f4
aa
b
c
d
f
Concurrency challenge
• Manually using asynchronous functions:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
import static groovyx.gpars.GParsPool.withPool
withPool(2) {
def a = 5
def futureB = f1.callAsync(a)
def c = f2(a)
def d = f3(c)
def f = f4(futureB.get(), d)
assert f == 10
}
f2
f3
f1
f4
aa
futureB
c
d
f
Concurrency challenge
• And with GPars Dataflows:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
import groovyx.gpars.dataflow.Dataflows
import static groovyx.gpars.dataflow.Dataflow.task
new Dataflows().with {
task { a = 5 }
task { b = f1(a) }
task { c = f2(a) }
task { d = f3(c) }
task { f = f4(b, d) }
assert f == 10
}
f2
f3
f1
f4
aa
b
c
d
f
Concurrency challenge
• And with GPars Dataflows:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
import groovyx.gpars.dataflow.Dataflows
import static groovyx.gpars.dataflow.Dataflow.task
new Dataflows().with {
task { f = f4(b, d) }
task { d = f3(c) }
task { c = f2(a) }
task { b = f1(a) }
task { a = 5 }
assert f == 10
}
f2
f3
f1
f4
aa
b
c
d
f
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Object-oriented
• Functional, Closures
• Logic/dataflow programming
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
• Ability to use imperative
when needed for speed
• Numerous declarative
approaches available
when it makes sense
Awesome
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Dynamic strong typing
• Static type checking
• Extensible
• Type inference
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Gradual typing
• Dynamic by default
• Gradual typing
• Static type checking
• Extensible type system
Awesome
Dynamic vs static
82
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
Dynamic vs static
83
Gradual
Type-time?
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
Dynamic vs static
84
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
Dynamic vs static
85
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
Duck-typing
Dynamic vs static
86
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
@TypeChecked
def myMethod() {
def myPets = ['Lassie', 'Skip']
List yourPets = ['Lassie', 'Skip']
}
shouldFail(CompilationFailedException) {
assertScript '''
@groovy.transform.TypeChecked
def yourMethod() {
List ourPets = new Date()
}
'''
}
Dynamic vs static
87
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
@TypeChecked
def myMethod() {
def myPets = ['Lassie', 'Skip']
List yourPets = ['Lassie', 'Skip']
}
shouldFail(CompilationFailedException) {
assertScript '''
@groovy.transform.TypeChecked
def yourMethod() {
List ourPets = new Date()
}
'''
}
Extensible
Inference
Extensible type checking
import groovy.transform.TypeChecked
import experimental.SprintfTypeChecker
@TypeChecked(extensions=SprintfTypeChecker)
void main() {
sprintf('%s will turn %d on %tF', 'John', new Date(), 21)
}
[Static type checking] - Parameter types didn't match types
expected from the format String:
For placeholder 2 [%d] expected 'int' but was 'java.util.Date'
For placeholder 3 [%tF] expected 'java.util.Date' but was 'int'
sprintf has an Object varargs parameter, hence not normally
amenable to further static checking but for constant Strings
we can do better using a custom type checking plugin.
Extensible type checking
import groovy.sql.Sql
import groovy.transform.TypeChecked
@TypeChecked(extensions='SQLExtension.groovy')
findAthletes(Sql sql) {
sql.eachRow('select * frm Athlete') { row -> println row }
}
SqlTC.groovy: 7: [Static type checking] - SQL query is not
valid: net.sf.jsqlparser.JSQLParserException
@ line 6, column 15.
sql.eachRow('select * frm Athlete') { row -> println row }
^
1 error
Static compilation
import groovy.transform.*
class Actor {
String firstName, lastName
@CompileStatic
String getFullName() { "$firstName $lastName" }
void makePeace() {
new AntBuilder().echo('Peace was never an option')
}
}
def magneto = new Actor(firstName: 'Ian', lastName: 'McKellen')
assert magneto.fullName == 'Ian McKellen'
magneto.makePeace()
Static compilation speed
0
5
10
15
20
25
30
Fibonacci micro-benchmark
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Dynamic strong typing
• Static type checking
• Extensible
• Type inference
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
• Maximise duck-typing
• Minimise noise
• yet type inference
• Flexibility at runtime
• As strict as you want
when needed
• Fast when needed
Awesome
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Runtime
• Compile-time
• Macros
• Domain Specific Language support
• Ecosystem
• Community/Team
Runtime metaprogramming
• Add instance & static methods, constructors,
properties at runtime
• Intercept method/property access
• Catch missing methods, properties
• Used for dynamic builders, aspect-oriented
programming, test stubs, mocks & dummies
Awesome*
* Individual levels of awesomeness may vary
Runtime metaprogramming
• Adding methods at runtime
assert 'Hello'.reverse() == 'olleH'
String.metaClass.swapCase = { delegate.collect{
it in 'A'..'Z' ? it.toLowerCase() : it.toUpperCase()
}.join() }
assert 'Hello'.swapCase() == 'hELLO'
Runtime metaprogramming
• Intercepting methods
class Foo {
def one() { println "Called one()" }
def methodMissing(String name, params) {
println "Attempted $name($params)"
}
}
def f = new Foo()
f.one()
f.two()
f.three('Some Arg')
Called one()
Attempted two([])
Attempted three([Some Arg])
XML Parsing/GPath expressions
def xml = '''
<hosts>
<host name='MyHost'>
<service name='MyMicroService'/>
<service name='MyNanoService'/>
</host>
</hosts>
'''
def hosts = new XmlParser().parseText(xml)
assert hosts.host.service[0].@name=='MyMicroService'
def xml = '''
<hosts>
<host name='MyHost'>
<service name='MyMicroService'/>
<service name='MyNanoService'/>
</host>
</hosts>
'''
def hosts = new XmlParser().parseText(xml)
assert hosts.host.service[0].@name=='MyMicroService'
XML Parsing/GPath expressions
Compile-time metaprogramming
• Gives you the ability to change the language by augmenting the
compilation process
Awesome
Compile-time metaprogramming
• Modify the program
at compile-time
@ToString
class Person {
String first, last
}
println new Person(first: 'John',
last: 'Smith')
// => Person(John, Smith)
Compile-time metaprogramming
• Modify the program
at compile-time
class Person {
String first, last
String toString() {
"Person($first, $last)"
}
}
println new Person(first: 'John',
last: 'Smith')
// => Person(John, Smith)
Parsing Summary
public run()
...
L1
ALOAD 1
LDC 1
AALOAD
ALOAD 0
LDC "Howdy Y'all"
INVOKEINTERFACE callCurrent()
ARETURN
...
println "Howdy Y'all"
BlockStatement
-> ReturnStatement
-> MethodCallExpression
-> VariableExpression("this")
-> ConstantExpression("println")
-> ArgumentListExpression
-> ConstantExpression("Howdy Y'all")
MyScript.groovy
> groovy MyScript.groovy
> groovyc MyScript.groovy
> groovysh
> groovyConsole
• 9 phase compiler
– Early stages: read source code
and convert into a sparse syntax
tree
– Middle stages: iteratively build up
a more dense and information rich
version of the syntax tree
– Later stages: check the tree and
convert it into byte code/class files
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
Parsing Summary
Parsing - Early Stages
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
@ToString
class Greeter {
String message = "Howdy Y'all"
void greet() {
println message
}
}
ClassNode: Greeter
MethodNode: greet
Property: message
type: unresolved(String)
AnnotationNode:
ToString
type:
unresolved(ToString)
methods:
properties:
annotations:
BlockStatement
MethodCall:
this.println(message)
Parsing - Middle Stages
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
ClassNode: Greeter
MethodNode: greet
FieldNode: message
type: resolved(String)
methods:
fields:
constructors:
ConstructorNode
MethodNode:
getMessageMethodNode:
setMessageMethodNode: toString
MethodNode:
getMetaClass…
Parsing - Final Stages
106
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
public greet()V
...
L1
...
ALOAD 0
GETFIELD Greeter.message
INVOKEINTERFACE callCurrent()
POP
...
Immutable Classes
• Some Rules
• Don’t provide mutators
• Ensure that no methods can
be overridden
o Easiest to make the class final
o Or use static factories & non-public
constructors
• Make all fields final
• Make all fields private
o Avoid even public immutable constants
• Ensure exclusive access to any mutable components
o Don’t leak internal references
o Defensive copying in and out
• Optionally provide equals and hashCode methods
• Optionally provide toString method
@Immutable...
• Java Immutable Class
• As per Joshua Bloch Effective Java
public final class Person {
private final String first;
private final String last;
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((first == null)
? 0 : first.hashCode());
result = prime * result + ((last == null)
? 0 : last.hashCode());
return result;
}
public Person(String first, String last) {
this.first = first;
this.last = last;
}
// ...
// ...
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
if (last == null) {
if (other.last != null)
return false;
} else if (!last.equals(other.last))
return false;
return true;
}
@Override
public String toString() {
return "Person(first:" + first
+ ", last:" + last + ")";
}
}
...@Immutable...
public final class Person {
private final String first;
private final String last;
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((first == null)
? 0 : first.hashCode());
result = prime * result + ((last == null)
? 0 : last.hashCode());
return result;
}
public Person(String first, String last) {
this.first = first;
this.last = last;
}
// ...
// ...
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
if (last == null) {
if (other.last != null)
return false;
} else if (!last.equals(other.last))
return false;
return true;
}
@Override
public String toString() {
return "Person(first:" + first
+ ", last:" + last + ")";
}
}
boilerplate• Java Immutable Class
• As per Joshua Bloch Effective Java
...@Immutable
@Immutable class Person {
String first, last
}
Awesome
With Macros (Groovy 2.5+)
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.expr.*
def ast = new ReturnStatement(
new ConstructorCallExpression(
ClassHelper.make(Date),
ArgumentListExpression.EMPTY_ARGUMENTS
)
)
def ast = macro {
return new Date()
}
With Macros (Groovy 2.5+)
Awesome
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.expr.*
def ast = new ReturnStatement(
new ConstructorCallExpression(
ClassHelper.make(Date),
ArgumentListExpression.EMPTY_ARGUMENTS
)
)
def ast = macro {
return new Date()
}
With Macros (Groovy 2.5+)
• Variations:
• Expressions, Statements, Classes
• Supports variable substitution,
specifying compilation phase
def ast = macro {
return new Date()
}
With Macros (Groovy 2.5+)
• AST Matching:
• Selective transformations, filtering, testing
• Supports placeholders
Expression transform(Expression exp) {
Expression ref = macro { 1 + 1 }
if (ASTMatcher.matches(ref, exp)) {
return macro { 2 }
}
return super.transform(exp)
}
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
def getName(Z z) {
z.y.list[0].name
}
• nullSafe
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
z.y.list[0].name
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
z.y.list[0].name
}
Prone to NPE
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
Macro method examples
• nullSafe
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
def result = null
if (z != null && z.y != null &&
z.y.list != null && z.y.list[0] != null) {
result = z.y.list[0].name
}
result
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
def result = null
if (z != null && z.y != null &&
z.y.list != null && z.y.list[0] != null) {
result = z.y.list[0].name
}
result
}
Verbose
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
Macro method examples
def getName(Z z) {
z?.y?.list?[0]?.name
}
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
Macro method examples
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
def getName(Z z) {
nullSafe(z.y.list[0].name)
}
Macro method examples
@Macro
static Expression nullSafe(MacroContext macroContext, Expression expression) {
if (expression instanceof PropertyExpression) {
// exp.prop -> exp?.prop …
} else if (expression instanceof MethodCallExpression) {
// exp.method() -> exp?.method() …
}
return expression
}
• nullSafe
def getName(Z z) {
nullSafe(z.y.list[0].name)
}
Macro method examples
def fact(num) {
return match(num) {
when String then fact(num.toInteger())
when(0 | 1) then 1
when 2 then 2
orElse num * fact(num - 1)
}
}
assert fact("5") == 120
See: https://github.com/touchez-du-bois/akatsuki
Macro method examples
• Spock inspired
@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
import spock.lang.Specification
class MathSpec extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 3 | 3
7 | 4 | 7
0 | 0 | 0
}
}
Macro method examples
See: https://github.com/touchez-du-bois/akatsuki
doWithData {
dowith:
assert a + b == c
where:
a | b || c
1 | 2 || 3
4 | 5 || 9
7 | 8 || 15
}
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Runtime
• Compile-time
• Macros
• Domain Specific Language support
• Ecosystem
• Community/Team
• Ability to change the language
at runtime
• Ability to change the language
during the compilation process
• Macros provide a
homogeneous form
for writing AST
transformations
Awesome
Part 2: What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
 Command chains
• Cranes and tortoises revisited
• Ecosystem
• Community/Team
Command Chains
• Ability to chain method calls without parentheses and dots
Awesome
Command Chains
• Ability to chain method calls without parentheses and dots
move forward at 3.km/h
Command Chains
• Ability to chain method calls without parentheses and dots
• Equivalent to:
move forward at 3.km/h
move(forward).at(3.getKm().div(h))
Command chains in DSLs
Number.metaClass.getShares = { delegate }
Number.metaClass.getDollars = { delegate }
String GOOG = 'Google'
def sell(int nShares) {
[of: { String ticker ->
[at: { int price ->
println "Sold $nShares $ticker at $$price"
}]
}]
}
sell 100.shares of GOOG at 1000.dollars
Command chains in DSLs
show = { println it }
square_root = { Math.sqrt(it) }
def please(action) {
[the: { what ->
[of: { n -> action(what(n)) }]
}]
}
please show the square_root of 100
// ==> 10.0
Command chains in DSLs
show = { println it }
square_root = { Math.sqrt(it) }
def please(action) {
[the: { what ->
[of: { n -> action(what(n)) }]
}]
}
please(show).the(square_root).of(100)
// ==> 10.0
Command chains in DSLs
show = { println it }
square_root = { Math.sqrt(it) }
def please(action) {
[the: { what ->
[of: { n -> action(what(n)) }]
}]
}
please(show).the(square_root).of(100)
// ==> 10.0
… and again in another language …
Command chains in DSLs
// Japanese DSL
Object.metaClass.を =
Object.metaClass.の =
{ clos -> clos(delegate) }
まず = { it }
表示する = { println it }
平方根 = { Math.sqrt(it) }
まず 100 の 平方根 を 表示する
// First, show the square root of 100
// => 10.0 // source: http://d.hatena.ne.jp/uehaj/20100919/1284906117
// http://groovyconsole.appspot.com/edit/241001
Part 3: What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Command chains
 Cranes and tortoises revisited
• Ecosystem
• Community/Team
Logic programming example
cranes have 2 legs
tortoises have 4 legs
there are 7 animals
there are 20 legs
How many of each animal?
Recall: Constraint programming example
@Grab('org.choco-solver:choco-solver:4.0.0')
import org.chocosolver.solver.Model
def m = new Model()
def totalAnimals = 7
def totalLegs = 20
def numCranes = m.intVar('Cranes', 0, totalAnimals, true)
def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true)
def numCraneLegs = m.intScaleView(numCranes, 2)
def numTortoiseLegs = m.intScaleView(numTortoises, 4)
m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post()
m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post()
if (m.solver.solve())
println "$numCranesn$numTortoises"
else
println "No Solutions" Cranes = 4
Tortoises = 3
ChocoCraneTortoise.groovy
Logic programming example
dslUntyped/ChocoCraneTortoiseDSL.groovy
50 lines to define the DSL
Logic programming example
cranes have 2 legs
tortoises have 4 legs
there are 7 animals
there are 20 legs
display solution
Cranes 4
Tortoises 3
dslUntyped/ChocoCraneTortoiseDSL.groovy
50 lines to define the DSL
Logic programming example
cranes have 2 legs
tortoises have 4 legs
millipedes have 1000 legs
there are 8 animals
there are 1020 legs
display solution
Cranes 4
Tortoises 3
Millipedes 1
dslUntyped/ChocoCraneTortoiseDSL.groovy
50 lines to define the DSL
Logic programming example
Crane(2), Tortoise(4), Beetle(6), Centipede(100), Millipede(1000)
Solution: Tortoise = 3, Beetle = 23
Solution: Crane = 1, Tortoise = 1, Beetle = 24
Solution: Crane = 25, Centipede = 1
dslTyped/ChocoCraneTortoiseDSL.groovy
80 lines to define the DSL
@TypeChecked
def main() {
animals seen include Crane, Tortoise, Beetle, Centipede
leg count is 150
head count is 26
display solution
}
@TypeChecked
def main() {
animals seen include Crane, Tortoise, Beetle, Centipede
leg count is 150
head count is 26
display solution
}
Logic programming example
dslTyped/ChocoCraneTortoiseDSL.groovy
80 lines to define the DSL
DSL Type Provider
unresolvedVariable { var ->
if (!cachedAnimalNames) {
def accessKey = '72ddf45a-c751-44c7-9bca-8db3b4513347'
// for illustrative purposes, just download xml for a few animals
def uid = 'ELEMENT_GLOBAL.2.104550,ELEMENT_GLOBAL.2.105196,ELEMENT_GLOBAL.2.120227'
def base = "https://services.natureserve.org/idd/rest/ns/v1.1/globalSpecies"
def url = "$base/comprehensive?uid=$uid&NSAccessKeyId=$accessKey"
def root = new XmlParser().parse(url)
def names = root.globalSpecies.classification.names
cachedAnimalNames = names.natureServePrimaryGlobalCommonName*.text()*.replaceAll(' ','')
}
if (var.name in cachedAnimalNames) {
storeType(var, STRING_TYPE)
handled = true
enclosingClassNode.addField(var.name, 0, STRING_TYPE, new ConstantExpression(var.name))
}
}
DSL Type Provider
@TypeChecked(extensions='NatureServeAnimalProvider.groovy')
def main() {
animals seen include SandhillCrane, GopherTortoise, ChihuahuanMillipede
leg count is 1020
head count is 8
display solution
}
Custom checker
provider/ChocoCraneTortoiseProvider.groovy
80 lines to define the DSL
25 lines to define the provider
Awesome
Awesome
Awesome
Awesome
Ecosystem
Groovy's Awesome Team
Groovy's Awesome Team
Groovy's Awesome Team
+100's of others
Direct downloads:
2013: approx. 3 million
2014: 4+ million
2015: 12+ million
now: 2+ million/month
Groovy's Awesome Team
+100's of others just like YOU!
http://www.manning.com/koenig2
Groovy in Action 2nd edition
Manning promo code:
ctwg3sum
(39% off all Manning books)
152

More Related Content

What's hot

Rest presentation
Rest  presentationRest  presentation
Rest presentationsrividhyau
 
Big Data with MySQL
Big Data with MySQLBig Data with MySQL
Big Data with MySQLIvan Zoratti
 
Advanced data modeling
Advanced data modelingAdvanced data modeling
Advanced data modelingDhani Ahmad
 
Dbms classification according to data models
Dbms classification according to data modelsDbms classification according to data models
Dbms classification according to data modelsABDUL KHALIQ
 
Database Administration
Database AdministrationDatabase Administration
Database AdministrationBilal Arshad
 
Presentation on tablespaceses segments extends and blocks
Presentation on tablespaceses segments extends and blocksPresentation on tablespaceses segments extends and blocks
Presentation on tablespaceses segments extends and blocksVinay Ugave
 
An Enterprise Architect's View of MongoDB
An Enterprise Architect's View of MongoDBAn Enterprise Architect's View of MongoDB
An Enterprise Architect's View of MongoDBMongoDB
 
PostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | EdurekaPostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | EdurekaEdureka!
 
Presentation database security audit vault & database firewall
Presentation   database security audit vault & database firewallPresentation   database security audit vault & database firewall
Presentation database security audit vault & database firewallxKinAnx
 
NOSQL- Presentation on NoSQL
NOSQL- Presentation on NoSQLNOSQL- Presentation on NoSQL
NOSQL- Presentation on NoSQLRamakant Soni
 

What's hot (20)

Database security issues
Database security issuesDatabase security issues
Database security issues
 
Rest presentation
Rest  presentationRest  presentation
Rest presentation
 
Presentation1.pptx
Presentation1.pptxPresentation1.pptx
Presentation1.pptx
 
Chapter 1 introduction to sql server
Chapter 1 introduction to sql serverChapter 1 introduction to sql server
Chapter 1 introduction to sql server
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
Big Data with MySQL
Big Data with MySQLBig Data with MySQL
Big Data with MySQL
 
Bootstrap
BootstrapBootstrap
Bootstrap
 
Introduction to JSON & AJAX
Introduction to JSON & AJAXIntroduction to JSON & AJAX
Introduction to JSON & AJAX
 
Advanced data modeling
Advanced data modelingAdvanced data modeling
Advanced data modeling
 
Dbms classification according to data models
Dbms classification according to data modelsDbms classification according to data models
Dbms classification according to data models
 
7 data management design
7 data management design7 data management design
7 data management design
 
Database Administration
Database AdministrationDatabase Administration
Database Administration
 
Presentation on tablespaceses segments extends and blocks
Presentation on tablespaceses segments extends and blocksPresentation on tablespaceses segments extends and blocks
Presentation on tablespaceses segments extends and blocks
 
Restful web services ppt
Restful web services pptRestful web services ppt
Restful web services ppt
 
Laravel Tutorial PPT
Laravel Tutorial PPTLaravel Tutorial PPT
Laravel Tutorial PPT
 
An Enterprise Architect's View of MongoDB
An Enterprise Architect's View of MongoDBAn Enterprise Architect's View of MongoDB
An Enterprise Architect's View of MongoDB
 
PostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | EdurekaPostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | Edureka
 
Presentation database security audit vault & database firewall
Presentation   database security audit vault & database firewallPresentation   database security audit vault & database firewall
Presentation database security audit vault & database firewall
 
NOSQL- Presentation on NoSQL
NOSQL- Presentation on NoSQLNOSQL- Presentation on NoSQL
NOSQL- Presentation on NoSQL
 
Database File operation
Database File operationDatabase File operation
Database File operation
 

Viewers also liked

Gr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedGr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedAndres Almiray
 
groovy transforms
groovy transformsgroovy transforms
groovy transformsPaul King
 
groovy databases
groovy databasesgroovy databases
groovy databasesPaul King
 
Groovy Tutorial
Groovy TutorialGroovy Tutorial
Groovy TutorialPaul King
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGuillaume Laforge
 
Greach - The Groovy Ecosystem
Greach - The Groovy EcosystemGreach - The Groovy Ecosystem
Greach - The Groovy EcosystemAndres Almiray
 
Making the Most of Your Gradle Build
Making the Most of Your Gradle BuildMaking the Most of Your Gradle Build
Making the Most of Your Gradle BuildAndres Almiray
 
Make Your Testing Groovy
Make Your Testing GroovyMake Your Testing Groovy
Make Your Testing GroovyPaul King
 
concurrency gpars
concurrency gparsconcurrency gpars
concurrency gparsPaul King
 
Practical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g ImplementationsPractical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g ImplementationsMichael Rainey
 
GoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data WarehousingGoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data WarehousingMichael Rainey
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...Michael Rainey
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data IntegrationA Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data IntegrationMichael Rainey
 
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data StreamingOracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data StreamingMichael Rainey
 
그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수Yeon Soo Kim
 
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12cGoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12cMichael Rainey
 
Real-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success StoriesReal-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success StoriesMichael Rainey
 
GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...Michael Rainey
 
Real-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c AdaptorsReal-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c AdaptorsMichael Rainey
 
Vert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMVert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMMassimiliano Dessì
 

Viewers also liked (20)

Gr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedGr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem Revisited
 
groovy transforms
groovy transformsgroovy transforms
groovy transforms
 
groovy databases
groovy databasesgroovy databases
groovy databases
 
Groovy Tutorial
Groovy TutorialGroovy Tutorial
Groovy Tutorial
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
 
Greach - The Groovy Ecosystem
Greach - The Groovy EcosystemGreach - The Groovy Ecosystem
Greach - The Groovy Ecosystem
 
Making the Most of Your Gradle Build
Making the Most of Your Gradle BuildMaking the Most of Your Gradle Build
Making the Most of Your Gradle Build
 
Make Your Testing Groovy
Make Your Testing GroovyMake Your Testing Groovy
Make Your Testing Groovy
 
concurrency gpars
concurrency gparsconcurrency gpars
concurrency gpars
 
Practical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g ImplementationsPractical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g Implementations
 
GoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data WarehousingGoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data IntegrationA Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration
 
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data StreamingOracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
 
그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수
 
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12cGoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
 
Real-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success StoriesReal-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success Stories
 
GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...
 
Real-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c AdaptorsReal-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
 
Vert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMVert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVM
 

Similar to awesome groovy

groovy rules
groovy rulesgroovy rules
groovy rulesPaul King
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Wsloffenauer
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceMaarten Balliauw
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GParsPaul King
 
Introduction to Oracle Groovy
Introduction to Oracle GroovyIntroduction to Oracle Groovy
Introduction to Oracle GroovyDeepak Bhagat
 
Polyglot Programming in the JVM
Polyglot Programming in the JVMPolyglot Programming in the JVM
Polyglot Programming in the JVMAndres Almiray
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala MakeoverGarth Gilmour
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Jonathan Felch
 
Top 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdetTop 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdetDevLabs Alliance
 
Writing Groovy DSLs
Writing Groovy DSLsWriting Groovy DSLs
Writing Groovy DSLsadam1davis
 
Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010Andres Almiray
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To ScalaPeter Maas
 
The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)jaxLondonConference
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005Tugdual Grall
 
Groovy for Java Developers
Groovy for Java DevelopersGroovy for Java Developers
Groovy for Java DevelopersAndres Almiray
 
Groovy
GroovyGroovy
Groovyatonse
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemKostas Saidis
 

Similar to awesome groovy (20)

groovy rules
groovy rulesgroovy rules
groovy rules
 
Groovy
GroovyGroovy
Groovy
 
Einführung in TypeScript
Einführung in TypeScriptEinführung in TypeScript
Einführung in TypeScript
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GPars
 
Introduction to Oracle Groovy
Introduction to Oracle GroovyIntroduction to Oracle Groovy
Introduction to Oracle Groovy
 
Polyglot Programming in the JVM
Polyglot Programming in the JVMPolyglot Programming in the JVM
Polyglot Programming in the JVM
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala Makeover
 
TDD with PhpSpec
TDD with PhpSpecTDD with PhpSpec
TDD with PhpSpec
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)
 
Top 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdetTop 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdet
 
Writing Groovy DSLs
Writing Groovy DSLsWriting Groovy DSLs
Writing Groovy DSLs
 
Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
 
The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
 
Groovy for Java Developers
Groovy for Java DevelopersGroovy for Java Developers
Groovy for Java Developers
 
Groovy
GroovyGroovy
Groovy
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystem
 

More from Paul King

tictactoe groovy
tictactoe groovytictactoe groovy
tictactoe groovyPaul King
 
functional groovy
functional groovyfunctional groovy
functional groovyPaul King
 
Make Testing Groovy
Make Testing GroovyMake Testing Groovy
Make Testing GroovyPaul King
 
Agile Testing Practices
Agile Testing PracticesAgile Testing Practices
Agile Testing PracticesPaul King
 
groovy DSLs from beginner to expert
groovy DSLs from beginner to expertgroovy DSLs from beginner to expert
groovy DSLs from beginner to expertPaul King
 
groovy and concurrency
groovy and concurrencygroovy and concurrency
groovy and concurrencyPaul King
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy PluginsPaul King
 
Dynamic Language Practices
Dynamic Language PracticesDynamic Language Practices
Dynamic Language PracticesPaul King
 
Make Your Builds More Groovy
Make Your Builds More GroovyMake Your Builds More Groovy
Make Your Builds More GroovyPaul King
 
Groovy Power Features
Groovy Power FeaturesGroovy Power Features
Groovy Power FeaturesPaul King
 
Groovy Testing Sep2009
Groovy Testing Sep2009Groovy Testing Sep2009
Groovy Testing Sep2009Paul King
 
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...
Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...Paul King
 
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Paul King
 
XML and Web Services with Groovy
XML and Web Services with GroovyXML and Web Services with Groovy
XML and Web Services with GroovyPaul King
 

More from Paul King (15)

tictactoe groovy
tictactoe groovytictactoe groovy
tictactoe groovy
 
functional groovy
functional groovyfunctional groovy
functional groovy
 
Make Testing Groovy
Make Testing GroovyMake Testing Groovy
Make Testing Groovy
 
Agile Testing Practices
Agile Testing PracticesAgile Testing Practices
Agile Testing Practices
 
groovy DSLs from beginner to expert
groovy DSLs from beginner to expertgroovy DSLs from beginner to expert
groovy DSLs from beginner to expert
 
groovy and concurrency
groovy and concurrencygroovy and concurrency
groovy and concurrency
 
GroovyDSLs
GroovyDSLsGroovyDSLs
GroovyDSLs
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Dynamic Language Practices
Dynamic Language PracticesDynamic Language Practices
Dynamic Language Practices
 
Make Your Builds More Groovy
Make Your Builds More GroovyMake Your Builds More Groovy
Make Your Builds More Groovy
 
Groovy Power Features
Groovy Power FeaturesGroovy Power Features
Groovy Power Features
 
Groovy Testing Sep2009
Groovy Testing Sep2009Groovy Testing Sep2009
Groovy Testing Sep2009
 
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...
Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...
 
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
 
XML and Web Services with Groovy
XML and Web Services with GroovyXML and Web Services with Groovy
XML and Web Services with Groovy
 

Recently uploaded

A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 

Recently uploaded (20)

Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 

awesome groovy

  • 1. Dr Paul King Groovy Lead for Object Computing Inc. @paulk_asert http:/slideshare.net/paulk_asert/awesome-groovy https://github.com/paulk-asert/awesome-groovy Apache Groovy: The Awesome Parts FRIEND OF GROOVY
  • 2.
  • 4. What is Groovy? 4 Groovy = Java – boiler plate code + closures (1st class FP) + extensible type system + runtime & compile-time metaprogramming + flexible language grammar (DSLs) + scripting + GDK library “Groovy is like a super version of Java. It leverages Java features but adds productivity features and provides great flexibility and extensibility.”
  • 5.
  • 7. Why Groovy? Too verbose Support functional programming Better concurrency Evolves too slowly I need feature XXX Too complex for some situations More flexibility Java
  • 8. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting
  • 9. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Java integration
  • 10. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Good IDE support Java integration
  • 11. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Good IDE support Custom features Java integration
  • 12. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Support concurrency Good IDE support Custom features Java integration
  • 13. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Support functional style Support concurrency Good IDE support Custom features Java integration
  • 14.
  • 15. Java code for list manipulation import java.util.List; import java.util.ArrayList; class Main { private List keepShorterThan(List strings, int length) { List result = new ArrayList(); for (int i = 0; i < strings.size(); i++) { String s = (String) strings.get(i); if (s.length() < length) { result.add(s); } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add("Ted"); names.add("Fred"); names.add("Jed"); names.add("Ned"); System.out.println(names); Main m = new Main(); List shortNames = m.keepShorterThan(names, 4); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } }
  • 16. Groovy code for list manipulation import java.util.List; import java.util.ArrayList; class Main { private List keepShorterThan(List strings, int length) { List result = new ArrayList(); for (int i = 0; i < strings.size(); i++) { String s = (String) strings.get(i); if (s.length() < length) { result.add(s); } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add("Ted"); names.add("Fred"); names.add("Jed"); names.add("Ned"); System.out.println(names); Main m = new Main(); List shortNames = m.keepShorterThan(names, 4); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } } Rename Main.java to Main.groovy
  • 17. Some Java Boilerplate identified import java.util.List; import java.util.ArrayList; class Main { private List keepShorterThan(List strings, int length) { List result = new ArrayList(); for (int i = 0; i < strings.size(); i++) { String s = (String) strings.get(i); if (s.length() < length) { result.add(s); } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add("Ted"); names.add("Fred"); names.add("Jed"); names.add("Ned"); System.out.println(names); Main m = new Main(); List shortNames = m.keepShorterThan(names, 4); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } } Are the semicolons needed? And shouldn’t we us more modern list notation? Why not import common libraries? Do we need the static types? Must we always have a main method and class definition? How about improved consistency?
  • 18. Java Boilerplate removed def keepShorterThan(strings, length) { def result = new ArrayList() for (s in strings) { if (s.size() < length) { result.add(s) } } return result } names = new ArrayList() names.add("Ted"); names.add("Fred") names.add("Jed"); names.add("Ned") System.out.println(names) shortNames = keepShorterThan(names, 4) System.out.println(shortNames.size()) for (s in shortNames) { System.out.println(s) }
  • 19. More Java Boilerplate identified def keepShorterThan(strings, length) { def result = new ArrayList() for (s in strings) { if (s.size() < length) { result.add(s) } } return result } names = new ArrayList() names.add("Ted"); names.add("Fred") names.add("Jed"); names.add("Ned") System.out.println(names) shortNames = keepShorterThan(names, 4) System.out.println(shortNames.size()) for (s in shortNames) { System.out.println(s) } Shouldn’t we have special notation for lists? And special facilities for list processing? Is ‘return’ needed at end? Is the method now needed? Simplify common methods? Remove unambiguous brackets?
  • 20. Boilerplate removed = nicer Groovy version names = ["Ted", "Fred", "Jed", "Ned"] println names shortNames = names.findAll{ it.size() < 4 } println shortNames.size() shortNames.each{ println it } ["Ted", "Fred", "Jed", "Ned"] 3 Ted Jed Ned Output:
  • 21. Or Groovy DSL version if required given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 // plus a DSL implementation
  • 22. Or Groovy DSL version if required given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 names = [] def of, having, less def given(_the) { [names:{ Object[] ns -> names.addAll(ns) [and: { n -> names += n }] }] } def the = [ number: { _of -> [names: { _having -> [size: { _less -> [than: { size -> println names.findAll{ it.size() < size }.size() }]}] }] }, names: { _having -> [size: { _less -> [than: { size -> names.findAll{ it.size() < size }.each{ println it } }]}] } ] def all = [the: { println it }] def display(arg) { arg }
  • 23. Or Groovy DSL version if required • Or use GDSL (IntelliJ IDEA) or DSLD (Eclipse) given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4
  • 24. Or typed Groovy DSL version if required given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 … enum The { the } enum Having { having } enum Of { of } … class DisplayThe { DisplayTheNamesHaving names(Having having) { new DisplayTheNamesHaving() } DisplayTheNumberOf number(Of of) { new DisplayTheNumberOf() } } … // plus 50 lines
  • 25. Or typed Groovy DSL version if required
  • 26. Groovy DSL being debugged
  • 27. Or typed Groovy DSL version if required @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 }
  • 28. Or typed Groovy DSL version if required @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 } afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } } 
  • 29. @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 } Or typed Groovy DSL version if required afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } }
  • 30. @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", “Mary", "Jed" and “Pete" display all the names display the number of names having size less than 4 display the names having size less than 4 } afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } } Or typed Groovy DSL version if required
  • 31. @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", “Mary", "Jed" and “Pete" display all the names display the number of names having size less than 4 display the names having size less than 4 } afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } } Or typed Groovy DSL version if required 
  • 32. What style of language is Groovy?
  • 33. Groovy Style • Imperative/OO but somewhat paradigm agnostic •Dynamic, optionally static (gradual extensible typing) • Extensible language features through metaprogramming
  • 34. Part 2: What makes Groovy Awesome?
  • 35. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain specific language (DSL) support • Ecosystem • Community/Team Awesome
  • 36. What makes Groovy Awesome? • Java integration • Builds up on Java • Tight integration • Polyglot friendly • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team
  • 37. Java Integration • Groovy is Java’s friend Java Groovy
  • 38. Java Integration • Standing on the shoulders of Giants • Some limitations inherited but much gained through new releases of Java • Rock solid foundation • Can ease migration to new versions of Java Java Groovy
  • 39. Java Integration • Seamless integration • IDEs provide cross-language compile, navigation, and refactoring • Arbitrarily mix source language • Drop-in replace any class • Overloaded methods • Syntax alignment • Shared data types Java Groovy
  • 40. Java Integration • Seamless integration • IDEs provide cross-language compile, navigation, and refactoring • Arbitrarily mix source language • Drop-in replace any class • Overloaded methods • Syntax alignment • Shared data types Java Groovy
  • 41. Java Integration • Polyglot friendly • Typically integrates well with other languages which integrate with Java • JRuby • Jython • Scala • Frege • Clojure • R through Renjin • JavaScript (Rhino/Nashorn)
  • 42. Java Integration • Polyglot friendly • JSR-223 scripting to talk to JavaScript import javax.script.ScriptEngineManager def mgr = new ScriptEngineManager() def engine = mgr.getEngineByName('nashorn') assert engine.eval(''' function factorial(n) { if (n == 0) { return 1; } return n * factorial(n - 1); } factorial(4) ''') == 24.0 Java GroovyJavaScript
  • 43. Java Integration • Polyglot friendly: R integration @GrabResolver('https://nexus.bedatadriven.com/content/groups/public') @Grab('org.renjin:renjin-script-engine:0.7.0-RC7') import javax.script.ScriptEngineManager def mgr = new ScriptEngineManager() def engine = mgr.getEngineByName('Renjin') engine.with { eval ''' factorial <- function(x) { y <- 1 for (i in 1:x) { y <- y * i } return(y) } ''' assert eval('factorial(4)')[0] == 24 } Java GroovyR
  • 44. Grooscript @Grab('org.grooscript:grooscript:1.2.0') import org.grooscript.GrooScript import javax.script.ScriptEngineManager def groojs = GrooScript.convert ''' def sayHello = { println "Hello ${it}!" } ['Groovy','JavaScript','GrooScript'].each sayHello''', [initialText: 'var console = { log: print }', addGsLib: 'grooscript.min'] new ScriptEngineManager().getEngineByName("nashorn").eval(groojs) Hello Groovy! Hello JavaScript! Hello GrooScript! Jorge Franco, grooscript.org Convert Groovy subset to JavaScript Support: Gradle, Grails, NPM Demos: react.js, node.js, Pollock Converts: Classes, closures, Date primitives, ranges, String/GString Special: builder, templates, gQuery
  • 45. What makes Groovy Awesome? • Java integration • Builds up on Java • Tight integration • Polyglot friendly • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team Awesome • Friend of Java • Integration • Good JVM Citizen
  • 46. What makes Groovy Awesome? • Java integration • Scripting support • Simplified scripting • Separation of concerns • Security sandbox • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team Awesome
  • 47. Scripting • Terse format • Isolation • Domain-Specific Languages (DSLs) • Security • Flexibility
  • 48. Scripting • Leave out surrounding class • Entire source file: public class Script { public static void main(String[] args) { System.out.println("Hello world"); } } println "Hello world"
  • 49. Scripting • Various approaches supported • GroovyShell • GroovyScriptEngine • GroovyClassLoader • Spring • JSR-223 • Base scripts • allows predefined methods • Binding • allows predefined variables • Customizers • add imports, static imports • lock down AST to a subset • apply any AST transform transparently
  • 53. Scripting class Robot { void move(dir) { println "robot moved $dir" } } def robot = new Robot()
  • 54. Scripting import static Direction.* enum Direction { left, right, forward, backward } class Robot { void move(Direction dir) { println "robot moved $dir" } } def robot = new Robot() robot.move left
  • 55. Scripting move left def robot = new Robot() def binding = new Binding( robot: robot, move: robot.&move, *: Direction.values().collectEntries { [(it.name()): it] } ) def shell = new GroovyShell(binding) shell.evaluate new File(args[0]).text
  • 56. Scripting move left def robot = new Robot() def binding = new Binding(/* ... */) def imports = new ImportCustomizer().addStaticStars('java.lang.Math') def timeout = new ASTTransformationCustomizer(value: 2, TimedInterrupt) def secure = new SecureASTCustomizer().with { closuresAllowed = false importsWhitelist = [] tokensWhitelist = [ PLUS, MINUS, MULTIPLY, DIVIDE, /*...*/ ] //... } def sysExit = new CompilationCustomizer(CANONICALIZATION) { void call(SourceUnit src, GeneratorContext ctxt, ClassNode cn) { new ClassCodeVisitorSupport() { void visitMethodCallExpression(MethodCallExpression call) { // check for System.exit() } // ... }.visitClass(cn) } } def config = new CompilerConfiguration() config.addCompilationCustomizers(imports, timeout, secure, sysExit) def shell = new GroovyShell(binding, config)
  • 57. Scripting move left move forward at 3.km/h More examples later
  • 58. What makes Groovy Awesome? • Java integration • Scripting support • Simplified scripting • Separation of concerns • Security sandbox • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team Awesome • Simpler scripting • Separation of concerns
  • 59. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Object-oriented • Functional, Closures • Logic/Dataflow programming • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team
  • 60. Multiparadigm • Imperative roots from Java • OO abstractions: classes, interfaces, inheritance • Properties • Traits • First class functional support via closures • External libraries for advanced features • Other paradigms via libraries • Logic, dataflow, reactive Awesome
  • 62. Rich OO features • Classes (and scripts, GroovyBeans) • Fields (and properties) • Methods, constructors, multi-methods, named and default parameters • Inheritance (behavior and implementation), interfaces, traits • Type aliases • Packages • Special accessor notation, spread operators, GPath, safe navigation
  • 63. Traits /** * Things that hop * @author Grace */ trait Hopper { String jump() { "I'm jumping!" } } class Kangaroo implements Hopper {} def skip = new Kangaroo() assert skip.jump() == "I'm jumping!"
  • 64. Rich functional features • Closures • First-class functions • Higher-order functions • Map, reduce, filter • Mutable & immutable data • Recursion • Lazy & eager evaluation • Advanced FP techniques • Memoization, Trampolines, Composition, Curry • Concurrency
  • 65. map/filter/reduce @Canonical class Person { String name int age } def people = [ new Person('Peter', 45), new Person('Paul', 35), new Person('Mary', 25) ] assert people .findAll{ it.age < 40 } .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL'
  • 66. map/filter/reduce (+ functional style) @Canonical class Person { String name int age } def people = [ new Person('Peter', 45), new Person('Paul', 35), new Person('Mary', 25) ] assert people .findAll{ it.age < 40 } .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL' def young = { person, threshold -> person.age < threshold }.rcurry(40).memoize() assert people .findAll(young) .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL'
  • 67. map/filter/reduce (+ with streams) @Canonical class Person { String name int age } def people = [ new Person('Peter', 45), new Person('Paul', 35), new Person('Mary', 25) ] assert people .findAll{ it.age < 40 } .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL' // requires JRE 8 def commaSep = Collectors.joining(", ") assert people.stream() .filter{ it.age < 40 } .map{ it.name.toUpperCase() } .sorted() .collect(commaSep) == 'MARY, PAUL'
  • 68. Logic/Constraint programming • Logic programming • Declarative style • Logic clauses for example Prolog • Constraint programming • Declarative style similar to logic programming but contain constraints which must be satisfied • Relations between variables are stated as constraints • Not a step or sequence of steps to execute, but rather the properties of a solution to be found
  • 69. Logic programming example cranes have 2 legs tortoises have 4 legs there are 7 animals there are 20 legs How many of each animal?
  • 70. Constraint programming example @Grab('org.choco-solver:choco-solver:4.0.4') import org.chocosolver.solver.Model def m = new Model() def totalAnimals = 7 def totalLegs = 20 def numCranes = m.intVar('Cranes', 0, totalAnimals, true) def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true) def numCraneLegs = m.intScaleView(numCranes, 2) def numTortoiseLegs = m.intScaleView(numTortoises, 4) m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post() m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post() if (m.solver.solve()) println "$numCranesn$numTortoises" else println "No Solutions" Cranes = 4 Tortoises = 3 ChocoCraneTortoise.groovy See also: JSR-331 Constraint Programming API
  • 71. Dataflow programming • Declarative style • Emphasizes the movement of data • models programs as a series of connected tasks • A task has explicitly defined inputs and outputs • runs as soon as all of its inputs become available • Inherently parallel
  • 72. GPars • Library classes and DSL allowing you to handle tasks concurrently: • Data Parallelism map, filter, reduce functionality in parallel with parallel array support • Asynchronous functions extend the Java executor services to enable multi-threaded closure processing • Dataflow Concurrency supports natural shared-memory concurrency model, using single-assignment variables • Actors provide Erlang/Scala-like actors including "remote" actors on other machines • Safe Agents provide a non-blocking mt-safe reference to mutable state; like "agents" in Clojure 72 Awesome
  • 73. Concurrency challenge • We can analyse the example’s task graph: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] def a = 5 def b = f1(a) def c = f2(a) def d = f3(c) def f = f4(b, d) assert f == 10
  • 74. Concurrency challenge • We can analyse the example’s task graph: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] def a = 5 def b = f1(a) def c = f2(a) def d = f3(c) def f = f4(b, d) assert f == 10 f2 f3 f1 f4 aa b c d f
  • 75. Concurrency challenge • Manually using asynchronous functions: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] import static groovyx.gpars.GParsPool.withPool withPool(2) { def a = 5 def futureB = f1.callAsync(a) def c = f2(a) def d = f3(c) def f = f4(futureB.get(), d) assert f == 10 } f2 f3 f1 f4 aa futureB c d f
  • 76. Concurrency challenge • And with GPars Dataflows: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] import groovyx.gpars.dataflow.Dataflows import static groovyx.gpars.dataflow.Dataflow.task new Dataflows().with { task { a = 5 } task { b = f1(a) } task { c = f2(a) } task { d = f3(c) } task { f = f4(b, d) } assert f == 10 } f2 f3 f1 f4 aa b c d f
  • 77. Concurrency challenge • And with GPars Dataflows: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] import groovyx.gpars.dataflow.Dataflows import static groovyx.gpars.dataflow.Dataflow.task new Dataflows().with { task { f = f4(b, d) } task { d = f3(c) } task { c = f2(a) } task { b = f1(a) } task { a = 5 } assert f == 10 } f2 f3 f1 f4 aa b c d f
  • 78. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Object-oriented • Functional, Closures • Logic/dataflow programming • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team • Ability to use imperative when needed for speed • Numerous declarative approaches available when it makes sense Awesome
  • 79. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Dynamic strong typing • Static type checking • Extensible • Type inference • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team
  • 80. Gradual typing • Dynamic by default • Gradual typing • Static type checking • Extensible type system Awesome
  • 81. Dynamic vs static 82 def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() }
  • 82. Dynamic vs static 83 Gradual Type-time? def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() }
  • 83. Dynamic vs static 84 def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY'
  • 84. Dynamic vs static 85 def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY' def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } Duck-typing
  • 85. Dynamic vs static 86 def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY' def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } @TypeChecked def myMethod() { def myPets = ['Lassie', 'Skip'] List yourPets = ['Lassie', 'Skip'] } shouldFail(CompilationFailedException) { assertScript ''' @groovy.transform.TypeChecked def yourMethod() { List ourPets = new Date() } ''' }
  • 86. Dynamic vs static 87 def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY' def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } @TypeChecked def myMethod() { def myPets = ['Lassie', 'Skip'] List yourPets = ['Lassie', 'Skip'] } shouldFail(CompilationFailedException) { assertScript ''' @groovy.transform.TypeChecked def yourMethod() { List ourPets = new Date() } ''' } Extensible Inference
  • 87. Extensible type checking import groovy.transform.TypeChecked import experimental.SprintfTypeChecker @TypeChecked(extensions=SprintfTypeChecker) void main() { sprintf('%s will turn %d on %tF', 'John', new Date(), 21) } [Static type checking] - Parameter types didn't match types expected from the format String: For placeholder 2 [%d] expected 'int' but was 'java.util.Date' For placeholder 3 [%tF] expected 'java.util.Date' but was 'int' sprintf has an Object varargs parameter, hence not normally amenable to further static checking but for constant Strings we can do better using a custom type checking plugin.
  • 88. Extensible type checking import groovy.sql.Sql import groovy.transform.TypeChecked @TypeChecked(extensions='SQLExtension.groovy') findAthletes(Sql sql) { sql.eachRow('select * frm Athlete') { row -> println row } } SqlTC.groovy: 7: [Static type checking] - SQL query is not valid: net.sf.jsqlparser.JSQLParserException @ line 6, column 15. sql.eachRow('select * frm Athlete') { row -> println row } ^ 1 error
  • 89. Static compilation import groovy.transform.* class Actor { String firstName, lastName @CompileStatic String getFullName() { "$firstName $lastName" } void makePeace() { new AntBuilder().echo('Peace was never an option') } } def magneto = new Actor(firstName: 'Ian', lastName: 'McKellen') assert magneto.fullName == 'Ian McKellen' magneto.makePeace()
  • 91. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Dynamic strong typing • Static type checking • Extensible • Type inference • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team • Maximise duck-typing • Minimise noise • yet type inference • Flexibility at runtime • As strict as you want when needed • Fast when needed Awesome
  • 92. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Runtime • Compile-time • Macros • Domain Specific Language support • Ecosystem • Community/Team
  • 93. Runtime metaprogramming • Add instance & static methods, constructors, properties at runtime • Intercept method/property access • Catch missing methods, properties • Used for dynamic builders, aspect-oriented programming, test stubs, mocks & dummies Awesome* * Individual levels of awesomeness may vary
  • 94. Runtime metaprogramming • Adding methods at runtime assert 'Hello'.reverse() == 'olleH' String.metaClass.swapCase = { delegate.collect{ it in 'A'..'Z' ? it.toLowerCase() : it.toUpperCase() }.join() } assert 'Hello'.swapCase() == 'hELLO'
  • 95. Runtime metaprogramming • Intercepting methods class Foo { def one() { println "Called one()" } def methodMissing(String name, params) { println "Attempted $name($params)" } } def f = new Foo() f.one() f.two() f.three('Some Arg') Called one() Attempted two([]) Attempted three([Some Arg])
  • 96. XML Parsing/GPath expressions def xml = ''' <hosts> <host name='MyHost'> <service name='MyMicroService'/> <service name='MyNanoService'/> </host> </hosts> ''' def hosts = new XmlParser().parseText(xml) assert hosts.host.service[0].@name=='MyMicroService'
  • 97. def xml = ''' <hosts> <host name='MyHost'> <service name='MyMicroService'/> <service name='MyNanoService'/> </host> </hosts> ''' def hosts = new XmlParser().parseText(xml) assert hosts.host.service[0].@name=='MyMicroService' XML Parsing/GPath expressions
  • 98. Compile-time metaprogramming • Gives you the ability to change the language by augmenting the compilation process Awesome
  • 99. Compile-time metaprogramming • Modify the program at compile-time @ToString class Person { String first, last } println new Person(first: 'John', last: 'Smith') // => Person(John, Smith)
  • 100. Compile-time metaprogramming • Modify the program at compile-time class Person { String first, last String toString() { "Person($first, $last)" } } println new Person(first: 'John', last: 'Smith') // => Person(John, Smith)
  • 101. Parsing Summary public run() ... L1 ALOAD 1 LDC 1 AALOAD ALOAD 0 LDC "Howdy Y'all" INVOKEINTERFACE callCurrent() ARETURN ... println "Howdy Y'all" BlockStatement -> ReturnStatement -> MethodCallExpression -> VariableExpression("this") -> ConstantExpression("println") -> ArgumentListExpression -> ConstantExpression("Howdy Y'all") MyScript.groovy > groovy MyScript.groovy > groovyc MyScript.groovy > groovysh > groovyConsole
  • 102. • 9 phase compiler – Early stages: read source code and convert into a sparse syntax tree – Middle stages: iteratively build up a more dense and information rich version of the syntax tree – Later stages: check the tree and convert it into byte code/class files Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization Parsing Summary
  • 103. Parsing - Early Stages Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization @ToString class Greeter { String message = "Howdy Y'all" void greet() { println message } } ClassNode: Greeter MethodNode: greet Property: message type: unresolved(String) AnnotationNode: ToString type: unresolved(ToString) methods: properties: annotations: BlockStatement MethodCall: this.println(message)
  • 104. Parsing - Middle Stages Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization ClassNode: Greeter MethodNode: greet FieldNode: message type: resolved(String) methods: fields: constructors: ConstructorNode MethodNode: getMessageMethodNode: setMessageMethodNode: toString MethodNode: getMetaClass…
  • 105. Parsing - Final Stages 106 Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization public greet()V ... L1 ... ALOAD 0 GETFIELD Greeter.message INVOKEINTERFACE callCurrent() POP ...
  • 106. Immutable Classes • Some Rules • Don’t provide mutators • Ensure that no methods can be overridden o Easiest to make the class final o Or use static factories & non-public constructors • Make all fields final • Make all fields private o Avoid even public immutable constants • Ensure exclusive access to any mutable components o Don’t leak internal references o Defensive copying in and out • Optionally provide equals and hashCode methods • Optionally provide toString method
  • 107. @Immutable... • Java Immutable Class • As per Joshua Bloch Effective Java public final class Person { private final String first; private final String last; public String getFirst() { return first; } public String getLast() { return last; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); return result; } public Person(String first, String last) { this.first = first; this.last = last; } // ... // ... @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; return true; } @Override public String toString() { return "Person(first:" + first + ", last:" + last + ")"; } }
  • 108. ...@Immutable... public final class Person { private final String first; private final String last; public String getFirst() { return first; } public String getLast() { return last; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); return result; } public Person(String first, String last) { this.first = first; this.last = last; } // ... // ... @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; return true; } @Override public String toString() { return "Person(first:" + first + ", last:" + last + ")"; } } boilerplate• Java Immutable Class • As per Joshua Bloch Effective Java
  • 109. ...@Immutable @Immutable class Person { String first, last } Awesome
  • 110. With Macros (Groovy 2.5+) import org.codehaus.groovy.ast.* import org.codehaus.groovy.ast.stmt.* import org.codehaus.groovy.ast.expr.* def ast = new ReturnStatement( new ConstructorCallExpression( ClassHelper.make(Date), ArgumentListExpression.EMPTY_ARGUMENTS ) ) def ast = macro { return new Date() }
  • 111. With Macros (Groovy 2.5+) Awesome import org.codehaus.groovy.ast.* import org.codehaus.groovy.ast.stmt.* import org.codehaus.groovy.ast.expr.* def ast = new ReturnStatement( new ConstructorCallExpression( ClassHelper.make(Date), ArgumentListExpression.EMPTY_ARGUMENTS ) ) def ast = macro { return new Date() }
  • 112. With Macros (Groovy 2.5+) • Variations: • Expressions, Statements, Classes • Supports variable substitution, specifying compilation phase def ast = macro { return new Date() }
  • 113. With Macros (Groovy 2.5+) • AST Matching: • Selective transformations, filtering, testing • Supports placeholders Expression transform(Expression exp) { Expression ref = macro { 1 + 1 } if (ASTMatcher.matches(ref, exp)) { return macro { 2 } } return super.transform(exp) }
  • 114. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. def getName(Z z) { z.y.list[0].name } • nullSafe
  • 115. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { z.y.list[0].name } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 116. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { z.y.list[0].name } Prone to NPE Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 117. Macro method examples • nullSafe class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { def result = null if (z != null && z.y != null && z.y.list != null && z.y.list[0] != null) { result = z.y.list[0].name } result } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser.
  • 118. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { def result = null if (z != null && z.y != null && z.y.list != null && z.y.list[0] != null) { result = z.y.list[0].name } result } Verbose Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 119. Macro method examples def getName(Z z) { z?.y?.list?[0]?.name } class X { String name } class Y { List<X> list } class Z { Y y } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 120. class X { String name } class Y { List<X> list } class Z { Y y } Macro method examples Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe def getName(Z z) { nullSafe(z.y.list[0].name) }
  • 121. Macro method examples @Macro static Expression nullSafe(MacroContext macroContext, Expression expression) { if (expression instanceof PropertyExpression) { // exp.prop -> exp?.prop … } else if (expression instanceof MethodCallExpression) { // exp.method() -> exp?.method() … } return expression } • nullSafe def getName(Z z) { nullSafe(z.y.list[0].name) }
  • 122. Macro method examples def fact(num) { return match(num) { when String then fact(num.toInteger()) when(0 | 1) then 1 when 2 then 2 orElse num * fact(num - 1) } } assert fact("5") == 120 See: https://github.com/touchez-du-bois/akatsuki
  • 123. Macro method examples • Spock inspired @Grab('org.spockframework:spock-core:1.0-groovy-2.4') import spock.lang.Specification class MathSpec extends Specification { def "maximum of two numbers"(int a, int b, int c) { expect: Math.max(a, b) == c where: a | b | c 1 | 3 | 3 7 | 4 | 7 0 | 0 | 0 } }
  • 124. Macro method examples See: https://github.com/touchez-du-bois/akatsuki doWithData { dowith: assert a + b == c where: a | b || c 1 | 2 || 3 4 | 5 || 9 7 | 8 || 15 }
  • 125. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Runtime • Compile-time • Macros • Domain Specific Language support • Ecosystem • Community/Team • Ability to change the language at runtime • Ability to change the language during the compilation process • Macros provide a homogeneous form for writing AST transformations Awesome
  • 126. Part 2: What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support  Command chains • Cranes and tortoises revisited • Ecosystem • Community/Team
  • 127. Command Chains • Ability to chain method calls without parentheses and dots Awesome
  • 128. Command Chains • Ability to chain method calls without parentheses and dots move forward at 3.km/h
  • 129. Command Chains • Ability to chain method calls without parentheses and dots • Equivalent to: move forward at 3.km/h move(forward).at(3.getKm().div(h))
  • 130. Command chains in DSLs Number.metaClass.getShares = { delegate } Number.metaClass.getDollars = { delegate } String GOOG = 'Google' def sell(int nShares) { [of: { String ticker -> [at: { int price -> println "Sold $nShares $ticker at $$price" }] }] } sell 100.shares of GOOG at 1000.dollars
  • 131. Command chains in DSLs show = { println it } square_root = { Math.sqrt(it) } def please(action) { [the: { what -> [of: { n -> action(what(n)) }] }] } please show the square_root of 100 // ==> 10.0
  • 132. Command chains in DSLs show = { println it } square_root = { Math.sqrt(it) } def please(action) { [the: { what -> [of: { n -> action(what(n)) }] }] } please(show).the(square_root).of(100) // ==> 10.0
  • 133. Command chains in DSLs show = { println it } square_root = { Math.sqrt(it) } def please(action) { [the: { what -> [of: { n -> action(what(n)) }] }] } please(show).the(square_root).of(100) // ==> 10.0 … and again in another language …
  • 134. Command chains in DSLs // Japanese DSL Object.metaClass.を = Object.metaClass.の = { clos -> clos(delegate) } まず = { it } 表示する = { println it } 平方根 = { Math.sqrt(it) } まず 100 の 平方根 を 表示する // First, show the square root of 100 // => 10.0 // source: http://d.hatena.ne.jp/uehaj/20100919/1284906117 // http://groovyconsole.appspot.com/edit/241001
  • 135. Part 3: What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Command chains  Cranes and tortoises revisited • Ecosystem • Community/Team
  • 136. Logic programming example cranes have 2 legs tortoises have 4 legs there are 7 animals there are 20 legs How many of each animal?
  • 137. Recall: Constraint programming example @Grab('org.choco-solver:choco-solver:4.0.0') import org.chocosolver.solver.Model def m = new Model() def totalAnimals = 7 def totalLegs = 20 def numCranes = m.intVar('Cranes', 0, totalAnimals, true) def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true) def numCraneLegs = m.intScaleView(numCranes, 2) def numTortoiseLegs = m.intScaleView(numTortoises, 4) m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post() m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post() if (m.solver.solve()) println "$numCranesn$numTortoises" else println "No Solutions" Cranes = 4 Tortoises = 3 ChocoCraneTortoise.groovy
  • 139. Logic programming example cranes have 2 legs tortoises have 4 legs there are 7 animals there are 20 legs display solution Cranes 4 Tortoises 3 dslUntyped/ChocoCraneTortoiseDSL.groovy 50 lines to define the DSL
  • 140. Logic programming example cranes have 2 legs tortoises have 4 legs millipedes have 1000 legs there are 8 animals there are 1020 legs display solution Cranes 4 Tortoises 3 Millipedes 1 dslUntyped/ChocoCraneTortoiseDSL.groovy 50 lines to define the DSL
  • 141. Logic programming example Crane(2), Tortoise(4), Beetle(6), Centipede(100), Millipede(1000) Solution: Tortoise = 3, Beetle = 23 Solution: Crane = 1, Tortoise = 1, Beetle = 24 Solution: Crane = 25, Centipede = 1 dslTyped/ChocoCraneTortoiseDSL.groovy 80 lines to define the DSL @TypeChecked def main() { animals seen include Crane, Tortoise, Beetle, Centipede leg count is 150 head count is 26 display solution }
  • 142. @TypeChecked def main() { animals seen include Crane, Tortoise, Beetle, Centipede leg count is 150 head count is 26 display solution } Logic programming example dslTyped/ChocoCraneTortoiseDSL.groovy 80 lines to define the DSL
  • 143. DSL Type Provider unresolvedVariable { var -> if (!cachedAnimalNames) { def accessKey = '72ddf45a-c751-44c7-9bca-8db3b4513347' // for illustrative purposes, just download xml for a few animals def uid = 'ELEMENT_GLOBAL.2.104550,ELEMENT_GLOBAL.2.105196,ELEMENT_GLOBAL.2.120227' def base = "https://services.natureserve.org/idd/rest/ns/v1.1/globalSpecies" def url = "$base/comprehensive?uid=$uid&NSAccessKeyId=$accessKey" def root = new XmlParser().parse(url) def names = root.globalSpecies.classification.names cachedAnimalNames = names.natureServePrimaryGlobalCommonName*.text()*.replaceAll(' ','') } if (var.name in cachedAnimalNames) { storeType(var, STRING_TYPE) handled = true enclosingClassNode.addField(var.name, 0, STRING_TYPE, new ConstantExpression(var.name)) } }
  • 144. DSL Type Provider @TypeChecked(extensions='NatureServeAnimalProvider.groovy') def main() { animals seen include SandhillCrane, GopherTortoise, ChihuahuanMillipede leg count is 1020 head count is 8 display solution } Custom checker provider/ChocoCraneTortoiseProvider.groovy 80 lines to define the DSL 25 lines to define the provider
  • 148. Groovy's Awesome Team +100's of others Direct downloads: 2013: approx. 3 million 2014: 4+ million 2015: 12+ million now: 2+ million/month
  • 149. Groovy's Awesome Team +100's of others just like YOU!
  • 150.
  • 151. http://www.manning.com/koenig2 Groovy in Action 2nd edition Manning promo code: ctwg3sum (39% off all Manning books) 152