Java 6 bietet Scripting-Support out-of-the-Box. Mit Groovy existiert eine Scriptsprache, die sich eng an Java anlehnt und reichlich Gebrauch der Java-Infrastruktur macht. Grund genug Groovy einmal genauer unter die Lupe zu nehmen.
Thorsten Kamann wird in seinem Vortrag die Grundkonzepte vorstellen. Anhand von einfachen Beispielen zeigt er die Mächtigkeit und Eleganz dieser Scriptsprache auf. Im 2. Teil des Vortrags geht er auf erweiterte Konzepte und Komponenten von Groovy ein.
Themen werden u.a. sein:
* Installation
* Syntax - Schleifen
* Bedingungen
* Closures
* GStrings
* Regex
* GroovyBeans
* GroovyBuilder
o XML
o HTML
o ANT
o Swing
o SWT
* Unit-Tests (jUnit, Stubs, Mocks, Code-Coverage,…)
* Weitere Groovy-Komponenten
* Grails
2. Agenda
Was ist Groovy? Testing
Getting started Grails
Syntax Groovy Module
GroovyBeans IDE-Support
XML-Processing Links
Groovy Builder
Thorsten Kamann ● thorsten.kamann@itemis.de 2
3. Was ist Scripting?
• Skriptsprachen sind Programmiersprachen, die vor
allem für kleine, überschaubare
Programmieraufgaben gedacht sind
• Kein Deklarationszwang für Variablen
• Automatische Speicherverwaltung
• Werden in der Regel ohne getrennte
Übersetzungsphase ausgeführt (d. h. sie werden
„interpretiert“)
Thorsten Kamann ● thorsten.kamann@itemis.de 3
4. Was ist Groovy?
• Eine dynamische Sprache
• Inspiriert von Ruby, Python, Smalltalk
• Entwickelt für die Java-Plattform
– Um sie Java-Entwicklern zugänglich zu machen
– Um möglichst viel der Java-Syntax wieder
verwenden zu können
– Um eine einfache Anbindung zu Enterprise-
Systemen anzubieten
Thorsten Kamann ● thorsten.kamann@itemis.de 4
6. Getting started
• Download des aktuellen Release von
http://groovy.codehaus.org
• Entpacken des Archivs
• Setzen der Umgebungsvariable GROOVY_HOME
• Hinzufügen von %GROOVY_HOME%bin zur PATH-
Variable
• Starten von groovyConsole und Eingabe von
println „Hallo Welt“
mit anschliessendem STRG-R
Thorsten Kamann ● thorsten.kamann@itemis.de 6
9. Getting started: Embedding
– Ist ein allgemeine Möglichkeit, jede beliebige
Scriptsprache in Java-Anwendungen einzubinden
– Groovy bietet aber leichtgewichtigere und
leistungsfähigere Möglichkeiten der Einbindung
Thorsten Kamann ● thorsten.kamann@itemis.de 9
10. Getting started: Embedding
– Groovy-Shell bietet die Möglichkeit des Ein- und
Auslesens von Variablen mittels des Binding-
Objekts
Binding binding = new Binding();
binding.setVariable(quot;fooquot;, new Integer(2));
GroovyShell shell = new GroovyShell(binding);
Object value = shell.evaluate(
quot;println 'Hello World!'; x = 123; return foo * 10quot;);
assert value == 20;
assert binding.getVariable(quot;x„) == 123;
Thorsten Kamann ● thorsten.kamann@itemis.de 10
11. Getting started: Embedding
– Lädt Groovy-Klassen dynamisch und ermöglicht
den direkten Zugriff auf deren Methoden
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new
GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(
new File(quot;script.groovyquot;));
GroovyObject groovyObject =
(GroovyObject) groovyClass.newInstance();
Object[] args = {};
groovyObject.invokeMethod(quot;runquot;, args);
Thorsten Kamann ● thorsten.kamann@itemis.de 11
12. Getting started: Embedding
– Lädt Groovy-Klassen dynamisch und ermöglicht
den direkten Zugriff auf deren Methoden
GroovyClassLoader gcl = new GroovyClassLoader();
Class clazz = gcl.parseClass(
myStringwithGroovyClassSource,
quot;SomeName.groovyquot;);
Object aScript = clazz.newInstance();
MyInterface myObject = (MyInterface) aScript;
myObject.interfaceMethod();
Thorsten Kamann ● thorsten.kamann@itemis.de 12
13. Getting started: Embedding
– Dies ist die leistungsfähige Möglichkeit, um
Groovy-Skripte auszuführen.
String[] roots = new String[]
{quot;/my/groovy/script/pathquot;};
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
Binding binding = new Binding();
binding.setVariable(quot;inputquot;, quot;worldquot;);
gse.run(quot;hello.groovyquot;, binding);
System.out.println(binding.getVariable(quot;outputquot;));
Thorsten Kamann ● thorsten.kamann@itemis.de 13
14. Getting started: Embedding
– ANT-Task, mit dem eine beliebige Anzahl von
Groovy-Skripten ausgeführt werden kann
– GroovyC-Task, der Groovy-Skripte (Klassen) zu
Java Bytecode kompiliert
– Erstellen von Ant-Tasks mit Groovy und dem
Ant-Builder
– Erzeugen von Ant-Skripten
Thorsten Kamann ● thorsten.kamann@itemis.de 14
15. Getting started: Embedding
– Unterstützung mittels des M2-Ant-Plugins
– Auf http://mojo.codehaus.org/ existieren bereits Maven-
Tools für direkte Unterstützung von Groovy:
• Groovy-Compiler
• Groovy-Archetype
• Tools, um Maven-Plugins mit Groovy zu entwickeln
Thorsten Kamann ● thorsten.kamann@itemis.de 15
16. Getting started: Embedding
– Groovy kann direkt von der Eingabeaufforderung
groovy script.groovy [arguments]
ausgeführt werden
– Alternativ kann über den Dialog
Ordneroptionen-->Dateitypen die Extension
*.groovy an groovy.bat gebunden werden.
Thorsten Kamann ● thorsten.kamann@itemis.de 16
17. Getting started: Embedding
– Groovy kann direkt von der Konsole mittels
groovy script.groovy [arguments]
ausgeführt werden
– Alternativ kann in die 1. Zeile eines Groovy-Skripts
#!/usr/bin/env groovy
eingefügt werden.
– So kann mit
chmod +x script.groovy
./script.groovy
das Skript ausgeführt werden
Thorsten Kamann ● thorsten.kamann@itemis.de 17
19. Die Syntax: Groovy vs. Java
– Package-, Import-Mechanismus
– Class und Method Definition
– Kontrollstrukturen (ausser for(init;test,inc))
– Operatoren, Ausdrücke und Zuweisungen
– Exeption Handling
– Literale
– Instantiierung, Referenzen
Thorsten Kamann ● thorsten.kamann@itemis.de 19
20. Die Syntax: Groovy vs. Java
– Vereinfachter Zugriff auf Java-Objekte mit neuen
Ausdrücken und Operatoren
– Zusätzliche Möglichkeiten, um Objekte zu
erstellen
– Neue Konstrollstrukturen
– Neue Datentypen
– Alles ist ein Objekt
Thorsten Kamann ● thorsten.kamann@itemis.de 20
22. Die Syntax
assert(true)
assert 1 == 1
def x = 1
assert x == 1
def y=1; assert y == 1
Thorsten Kamann ● thorsten.kamann@itemis.de 22
23. Die Syntax: Datentypen
– Alles ist ein Objekt
– Keine primitiven Datentypen
– Automatisches Wrapping (Boxing/Unboxing)
– Optionales Typing
– Statisches/Dynamisches Typing
Thorsten Kamann ● thorsten.kamann@itemis.de 23
27. Die Syntax: Datentypen
– Basieren auf einfachen Strings
– Bieten allerdings eine erweiterte Funktionalität
– Sie müssen in doppelten Anführungszeichen
definiert werden
– Unterstützen Platzhalter
• ${expression}
• $expression
Thorsten Kamann ● thorsten.kamann@itemis.de 27
28. Die Syntax: Datentypen
me = „Thorsten“
age = 34
location = „Neuss“
line = „Ich heisse $name, bin $age und wohne in $location“
assert line == „Ich heisse Thorsten, bin 34 und wohne in
Neuss“
assert line instancof java.lang.String
Thorsten Kamann ● thorsten.kamann@itemis.de 28
29. Die Syntax: Datentypen
Start/End Zeichen Beispiel GString? Backslash?
Einfache Anführungszeichen ‚Hallo Thorsten„
Doppelte Anführungszeichen „Hallo $name“
Dreifache Anführungszeichen „„„----------------
Total: $0.02
---------------„„„
Dreifache doppelte “““---------------
Anführungszeichen Line with text
--------------“““
Forward Slash /x(d*)y/
Thorsten Kamann ● thorsten.kamann@itemis.de 29
31. Die Syntax: Datentypen (collective)
List list = []
assert list.size == 0
list = [‚a‘, ‚b‘, ‚c‘]
assert list.size == 3 && list[1] = ‚b‘
list << ‚d‘
assert list.size == 4
list += ‚e‘
assert list.size == 5
assert list – ‚d‘ == [‚a‘, ‚b‘, ‚c‘, ‚e‘]
Thorsten Kamann ● thorsten.kamann@itemis.de 31
32. Die Syntax: Datentypen (collective)
– Sind Listen mit einem definierten Anfangs- und
Endwert
– Nahezu jedes Objekt kann in einer Range
verwaltet werden
• Methoden next und previous müssen implementiert
werden
• Das Interface java.lang.Comparable muss
implementiert werden
Thorsten Kamann ● thorsten.kamann@itemis.de 32
33. Die Syntax: Datentypen (collective)
def range = 0..10
assert range.contains(0)
assert range.contains(10)
range = 0..<10
assert range.contains(0)
assert !range.contains(10)
Thorsten Kamann ● thorsten.kamann@itemis.de 33
35. Die Syntax: Datentypen (collective)
– Expandos ermöglichen die Erzeugung von
dynamischen Objekten
def player = new Expando()
player.name = “Thorstenquot;
player.greeting = { quot;Hello, my name is $player.namequot; }
assert player.greeting() == quot;Hello, my name is Thorstenquot;
Thorsten Kamann ● thorsten.kamann@itemis.de 35
36. Die Syntax: Closures
– Codeblöcke
– Können einen Wert/Objekt zurückgeben
– Referenzieren und verwenden Variablen
– call()(implizit/explizit) führt die Closure aus
– Können an eine Variable gebunden werden
– Ähneln Java Inner Classes
Thorsten Kamann ● thorsten.kamann@itemis.de 36
37. Die Syntax: Closures
List list = [1, 2, 3]
list.each{ entry ->
println „entry $entry“
}
Ausgabe:
entry 1
entry 2
entry 3
Thorsten Kamann ● thorsten.kamann@itemis.de 37
38. Die Syntax: Closures
public void each(Closure closure){
for (it: listItems){
closure(it).call();
}
}
Thorsten Kamann ● thorsten.kamann@itemis.de 38
39. Die Syntax: Closures
Class MethodClosureSample(){
boolean validate(String value){
return StringUtils.isNotEmpty(value);
}
}
MethodClosureSample sample = new MethodeClosureSample()
List success = [„Hello“, „World“, „!“]
List fails = [„Hello“, „“, „World“, „!“]
assert success.each(sample.&validate)
assert !fails.each(sample.&validate)
Thorsten Kamann ● thorsten.kamann@itemis.de 39
40. Die Syntax: Closures
– Transformiert eine Closure mit vielen Parametern
in eine Closure mit weniger Parametern
– Dabei werden Parameter mit Werten vorbelegt
def adder = {x, y -> return x+y}
def addOne = adder.curry(1)
assert addOne(5) == 6
Thorsten Kamann ● thorsten.kamann@itemis.de 40
41. Die Syntax: Closures
Closure Beschreibung
collect Sammelt Objekte und fügt sie in eine neue Liste ein
each Führt für jedes Element aus
find Findet ein Element
findAll Findet alle Elemente anhand von Kriterien
min(Comparator) Gibt den min. Wert aus der Collection zurück
max(Comparator) Gibt den max. Wert aus der Collection zurück
sort(Comparator) Sortiert die Collection (Comparator ist optional)
unique Entfernt doppelte Werte aus der Collection
Thorsten Kamann ● thorsten.kamann@itemis.de 41
42. Die Syntax: Kontrollstrukturen
•
Runtime type Evaluation criterion required for truth
Boolean Booleanwert muss true sein
Matcher Der reguläre Ausdruck muss mindestens 1 Treffer haben
Collection Die Collection darf nicht leer sein
Map Die Map darf nicht leer sein
String Der String darf ebenfalls nicht leer sein
Number Muss ungleich 0 sein
Alles andere Die Objektreferenz muss ungleich null sein
Thorsten Kamann ● thorsten.kamann@itemis.de 42
43. Die Syntax: If-Statement
•
If (true) assert true
Else assert false
If (1){ assert true
}else{ assert false
}
If (0) assert false
Else if (1) assert true
Else assert false
(1 > 0)? assert true: assert False
Thorsten Kamann ● thorsten.kamann@itemis.de 43
44. Die Syntax: Kontrollstrukturen
– Kann mit jedem Datentyp verwendet werden
switch (10){
case 0 : assert false; break;
case 0..9 : assert false; break;
case [8,9,11] : assert false; break;
case Float : assert false; break;
case {it%3==0} : assert false; break;
case ~/../ : assert true; break;
default : assert false; break;
}
Thorsten Kamann ● thorsten.kamann@itemis.de 44
45. Die Syntax: Looping
def list = [1, 2, 3, 4, 5]
while (list){
list.remove()
}
assert list == []
while (list.size() < 3){
list << list.size()+1
}
assert list == [1, 2, 3]
Thorsten Kamann ● thorsten.kamann@itemis.de 45
46. Die Syntax: Looping
for (String i in ‘a‘..‘c‘) store += i
assert store == ‘abc‘
for (i in [1, 2, 3]){ store += i}
assert store == ‘123‘
def myString = ‘Hello Groovy!‘
for (i in 0..myString.size()){ store += myString[i]}
assert store == myString
Entspricht dem Java Equivalent:
for (int i=0;i<upperBound;i++){}
Thorsten Kamann ● thorsten.kamann@itemis.de 46
47. Die Syntax: Return/Break/Continue
Boolean someMethod(){
if (false){
return false
}
return true
}
Thorsten Kamann ● thorsten.kamann@itemis.de 47
49. Die Syntax: Return/Break/Continue
for(item in items){
if (someCondition){
continue
}
}
Thorsten Kamann ● thorsten.kamann@itemis.de 49
50. Die Syntax: Exception
– Ähnliche Unterstützung wie in Java
• try-catch-finally
• try-catch
• try-finally
– Checked-Exception werden als Runtime-
Excpetion hochgereicht
Thorsten Kamann ● thorsten.kamann@itemis.de 50
51. Die Syntax: OO und Groovy
– Identisch mit Klassen in Java
– Können Felder, Konstruktoren, Methoden
enthalten
– Konstruktoren und Methoden können lokale
Variablen verwenden
Thorsten Kamann ● thorsten.kamann@itemis.de 51
52. Die Syntax: OO und Groovy
– Lokale Variablen und Felder müssen deklariert
werden
– Java Modifiers werden verwendet:
• private, protected, public, final, static
• Bei fehlendem Modifier wird eine Property erzeugt
Thorsten Kamann ● thorsten.kamann@itemis.de 52
55. Groovy Beans
– Sind wie JavaBeans
– Getter/Setter werden zur Laufzeit erzeugt
– Event-Support wird mit vereinfachten Methoden
ermöglicht
Thorsten Kamann ● thorsten.kamann@itemis.de 55
56. Groovy Beans
Customer.groovy: Customer.java:
class Customer { public class Customer {
int id private int id = 0;
String name private String name;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
...
}
Thorsten Kamann ● thorsten.kamann@itemis.de 56
57. Groovy Beans
– Wenn eine Property als private gekennzeichnet
ist, wird ein Java Field benutzt, um diese Property
zu repräsentieren
Thorsten Kamann ● thorsten.kamann@itemis.de 57
58. Groovy Beans
– Wenn eine Property als public oder protected
gekennzeichnet wird, werden Getter- und Setter-
Methoden mit der gleichen Sichtbarkeit und ein
Feld mit der Sichtbarkeit private auf Bytecode-
Ebene erzeugt
Thorsten Kamann ● thorsten.kamann@itemis.de 58
59. Groovy Beans
– Wenn keine Getter- oder Setter-Methoden für
Properties mit der Sichtbarkeit public oder
protected deklariert wurden, werden fehlende
Getter- und Setter-Methoden mit der gleichen
Sichtbarkeit automatisch auf Bytecode-Ebene
erzeugt
Thorsten Kamann ● thorsten.kamann@itemis.de 59
60. Groovy Beans
– Mit selbst deklarierten Getter- und Setter-
Methoden können die von der Groovy-Runtime
generierten Methoden überschrieben werden
Thorsten Kamann ● thorsten.kamann@itemis.de 60
61. Groovy Beans
Groovy: Java:
def button = new JButton(Push me!”) final JButton button =
new Jbutton(„Push me!“);
button.actionPerformed = {event -> button.addEventListener(
println button.text new IActionListener(){
} public void actionPerformed(
ActionEvent event){
System.out.println(
button.getText());
}
});
Thorsten Kamann ● thorsten.kamann@itemis.de 61
63. XML-Processing
XML-Support
Edit Create
XML-Parser MarkupBuilder
XMLSlurper NodeBuilder
DOMCategroy
DOM StAX DOM4J JAXEN DOM DOM4J
SAX XOM JDOM XPATH XOM JDOM
Thorsten Kamann ● thorsten.kamann@itemis.de 63
64. XML-Processing
– Groovy bietet reichhaltige Unterstützung für das
XML-Processing
– GPath (Xpath) Ausdrücke erlauben schnelle
Navigation im XML-Dokument
– DOMCategory stellt mächtige
Navigationselemente zur Verfügung
Thorsten Kamann ● thorsten.kamann@itemis.de 64
65. XML-Processing
DOM Element Expression Beschreibung
Element .elementName Alle Kindelemente mit dem
.„elementName„ angegebenen Namen
Element [index] Kindelement mit dem [index]
Element .@attrName Attribut mit den angebenen Namen
.„@attrName„
.[„@attrName„]
Element .name() Name des aktuellen Elements
Element .parent() Das Elternelement
Element .text() Der Textinhalt des Elements
Thorsten Kamann ● thorsten.kamann@itemis.de 65
66. XML-Processing
//XML-Parser
def xml = new XmlParser().parseText(SOME_XML_TEXT)
//XML-Slurper
def xml = new XmlSlurper().parseText(SOME_XML_TEXT)
//DOMCategory
def reader = new StringReader(SOME_XML_TEXT)
def doc = DOMBuilder.parse(reader)
def records = doc.documentElement
use (DOMCategory) {
//do something
}
Thorsten Kamann ● thorsten.kamann@itemis.de 66
68. Groovy Builder
– Groovy bietet Unterstützung für die Arbeit mit
Baumartige Strukturen:
• XML, HTML, Ant Tasks, Swing UI's, SWT UI„s
Your
XML HTML ANT Swing SWT
Builder
GroovyObjectSupport
BuilderSupport
Thorsten Kamann ● thorsten.kamann@itemis.de 68
69. Groovy Builder
– eine einheitliche Schnittstelle
• Elemente sind Closures
• Attribute sind Maps
– Vollständige Integration anderer Groovy-Features
• Collections
• Arrays
• Conditions
• ...
Thorsten Kamann ● thorsten.kamann@itemis.de 69
78. Testing
Groovy Testing
TPTP
Unit Coverage UI-Test Webservice-Test
jUnit Corbertura
SoapUI
Mocks HTML Unit Canoo Webtest
Stubs
Thorsten Kamann ● thorsten.kamann@itemis.de 78
79. Testing
– jUnit ist in der Groovy-Runtime verankert
– Zusätzliche Assert-Statements
– Leicht integrierbar mit Ant und Maven
– Groovy liefert auch Groovy Mocks
Thorsten Kamann ● thorsten.kamann@itemis.de 79
82. Testing
– Resourcen (*.xml, Spring) können zur Laufzeit
erzeugt werden
– Zugriffe auf private Java-Ressourcen sind
einfacher (kein Reflection)
– Stubs und Mocks sind einfacher
– 100%ige Integration in den Buildprozess (Ant,
Maven)
Thorsten Kamann ● thorsten.kamann@itemis.de 82