2007 09 10 fzi training groovy grails v ws
DESCRIPTION
2-3 hour introduction to GROOVY and GRAILS given on Sep 10, 2007 for an internal tech talk at the FZI, GermanyTRANSCRIPT
1 R. Volz - Groovy & Grails
Groovy & Grails Lightning Talk
Raphael Volz
Sep. 10, 2007
FZI, Karlsruhe
Builds on content from the following presentations
Rod Cope and James StrachanThe Groovy Programming LanguagePresentation held at JavaOne 2004
Graeme RocherRapid Web Application Development with GrailsPresentation held at JavaOne 2006
2 R. Volz - Groovy & Grails
Agenda
Why should I care ?
Get Groovy
Find Grails
3 R. Volz - Groovy & Grails
Why should I care ?
40-60%User Interface
40-60%Functionality
Software Development Effort
Variance Max. 20 %User Interface
Min. 80%Functionality
Focus :Users Great Interface
Developer Gigantic Functionality
Typically Research
… try to be efficientin programming efforts …
... try to be efficientin UI efforts...
4 R. Volz - Groovy & Grails
Efficiency Problems in Web Development
Many repetitive tasks Consider example data flow:
Database – Object Representation – Presentation HTML
Different structure of individual applications Hard to understand Hard to maintain
Difficulty to get started Many concepts at once:
HTML, XML, SQL, JavaScript, Programming Languages …
Need: Simplification Standardization Capture “Best Practices”
5 R. Volz - Groovy & Grails
Java’s biggest strengths in Web development ?
VM and Binary Compatibility We can build deployment units (class, jar, jnlp, war, ear, rar, car) and
run them anywhere We can easily reuse libraries, APIs and tools
e.g. high quality BPM, SemWeb, Market APIs
Lots of reusable software & components & tools We can innovate at the source code level if we play nice at
the binary level
6 R. Volz - Groovy & Grails
Problems with Java in Web Dev’t
Verbose Many import statements Try… Catch Nightmare …
Static Compile Cycle prevents necessary agility
Language Concepts (in my opinion) slow to embrace “modern” concepts … … many of which are helpful for Web Development
7 R. Volz - Groovy & Grails
Agenda
Why should I care ?
Get Groovy
Find Grails
8 R. Volz - Groovy & Grails
Get Groovy – An agile dynamic language for Java
Integrates with Java Can call Java Can be called by Java Compiles to Java byte code
Simplifies syntax of java Adds modern language features from
Python, Ruby, Dylan and Smalltalk to Java Supports DSL (domain specific languages)
to compact syntax and increase readability Reduces scaffolding code (Web, GUI, database) Simplifies testing (mocks up out-of-the-box)
9 R. Volz - Groovy & Grails
Groovy // Simplifying Java Syntax (1)
Feature Java Groovy
Semicolon after statement
MUST OPTIONAL
Brackets with method calls
MUST OPTIONAL
Typing of variables MUST OPTIONAL
Default scope PRIVATE PUBLIC
Imports Declare all imports Automatically imports groovy.lang.* groovy.util.* java.lang.* java.util.* java.net.* java.io.* java.math.BigInteger java.math.BigDecimal
10 R. Volz - Groovy & Grails
Groovy // New features beyond Java
Everything is an object Groovy Beans
Automatically generates get/set methods Uses these methods when attributes are read
Simple Notation of lists and (hash) maps Closures - Objects with executable code Operator overloading Extended Switch
11 R. Volz - Groovy & Grails
Println “Hello World”
Groovy // Hello World
Java
public class HelloWorld {
public static void main (String[] args) {
System.out.println( “Hello World”);
}
}
Groovy
println “Hello World”
Simplifications applied1. Public optional
2. Type information optional
3. Every Class knows “println”
4. Script needs no class and main method context
5. Semicolon optional
6. Brackets are optional when calling methods
class HelloWorld {static void
main (String[] args) { System.out.println( “Hello World”);}
}
class HelloWorld {static main (args) { System.out.println( “Hello World”);}
}
class HelloWorld { static main (args) {
println(“Hello World”); }}
println(“Hello World”); Println “Hello World”
12 R. Volz - Groovy & Grails
Groovy // Closures : Blocks of code as objects
def c = { println "hello" }c()
square = { x -> x * x }assert square(2) == 4
square = { it * it }
3.times { println "hoch!" }
def sum = 01.upto(5) { sum += it }assert sum == 15
Use to substitute repeated code blocks
Closure with parameter
Closure with default parameter "it" does not require return
Times function
upto function
Remember LISP ?
... pass around as references, store, execute at arbitratry time
... similar to anonymous inner classes, but nicer syntax and more flexible
13 R. Volz - Groovy & Grails
Groovy // Calling Java APIS
10 liner to get "Google Patent Search" results via HTMLUnit
1 import com.gargoylesoftware.htmlunit.WebClient
2 def searchTerm = 'Robot'
// Patent Search with Google
3 def client = new WebClient()
4 def page = client.getPage('http://www.google.com/patents')
5 def input = page.forms[0].getInputByName('q')
6 input.valueAttribute = searchTerm
7 page = page.forms[0].submit()
8 def results = page.anchors.grep { it.classAttribute == 'big' }
9 results.each {
10 println it.hrefAttribute.padRight(30) + ' : ' + it.asText() }
Closure
14 R. Volz - Groovy & Grails
Groovy // Everything is an object
def i = 1
assert i == new Integer (1)
def k = iassert i.is(k)assert !(i.is(new Integer(i)))
No primitive datatypes Int, short byte, long real objects
== is equals() Checks equality of objects
is() checks identity of objects
Very, very usefulwhen writing test code !!!
16 R. Volz - Groovy & Grails
Groovy // Simplified List Handling
def list = [1,2,3]assert list[0] == 1assert list[-1] == 3assert list[1..2] == [2,3]
assert list + [4,5] == [1,2,3,4,5]assert list << 9 == [1,2,3,9]
assert [1,2,3] - [2] == [1,3]assert [1,2] * 2 == [1,2,1,2]
def sum = 0for (i in list) sum+= iasset sum == 6
Simplified addressing of list elements avoids calls to len()
Simplied modification of lists
Simplified iteration
17 R. Volz - Groovy & Grails
Groovy // List Handling Example
public class Filter { public static void main( String[] args ) { List list = new java.util.ArrayList(); list.add( "Rod" ); list.add( "James" ); list.add( "Chris" ); Filter filter = new Filter(); List shorts = filter.filterLongerThan( list, 4 ) for ( String item : shorts ) { System.out.println( item ); } } public List filterLongerThan( List list, int length ) { List result = new ArrayList(); for ( String item : list ) { if ( item.length() <= length ) { result.add( item ); } } return result; }}
Select all names with at most 3 characters from a list
Groovy
Java
list = ["Rod", "James", "Chris"]shorts = list.findAll { it.size() <= 4 }shorts.each { println it }
18 R. Volz - Groovy & Grails
Groovy // Ranges and Maps
def sum = 0for (i in 1..10) sum += iassert sum ==55
map = ['rod' : 33, 'james' : 35]assert map['rod'] == map.rod
map.joe = 28 assert map == ['rod':33, 'james':35, 'joe':28]
assert map.subMap(['rod', 'joe']) == ['rod':33, 'joe':28]
19 R. Volz - Groovy & Grails
Basic Sorting
list = [ 'dog', 'bird', 'chick' ] println( list.sort() )
-> [bird, chick, dog] println( list.sort { it.size() }.reverse() )
-> [chick, bird, dog]
20 R. Volz - Groovy & Grails
Sorting JavaBeans
class Person { name; age }list = [ new Person( name:'Rod', age:33 ),
new Person( name:'James', age:35 ) ]list.sort { | person | person.age }list.sort { [ it.name, it.age ] }list.sort { | a, b | a.name <=> b.name }println( list.sort{it.name}.name )
-> [James, Rod]println(list.sort{it.name}.name.join(':'))
-> "James:Rod"
21 R. Volz - Groovy & Grails
Groovy // Operator Overloading
Maps Operators to Methods Can be implemented by any class and subsequently used Operator Name Method
a+b plus a.plus(b)a-b minus a.minus(b)a*b star a.multiply(b)a/b divide a.div(b)a % b modulo a.mod(b)a++ increment a.next()a-- decrement a.previous()a**b power a.power(b)
22 R. Volz - Groovy & Grails
Groovy // Advanced switch
switch (v) { case 1: println 'Number one'; break;
case 'test': println 'String test'; break;
case 2..15 : println 'in range 2 to 15'; break;
case [1, '1', 'One'] : println 'Number one'; break;
case ~/A.*/: println 'Starts with A'; break;
default: println 'Default Output'; break}
23 R. Volz - Groovy & Grails
Groovy // Additional Library
Adds methods missing from the JDK String
contains(), count(), execute(), padLeft(), center(), padRight(), reverse(), tokenize(), each(), etc.
Collection count(), collect(), join(), each(), reverseEach(), find/All(), min(),
max(), inject(), sort(), etc.
File eachFile(), eachLine(), withPrintWriter(), write(), getText(), etc.
24 R. Volz - Groovy & Grails
Groovy // Strings and Regular Expressions
def cal = new GregorianCalendar()println "Date: $cal.time"
assert 'only letters' ==~ /((\w*) *)*/
assert 'only letters' =~ /\w*/
def matcher = 'only letters' =~ /\w*/mather.each { println it }
Usage of variables in strings
Matches whole words
Matches all words
Print all words
25 R. Volz - Groovy & Grails
Groovy // GPath path expressions
class Person { name; age }
list = [ new Person( name:'Rod', age:33 ),
new Person( name:'James', age:35 ) ]
println( list.find {it.age > 25}.name )
-> [Rod]
println( list.findAll {it.age > 25}.name )
-> [Rod, James]
println( list.any{ it.name.size() > 4 } )
-> true
26 R. Volz - Groovy & Grails
Groovy // Builders
Implemenation of Builder Design Pattern Used to construct other things
Groovy provides builders for Groovy objects NodeBuilder XML,HTML groovy.xml.MarkupBuilder Swing SwingBuilder Ant AntBuilder
Can add own Builders (very powerful) Who writes one for RDF ? Who writes one for OWL ? Who writes one for BPEL ?
27 R. Volz - Groovy & Grails
Groovy // XML Builder
Groovy
data = ['Rod': ['Misha':8, 'Bowie':2], 'Eric': ['Poe':4, 'Doc':3] ]
xml = new groovy.xml.MarkupBuilder()
people = xml.people() {
for ( entry in data ) { person( name: entry.key ) { for ( dog in entry.value) { pet( name:dog.key, age:dog.value ) } }
}
}
XML
<people>
<person name='Rod'>
<pet name='Bowie' age='2' />
<pet name='Misha' age='8' />
</person>
<person name='Eric'>
<pet name='Poe' age='4' />
<pet name='Doc' age='3' />
</person>
</people>
28 R. Volz - Groovy & Grails
Groovy // XML Parser
XML
<people>
<person name='Rod'>
<pet name='Bowie' age='2' />
<pet name='Misha' age='8' />
</person>
<person name='Eric'>
<pet name='Poe' age='4' />
<pet name='Doc' age='3' />
</person>
</people>
Groovy
def persons = new XmlParser().parseText(text);
assert people.person.pet.name ==['Bowie', 'Misha', 'Poe', 'Doc']
29 R. Volz - Groovy & Grails
Groovy // Dynamic Features
Meta Object protocol Intercept method calls Control access to properties Control access to classes
Expando Objectdef e = new Expando ()e.a = Math.PIe.m = { println 'I am an expando, this is new method m' }e.m()
Duck Typingclass Fish { def swim() { println 'I am a fish' } }class Dolphin {def swim() { println 'I am a dolphin' } }[new Fish(), new Dolphin()].each { it.swim() }
30 R. Volz - Groovy & Grails
Groovy // Summary
Groovy Dynamic, flexible Components Focus Adaptivity, Prototyping
Java Static, stable Components Critical for runtime More efficient compiler
Typically 50% less development effort (*)
Note: (*) Comes at higher debugging expense and 20-90% performance
31 R. Volz - Groovy & Grails
Agenda
Why should I care ?
Get Groovy
Find Grails
32 R. Volz - Groovy & Grails
What is GRAILS ?
Grails is an MVC Web framework Initially inspired by Ruby on Rails
Built upon solid bricks & best of breed components Spring: IoC, DI, Spring MVC, transactional support, experimental
Spring WebFlow… Hibernate: ORM, querying mechanism… Groovy: for focusing on everything that matters And: SiteMesh, Quarz, AJAX frameworks…
« Convention over configuration »: Focus not on wiring and configuration!
33 R. Volz - Groovy & Grails
GRAILS // Layering on Java Components
Source: G. K. Rocher, The Definite Guide to Grails, Apress, 2006, p. 7
34 R. Volz - Groovy & Grails
GRAILS // Step 1
35 R. Volz - Groovy & Grails
Source: G. K. Rocher, The Definite Guide to Grails, Apress, 2006, p. 39
36 R. Volz - Groovy & Grails
GRAILS // Basic application already there after Step 1
37 R. Volz - Groovy & Grails
GRAILS // Step 2 - Define a Model
• Now that the skeleton is there, focus on the model• Model backed by GORM• The model is just a set POGOs (Plain Old Groovy Objects)
• First class of our domain: the books
class Book {String title
String authorString publisher
}
38 R. Volz - Groovy & Grails
GRAILS // GRAILS Contribution
• Automatically, Grails add dynamic instance & static methods to all your domain classes:
Static methods: Instance methods:
• Book.get(1) • Book.save()• Book.find() • book.validate()• Book.findAll() • book.update()
• bok.delete()
39 R. Volz - Groovy & Grails
GRAILS // Step 3 Generation of views and controllers
• Once the Book class is created, let´s benefint from static scaffolding
→ grails generate-all→ grails run-app
• A BookController is created, as well as four GSP:
▪ create.gsp ▪ edit.gsp ▪ list.gsp ▪ show.gsp
40 R. Volz - Groovy & Grails
GRAILS // Scaffolding provides basic GUI for CRUD
41 R. Volz - Groovy & Grails
GRAILS // Taking control of GRAILS
View
Model Controller
grails generate-controller/grails-app/controllers
grails generate-views/grails-app/views
grails create-domain-class/grails-app/model
Jobs Services
/grails-app/jobs /grails-app/services
grails create-app1
2
grails generate-all
3
Web
Tes
tU
nit
Tes
t
4
56
42 R. Volz - Groovy & Grails
GRAILS // VIEW CONTROLLER INTERACTION
Source: G. K. Rocher, The Definite Guide to Grails, Apress, 2006
43 R. Volz - Groovy & Grails
GRAILS // Hibernate interaction
• Hibernate is the de facto ORM solution• Domain classes are automatically and transparently mapped with Hibernate
• 1:1, 1:n & m:n realtionships supported
• Various database environments (dev, test, prod)• Default HSQLDB in-memory config
• You can even provide your own Hibernate mapping files for legacy schemas• You can also reuse your EJB3!
VM C S J
44 R. Volz - Groovy & Grails
GRAILS // A more complex domain
class Author { String firstName String lastName
def hasMany = [books: Book] String toString() { “$firstName $lastName” }}
class Book { String title Author author Publisher publisher
def belongsTo = [Publisher,Author]
String toString() { title }}
class Publisher { String name
def hasMany = [ books: Book]
String toString() { name }}
Author has many Books
Publisher has many Books
VM C S J
45 R. Volz - Groovy & Grails
GRAILS // Domain with constraints to keep valid
Add an email to Author
class Author { String email // … static constraints = {
email (email: true) }}
Add an ISBN to Book
class Book { Stringisbn // … static constraints = {
isbn (matches:“ [0-9] {9} [0-9X ]”)}
}
VM C S J
46 R. Volz - Groovy & Grails
GRAILS // ... and even more constraints
• Many constraints available:
blank, creditcard, email, inList, length, min, minLength, minSize, matches, max, maxLength, maxSize, notEqual, nullable, range, size, unique, url, validator
• And you can create your own closure validator:
even( validator: { it % 2 == 0 )}
VM C S J
47 R. Volz - Groovy & Grails
GRAILS // Querying your Model
Grails provides various querying mechanisms:
Dynamic finder methods Query by example Criteria builders Full-blown HQL queries
VM C S J
48 R. Volz - Groovy & Grails
GRAILS // Query Examples
• Book.findByTitle (“The Stand”)
Book.findByTitleLike(“Harry Pot%”) Book.findByReleaseDataBetween(start, end) Book.findByTitleLikeOrReleaseDataLessThan(
“%Grails%”, someData)
• Find by relationship Book.findAllByAuthor( Author.get(1) )
• Affect sorting Book.findAllbyAuthor(me,[sort:‘title’,order:’asc’])
VM C S J
49 R. Volz - Groovy & Grails
GRAILS // Views
• Spring MVC under the hood• Support for flash scope between requests• GSP: Groovy alternative to JSP• Dynamic taglib development: no TLD, no configuration, just conventions• Adaptive AJAX tags (Yahoo, Dojo, Prototype)• Customizable layout with SiteMesh• Page fragments through reusable templates• View under grails-app/views
VM C S J
TIP: Use grails install-templates to install and customize your the templates to be used
for generation (templates in ../src/templates)
50 R. Volz - Groovy & Grails
GRAILS // GSP Groovy Server Pages
<html> <head>
<meta name=“layout“ content=“main“ /> <title>Book List</title>
</head> <body> <a href=“${createLinkTo(dir:’’)}”>Home</a>
<g:link action=“create”>New Book</g:link> <g:if test=“${flash.message}”>
${flash.message} </g:if> <g:each in=“${bookList}”>${it.title}</g:each>
</body></html>
VM C S J
51 R. Volz - Groovy & Grails
GRAILS // Rich Set of Dynamic Tag Libs
• Logical: if, else, elseif• Iterative: while, each, collect, findAll…• Linking: link, createLink, createLinkTo• Ajax: remoteFunction, remoteLink, formRemote, submitToRemote…• Form: form, select, currencySelect, localSelect, datePicker, checkBox…• Rendering: render*, layout*, paginate…• Validation: eachError, hasError, message• UI: rich TextEditor…
VM C S J
52 R. Volz - Groovy & Grails
GRAILS // URL Convention
• URL mapping convention: controller/action/id http://localhost:8080/library/book/show/1 • Scaffolding can be ▪ dynamic (def scaffold = true) ▪ static (code generation)• Controllers pass data to the view through maps• Direct access to parameters• Easy redirect and forward• Can define allowed methods for each action
VM C S J
53 R. Volz - Groovy & Grails
GRAILS // Controllers provide actions to execute (call)
class BookController { def index = { redirect(action:list,params:params) } def list = { [ bookList: Book.list( params )] }
def show = { [ book : Book.get( params.id ) ] }
def edit = { def book = Book.get( params.id ) if(!book) { flash.message = “Book ${params.id} not found” redirect(action:list) } else return [ book : book ] }}
VM C S J
54 R. Volz - Groovy & Grails
GRAILS // Chaining and Flashing
Source: G. K. Rocher, The Definite Guide to Grails, Apress, 2006
55 R. Volz - Groovy & Grails
GRAILS // Services
• Services are Groovy classes that should contain your business logic
• Automatic injection of services in controllers & services simply by declaring a field:
class BookController { MySuperService mySuperService }
VM C S J
56 R. Volz - Groovy & Grails
Grails // Jobs
• You can create recuring events with Quartz under the hood, configured by Spring• Again a convention on the name and directory• Regular intervals, or cron definitions
• class MyJob {} def cronExpression = “0 0 24 * * ?” def execute() {
print “Job run!” } }
VM C S J
57 R. Volz - Groovy & Grails
Further Reading
58 R. Volz - Groovy & Grails
Concluding Notes
Slides (largely) inspired by the following two presentations Rod Cope and James Strachan
The Groovy Programming LanguagePresentation held at JavaOne 2004
Graeme RocherRapid Web Application Development with GrailsPresentation held at JavaOne 2006
Get started with... GRAILS: grails.codehaus.org GROOVY: groovy.codehaus.org