Let’s groove with Groovy
-
Upload
thorsten-kamann -
Category
Technology
-
view
3.856 -
download
0
description
Transcript of Let’s groove with Groovy
Thorsten Kamann ● [email protected] 11
Thorsten Kamann ● [email protected] 22
Agenda
Was ist Groovy?
Getting started
Syntax
GroovyBeans
XML-Processing
Groovy Builder
Testing
Grails
Groovy Module
IDE-Support
Links
Thorsten Kamann ● [email protected] 33
• 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“)
Was ist Scripting?
Thorsten Kamann ● [email protected] 44
• 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
Was ist Groovy?
Thorsten Kamann ● [email protected] 55
Thorsten Kamann ● [email protected] 66
• 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
Getting started
Thorsten Kamann ● [email protected] 88
Getting started: Embedding
Java-Anwendung
Bean-Scripting-Framework
(BSF)
Groovy-Shell
Groovy-Classloader
Groovy ScriptEngine
Groovy Script
ANTMaven
Thorsten Kamann ● [email protected] 99
– Ist ein allgemeine Möglichkeit, jede beliebige Scriptsprache in Java-Anwendungen einzubinden
– Groovy bietet aber leichtgewichtigere und leistungsfähigere Möglichkeiten der Einbindung
Getting started: Embedding
Thorsten Kamann ● [email protected] 1010
– Groovy-Shell bietet die Möglichkeit des Ein- und Auslesens von Variablen mittels des Binding-Objekts
Getting started: Embedding
Binding binding = new Binding();
binding.setVariable("foo", new Integer(2));
GroovyShell shell = new GroovyShell(binding);
Object value = shell.evaluate(
"println 'Hello World!'; x = 123; return foo * 10");
assert value == 20;
assert binding.getVariable("x„) == 123;
Thorsten Kamann ● [email protected] 1111
– Lädt Groovy-Klassen dynamisch und ermöglicht den direkten Zugriff auf deren Methoden
Getting started: Embedding
ClassLoader parent = getClass().getClassLoader();
GroovyClassLoader loader = new
GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(
new File("script.groovy"));
GroovyObject groovyObject =
(GroovyObject) groovyClass.newInstance();
Object[] args = {};
groovyObject.invokeMethod("run", args);
Thorsten Kamann ● [email protected] 1212
– Lädt Groovy-Klassen dynamisch und ermöglicht den direkten Zugriff auf deren Methoden
Getting started: Embedding
GroovyClassLoader gcl = new GroovyClassLoader();
Class clazz = gcl.parseClass(
myStringwithGroovyClassSource,
"SomeName.groovy");
Object aScript = clazz.newInstance();
MyInterface myObject = (MyInterface) aScript;
myObject.interfaceMethod();
Thorsten Kamann ● [email protected] 1313
– Dies ist die leistungsfähige Möglichkeit, um Groovy-Skripte auszuführen.
Getting started: Embedding
String[] roots = new String[]
{"/my/groovy/script/path"};
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
Binding binding = new Binding();
binding.setVariable("input", "world");
gse.run("hello.groovy", binding);
System.out.println(binding.getVariable("output"));
Thorsten Kamann ● [email protected] 1414
– 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
Getting started: Embedding
Thorsten Kamann ● [email protected] 1515
– 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
Getting started: Embedding
Thorsten Kamann ● [email protected] 1616
– Groovy kann direkt von der Eingabeaufforderunggroovy script.groovy [arguments]
ausgeführt werden
– Alternativ kann über den Dialog Ordneroptionen-->Dateitypen die Extension *.groovy an groovy.bat gebunden werden.
Getting started: Embedding
Thorsten Kamann ● [email protected] 1717
– Groovy kann direkt von der Konsole mittelsgroovy 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
Getting started: Embedding
Thorsten Kamann ● [email protected] 1818
Thorsten Kamann ● [email protected] 1919
– Package-, Import-Mechanismus
– Class und Method Definition
– Kontrollstrukturen (ausser for(init;test,inc))
– Operatoren, Ausdrücke und Zuweisungen
– Exeption Handling
– Literale
– Instantiierung, Referenzen
Die Syntax: Groovy vs. Java
Thorsten Kamann ● [email protected] 2020
– 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
Die Syntax: Groovy vs. Java
Thorsten Kamann ● [email protected] 2121
– groovy.lang.*, groovy.util.*
– java.lang.*, java.util.*, java.net.*, java.io.*
– java.math.BigInteger, java.math.BigDecimal
Die Syntax: Groovy vs. Java
Thorsten Kamann ● [email protected] 2222
Die Syntax
assert(true)
assert 1 == 1
def x = 1
assert x == 1
def y=1; assert y == 1
Thorsten Kamann ● [email protected] 2323
– Alles ist ein Objekt
– Keine primitiven Datentypen
– Automatisches Wrapping (Boxing/Unboxing)
– Optionales Typing
– Statisches/Dynamisches Typing
Die Syntax: Datentypen
Thorsten Kamann ● [email protected] 2424
Die Syntax: Datentypen
Typ Beispiel
java.lang.Integer 15, 0x1234ffff
java.lang.Long 100L, 100l
java.lang.Float 1.23F, 1.23f
java.lang.Double 1.23D, 1.23d
java.math.BigInteger 123g, 456G
java.math.BigDecimal 1.23, 4.56, 1.4E4, 2.8e4, 1.23g, 1.23G
Thorsten Kamann ● [email protected] 2525
– Whole word Matcher
– Find Matcher
– Count
– Foreach
– Replace
– Split
Die Syntax: Datentypen
Thorsten Kamann ● [email protected] 2626
Die Syntax: Datentypen
//Finder
assert „Hello Groovy!“ =~ /o.G/
//Matcher
assert „Hello Groovy!“ ==~ /Hello\sGroovy\\!/
//Replace
assert „Hello Groovy!“.replaceAll(/Hello/, „Hi“)
== „Hi Groovy!“
//Split
assert „Hello Groovy!“.split(/ /).size == 2
Thorsten Kamann ● [email protected] 2727
– Basieren auf einfachen Strings
– Bieten allerdings eine erweiterte Funktionalität
– Sie müssen in doppelten Anführungszeichen definiert werden
– Unterstützen Platzhalter• ${expression}
• $expression
Die Syntax: Datentypen
Thorsten Kamann ● [email protected] 2828
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 ● [email protected] 2929
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 ● [email protected] 3030
Die Syntax: Datentypen
greeting = „Hello Groovy!“
assert greeting[0] == „H“
assert greeting [6..11] == „Groovy“
assert ‚Hi‘ + greeting – ‚Hello‘ == „Hi Groovy!“
assert greeting.count(„o“) = 3
assert „x“.padLeft(3) == „ x“
assert „x“.padRight(3) == „x „
assert „x“.center(3) == „ x „
assert „x“ * 3 == „xxx“
Thorsten Kamann ● [email protected] 3131
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 ● [email protected] 3232
– 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
Die Syntax: Datentypen (collective)
Thorsten Kamann ● [email protected] 3333
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 ● [email protected] 3434
Die Syntax: Datentypen (collective)
Map map = [:]
assert map.size == 0
map = [a:1, b:2,c:3]
assert map.size = 3
assert map.get(„a“) == 1
assert map[‚b‘] == 2
assert map.c == 3
map.e = 4
assert map.e == 4
Thorsten Kamann ● [email protected] 3535
– Expandos ermöglichen die Erzeugung von dynamischen Objekten
Die Syntax: Datentypen (collective)
def player = new Expando()
player.name = “Thorsten"
player.greeting = { "Hello, my name is $player.name" }
assert player.greeting() == "Hello, my name is Thorsten"
Thorsten Kamann ● [email protected] 3636
– 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
Die Syntax: Closures
Thorsten Kamann ● [email protected] 3737
Die Syntax: Closures
List list = [1, 2, 3]
list.each{ entry ->
println „entry $entry“
}
Ausgabe:
entry 1
entry 2
entry 3
Thorsten Kamann ● [email protected] 3838
Die Syntax: Closures
public void each(Closure closure){
for (it: listItems){
closure(it).call();
}
}
Thorsten Kamann ● [email protected] 3939
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 ● [email protected] 4040
– Transformiert eine Closure mit vielen Parametern in eine Closure mit weniger Parametern
– Dabei werden Parameter mit Werten vorbelegt
Die Syntax: Closures
def adder = {x, y -> return x+y}
def addOne = adder.curry(1)
assert addOne(5) == 6
Thorsten Kamann ● [email protected] 4141
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 ● [email protected] 4242
•
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 ● [email protected] 4343
•
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 ● [email protected] 4444
– Kann mit jedem Datentyp verwendet werden
Die Syntax: Kontrollstrukturen
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 ● [email protected] 4545
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 ● [email protected] 4646
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 ● [email protected] 4747
Die Syntax: Return/Break/Continue
Boolean someMethod(){
if (false){
return false
}
return true
}
Thorsten Kamann ● [email protected] 4848
Die Syntax: Return/Break/Continue
while (true){
if (someCondition){
break
}
}
Thorsten Kamann ● [email protected] 4949
Die Syntax: Return/Break/Continue
for(item in items){
if (someCondition){
continue
}
}
Thorsten Kamann ● [email protected] 5050
– Ähnliche Unterstützung wie in Java
• try-catch-finally
• try-catch
• try-finally
– Checked-Exception werden als Runtime-Excpetion hochgereicht
Die Syntax: Exception
Thorsten Kamann ● [email protected] 5151
– Identisch mit Klassen in Java
– Können Felder, Konstruktoren, Methoden enthalten
– Konstruktoren und Methoden können lokale Variablen verwenden
Die Syntax: OO und Groovy
Thorsten Kamann ● [email protected] 5252
– Lokale Variablen und Felder müssen deklariert werden
– Java Modifiers werden verwendet:
• private, protected, public, final, static
• Bei fehlendem Modifier wird eine Property erzeugt
Die Syntax: OO und Groovy
Thorsten Kamann ● [email protected] 5353
Die Syntax: OO und Groovy
def map = [a:[b:[c:1]]]
assert map.a.b.c == 1
try{
assert map a.x.c == null
}catch (NullPointerException npe){
}
assert map?.a.?x?.c == null
Fängt die NPE
Thorsten Kamann ● [email protected] 5454
Thorsten Kamann ● [email protected] 5555
– Sind wie JavaBeans
– Getter/Setter werden zur Laufzeit erzeugt
– Event-Support wird mit vereinfachten Methoden ermöglicht
Groovy Beans
Thorsten Kamann ● [email protected] 5656
Groovy Beans
Customer.groovy:class Customer {
int idString name
}
Customer.java:public class Customer {private int id = 0;private String name;
public int getId(){return id;
} public void setId(int id){
this.id = id;}...
}
Thorsten Kamann ● [email protected] 5757
– Wenn eine Property als private gekennzeichnet
ist, wird ein Java Field benutzt, um diese Property zu repräsentieren
Groovy Beans
Thorsten Kamann ● [email protected] 5858
– 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
Groovy Beans
Thorsten Kamann ● [email protected] 5959
– 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
Groovy Beans
Thorsten Kamann ● [email protected] 6060
– Mit selbst deklarierten Getter- und Setter-Methoden können die von der Groovy-Runtimegenerierten Methoden überschrieben werden
Groovy Beans
Thorsten Kamann ● [email protected] 6161
Groovy Beans
Groovy:def button = new JButton(Push me!”)
button.actionPerformed = {event ->println button.text
}
Java:final JButton button =
new Jbutton(„Push me!“);button.addEventListener(
new IActionListener(){public void actionPerformed(
ActionEvent event){System.out.println(button.getText());
}});
Thorsten Kamann ● [email protected] 6262
Thorsten Kamann ● [email protected] 6363
XML-Processing
XML-Support
Edit
XML-Parser
XMLSlurper
DOMCategroy
Create
MarkupBuilder
NodeBuilder
DOM StAX DOM4J JAXEN
SAX XOM JDOM XPATH
DOM4JDOM
XOM JDOM
Thorsten Kamann ● [email protected] 6464
– 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
XML-Processing
Thorsten Kamann ● [email protected] 6565
XML-Processing
DOM Element Expression Beschreibung
Element .elementName.„elementName„
Alle Kindelemente mit dem angegebenen Namen
Element [index] Kindelement mit dem [index]
Element .@attrName.„@attrName„.[„@attrName„]
Attribut mit den angebenen Namen
Element .name() Name des aktuellen Elements
Element .parent() Das Elternelement
Element .text() Der Textinhalt des Elements
Thorsten Kamann ● [email protected] 6666
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 ● [email protected] 6767
Thorsten Kamann ● [email protected] 6868
– Groovy bietet Unterstützung für die Arbeit mit Baumartige Strukturen:
• XML, HTML, Ant Tasks, Swing UI's, SWT UI„s
Groovy Builder
XML HTML ANT Swing SWTYour
Builder
GroovyObjectSupport
BuilderSupport
Thorsten Kamann ● [email protected] 6969
– eine einheitliche Schnittstelle
• Elemente sind Closures
• Attribute sind Maps
– Vollständige Integration anderer Groovy-Features
• Collections
• Arrays
• Conditions
• ...
Groovy Builder
Thorsten Kamann ● [email protected] 7070
Groovy Builder
builder = new
MarkupBuilder(writer)
builder.person() {
name(first:“Thorsten",
last:“Kamann") {
age("34")
}
}
<person>
<name first=“Thorsten“
last=“Kamann“>
<age>34</age>
</name>
</person>
Thorsten Kamann ● [email protected] 7171
Groovy Builder
def writer = new FileWriter(“markup.html“)
def html = new groovy.xml.MarkupBuilder(writer)
html.html{
head{
title ‘Hello Groovy!‘
}
body{
h1 ‘Hello Groovy‘
p(style:‘font-weight: bold;‘,
‘This is built by Groovy.‘)
}
}
Thorsten Kamann ● [email protected] 7272
Groovy Builder
Thorsten Kamann ● [email protected] 7373
Groovy Builder
def ant = new groovy.util.AntBuilder()
ant.mkdir(dir:myDir)
ant.copy(todir:myDir) {
fileset(dir:"src/test") {
include(name:"**/*.groovy")
}
}
Thorsten Kamann ● [email protected] 7474
Groovy Builder
def swing = new groovy.swing.SwingBuilder()
def frame = swing.frame(title:'Password'){
passwordField(columns:30, actionPerformed: {event ->
println event.source.text
System.exit(0)
})
}
frame.pack()
frame.show()
Thorsten Kamann ● [email protected] 7575
Groovy Builder
Thorsten Kamann ● [email protected] 7676
Groovy Builder
bb = new grails.spring.BeanBuilder()
bb.beans{
CustomerService(org.x.y.z.CustomerServiceImpl){
customerDao = CustomerDao
}
CustomerDao(org.x.y.z.CustomerDaoImpl){
sessionFactory = MySessionFactory
}
ApplicationContext context =
bb.createApplicationContext()
}
Thorsten Kamann ● [email protected] 7777
Thorsten Kamann ● [email protected] 7878
Testing
Groovy Testing
Unit
TPTP
Mocks
Stubs
UI-Test Webservice-TestCoverage
jUnit Corbertura
Canoo WebtestHTML Unit
SoapUI
Thorsten Kamann ● [email protected] 7979
– jUnit ist in der Groovy-Runtime verankert
– Zusätzliche Assert-Statements
– Leicht integrierbar mit Ant und Maven
– Groovy liefert auch Groovy Mocks
Testing
Thorsten Kamann ● [email protected] 8080
Testing
assertArrayEquals(Object[] expected, Object[] value)
assertLength(int length, char[] array)
assertLength(int length, int[] array)
assertLength(int length, Object[] array)
assertContains(char expected, char[] array)
assertContains(int expected, int[] array)
assertToString(Object value, String expected)
assertInspect(Object value, String expected)
assertScript(final String script)
shouldFail(Closure code)
shouldFail(Class clazz, Closure code)
Thorsten Kamann ● [email protected] 8181
Testing
import groovy.mock.interceptor.MockFor
def mocker = new MockFor(Collaborator.class)
mocker.demand.one(1..2) { 1 }
mocker.demand.two() { 2 }
mocker.use {
def caller = new Caller()
assertEquals 1, caller.collaborateOne()
assertEquals 1, caller.collaborateOne()
assertEquals 2, caller.collaborateTwo()
}
Thorsten Kamann ● [email protected] 8282
– 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)
Testing
Thorsten Kamann ● [email protected] 8383
Thorsten Kamann ● [email protected] 8484
– MVC-Framework
• Basierend auf Spring-MVC und Hibernate
– JSP oder GSP
– Einfache AJAX-Integration
– Sehr performant
– Integrierter Job-Scheduler
Grails
Thorsten Kamann ● [email protected] 8585
– Domänenklassen (mit GORM)
– Controller
– Services
– Jobs
– CRUD-Anwendung in No-Time
– AJAX (Dojo, Yahoo, Scriptacolous, Prototype)
– Vollständig integriert
Grails
Thorsten Kamann ● [email protected] 8686
Thorsten Kamann ● [email protected] 8787
Groovy Module
class Client{
String name
String email
Address address
static hasMany = [orders: Order]
static constraints = {
name(blank:false,size:5..20)
email(email:true)
}
}
Einfache Properties
1:* Beziehungstatic belongsTo=Client
Constraints
1:1 Beziehung
Thorsten Kamann ● [email protected] 8888
Groovy Module
Thorsten Kamann ● [email protected] 8989
Thorsten Kamann ● [email protected] 9090
– Assistenten für Groovy-Klassen und –Unittests
– Komplette Integration in Eclipse
– Syntax-Coloring
– Syntax-Checking
– Word-Completion
– Duck-Typing
IDE-Support
Thorsten Kamann ● [email protected] 9191
IDE-Support
Instance variable completion
Method completion asGroovy Properties
Complexcompletion
Thorsten Kamann ● [email protected] 9393
Thorsten Kamann ● [email protected] 9494
Links und Ressourcen
Groovy in Actionvon Dierk Koenig, Andrew Glover, Paul King, Guillaume Laforge
- Taschenbuch: 696 Seiten- Verlag: Manning (Januar 2007)- Sprache: Englisch- ISBN-10: 1932394842- ISBN-13: 978-1932394849
Thorsten Kamann ● [email protected] 9595
• Groovy Webseitehttp://groovy.codehaus.org/
• Groovy Series Podcasthttp://groovy.codehaus.org/Groovy+Series
• Groovy Blogshttp://www.groovyblogs.org/
• Webseite des Referenten (Blog, Wiki)http://www.thorsten-kamann.de
Links und Ressourcen
Thorsten Kamann ● [email protected] 9696