3. Groovy & Grails
Introduction to Groovy
Groovy is an agile and dynamic language for the JVM
• With a Meta-Object Protocol
• Compiles down to bytecode
• But also supports static typing
{ Agile Development } { Ruby on Rails } { Java / J2EE }
4. Groovy & Grails
Introduction to Groovy
Groovy is an agile and dynamic language for the JVM
• With a Meta-Object Protocol
• Compiles down to bytecode
• But also supports static typing
Java on steroids:
• Builds upon the strengths of Java, but...
• With power features borrowed from Smalltalk/Python/Ruby
• Makes modern programming features available to Java
developers with a flat learning curve
{ Agile Development } { Ruby on Rails } { Java / J2EE }
5. Groovy & Grails
Introduction to Groovy
Groovy is an agile and dynamic language for the JVM
• With a Meta-Object Protocol
• Compiles down to bytecode
• But also supports static typing
Java on steroids:
• Builds upon the strengths of Java, but...
• With power features borrowed from Smalltalk/Python/Ruby
• Makes modern programming features available to Java
developers with a flat learning curve
Seamlessly integrates with all existing Java objects and
libraries
{ Agile Development } { Ruby on Rails } { Java / J2EE }
6. Groovy & Grails
Introduction to Groovy
Groovy is an agile and dynamic language for the JVM
• With a Meta-Object Protocol
• Compiles down to bytecode
• But also supports static typing
Java on steroids:
• Builds upon the strengths of Java, but...
• With power features borrowed from Smalltalk/Python/Ruby
• Makes modern programming features available to Java
developers with a flat learning curve
Seamlessly integrates with all existing Java objects and
libraries
Feels natural to Java developers
{ Agile Development } { Ruby on Rails } { Java / J2EE }
7. Groovy & Grails
From Java to Groovy
A normal Java program
public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String greet() {
return "Hello " + name;
}
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Groovy");
System.out.println(helloWorld.greet());
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
8. Groovy & Grails
From Java to Groovy
A valid Groovy program
public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String greet() {
return "Hello " + name;
}
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Groovy");
System.out.println(helloWorld.greet());
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
9. Groovy & Grails
From Java to groovy
But hey?
Where are the steroids?
{ Agile Development } { Ruby on Rails } { Java / J2EE }
10. Groovy & Grails
From Java to Groovy
A Groovier program
class HelloWorld {
def name
def greet() { "Hello ${name}" }
}
helloWorld = new HelloWorld(name: "Groovy")
println helloWorld.greet()
Dynamic types using the def keyword
Everything in Groovy is public unless defined otherwise
Automatic getters and setters
Semicolons at end-of-line are optional
Variable interpolation through GStrings
Return keyword is optional
{ Agile Development } { Ruby on Rails } { Java / J2EE }
11. Groovy & Grails
From Java to Ruby
A Ruby program
class HelloWorld < Struct.new(:name)
def greet
"Hello #{name}"
end
end
hello_world = HelloWorld.new("Ruby")
puts hello_world.greet
{ Agile Development } { Ruby on Rails } { Java / J2EE }
12. Groovy & Grails
JVM Languages
{ Agile Development } { Ruby on Rails } { Java / J2EE }
13. Groovy & Grails
Joint Compilation
Total interoperability
Java Interface Groovy Interface
Groovy Class Java Class
Java Class Groovy Class
{ Agile Development } { Ruby on Rails } { Java / J2EE }
16. Groovy & Grails
Iterating
Looping
• Groovy: for (i in list) { println i }
• Ruby: for i in list
puts i
end
{ Agile Development } { Ruby on Rails } { Java / J2EE }
17. Groovy & Grails
Iterating
Looping
• Groovy: for (i in list) { println i }
• Ruby: for i in list
puts i
end
Looping with closures
• Groovy: list.each { println it }
• Ruby: list.each {|i| puts i }
{ Agile Development } { Ruby on Rails } { Java / J2EE }
18. Groovy & Grails
GStrings
GStrings are interpolated strings
• Placeholder variables are replaced
• You can have multiline strings
def person = "Marcel"
def letter = """
${new Date()}
Hello ${person},
You have won 100,000,000GBP in the UK lottery!
"""
{ Agile Development } { Ruby on Rails } { Java / J2EE }
19. Groovy & Grails
Special Operators
Elvis operator
• A shortening of Java's ternary operator
def displayName = user.name ? user.name : "Anonymous"
def displayName = user.name ?: "Anonymous"
{ Agile Development } { Ruby on Rails } { Java / J2EE }
20. Groovy & Grails
Special Operators
Elvis operator
• A shortening of Java's ternary operator
def displayName = user.name ? user.name : "Anonymous"
def displayName = user.name ?: "Anonymous"
Safe Navigation Operator
• Java: String postalCode = null;
if (user != null) {
Address address = user.getAddress();
if (address != null) {
postalCode = address.getPostalCode();
if (postalCode != null) {
postalCode = postalCode.toUpperCase();
}
}
}
• Groovy: def postalCode = user?.address?.postalCode?.toUpperCase()
{ Agile Development } { Ruby on Rails } { Java / J2EE }
21. Groovy & Grails
The Groovy Truth
Booleans
def a = true
def b = false
assert a
assert !b
Collections
def numbers = []
assert !numbers // false, as numbers is an empty collection
numbers = [1, 2, 3]
assert numbers // true, as numbers is not empty
Strings
assert 'This is true'
assert !''
Numbers
assert !0 // yeah, 0s are false, like in Perl
assert 1 // this is also true for all other number types
Objects
assert new Object()
{ Agile Development } { Ruby on Rails } { Java / J2EE }
22. Groovy & Grails
Meta Programming
You can add methods and properties to any Object at
runtime
You can intercept method calls and property access
(similar to AOP)
def s = "Hello Groovy"
println s
println s.toUpperCase() // standard JDK method
String.metaClass {
toMixedCase { delegate.toUpperCase() } // add method
toUpperCase { delegate.toLowerCase() } // override existing method
multiply { i -> delegate * i } // add method with argument
}
println s.toMixedCase()
println s.toUpperCase()
println s.multiply(3)
{ Agile Development } { Ruby on Rails } { Java / J2EE }
23. Groovy & Grails
Builders
Simple mechanism for creating any create any structured
tree of data
• You can use out-of-the-box builders
• You can create your own builders
import groovy.xml.MarkupBuilder
def mkp = new MarkupBuilder()
mkp.html {
head {
title "Kabisa ICT"
}
body {
div(class: "container") {
p "Welcome to Kabisa ICT"
}
}
}
println mkp
{ Agile Development } { Ruby on Rails } { Java / J2EE }
24. Groovy & Grails
Do you want to be Groovy?
?
{ Agile Development } { Ruby on Rails } { Java / J2EE }
26. Groovy & Grails
Introduction to Grails
Full-stack web application framework inspired by
• Code by Convention
• Don’t Repeat Yourself (DRY)
• Ruby on Rails, Django, TurboGears
{ Agile Development } { Ruby on Rails } { Java / J2EE }
27. Groovy & Grails
Introduction to Grails
Full-stack web application framework inspired by
• Code by Convention
• Don’t Repeat Yourself (DRY)
• Ruby on Rails, Django, TurboGears
Built on the shoulders of Giants
• Java/JEE
• Spring framework
• Hibernate
{ Agile Development } { Ruby on Rails } { Java / J2EE }
28. Groovy & Grails
Introduction to Grails
Full-stack web application framework inspired by
• Code by Convention
• Don’t Repeat Yourself (DRY)
• Ruby on Rails, Django, TurboGears
Built on the shoulders of Giants
• Java/JEE
• Spring framework
• Hibernate
Reduces complexity
{ Agile Development } { Ruby on Rails } { Java / J2EE }
29. Groovy & Grails
Introduction to Grails
Full-stack web application framework inspired by
• Code by Convention
• Don’t Repeat Yourself (DRY)
• Ruby on Rails, Django, TurboGears
Built on the shoulders of Giants
• Java/JEE
• Spring framework
• Hibernate
Reduces complexity
Increases productivity
{ Agile Development } { Ruby on Rails } { Java / J2EE }
30. Groovy & Grails
Introduction to Grails
Full-stack web application framework inspired by
• Code by Convention
• Don’t Repeat Yourself (DRY)
• Ruby on Rails, Django, TurboGears
Built on the shoulders of Giants
• Java/JEE
• Spring framework
• Hibernate
Reduces complexity
Increases productivity
“Java”
{ Agile Development } { Ruby on Rails } { Java / J2EE }
31. Groovy & Grails
Full-stack Web Application Framework
Easy Object Relational Mapping (ORM) based on
Hibernate
View layer with Groovy Server Pages (GSP), dynamic Tag
Libraries and SiteMesh
Controller layer based on Spring MVC / Spring Web Flow
Dependency Injection (DI) using the Spring Container
Transactional service layer based on Spring’s transaction
abstraction
Internationalization (i18n) based on Spring’s
MessageSource concept
Embedded Tomcat servlet container for on the fly
reloading
{ Agile Development } { Ruby on Rails } { Java / J2EE }
32. Groovy & Grails
About SpringSource, G2One and VMware
First version of Spring framework was released in 2003
{ Agile Development } { Ruby on Rails } { Java / J2EE }
33. Groovy & Grails
About SpringSource, G2One and VMware
First version of Spring framework was released in 2003
SpringSource was founded in 2004
{ Agile Development } { Ruby on Rails } { Java / J2EE }
34. Groovy & Grails
About SpringSource, G2One and VMware
First version of Spring framework was released in 2003
SpringSource was founded in 2004
G2One (The Groovy Grails Company) was founded in
2007 by the Groovy and Grails project leads
{ Agile Development } { Ruby on Rails } { Java / J2EE }
35. Groovy & Grails
About SpringSource, G2One and VMware
First version of Spring framework was released in 2003
SpringSource was founded in 2004
G2One (The Groovy Grails Company) was founded in
2007 by the Groovy and Grails project leads
In November 2008 G2One was acquired by SpringSource
{ Agile Development } { Ruby on Rails } { Java / J2EE }
36. Groovy & Grails
About SpringSource, G2One and VMware
First version of Spring framework was released in 2003
SpringSource was founded in 2004
G2One (The Groovy Grails Company) was founded in
2007 by the Groovy and Grails project leads
In November 2008 G2One was acquired by SpringSource
In August 2009 SpringSource was acquired by VMware for
$420m
{ Agile Development } { Ruby on Rails } { Java / J2EE }
37. Groovy & Grails
About SpringSource, G2One and VMware
First version of Spring framework was released in 2003
SpringSource was founded in 2004
G2One (The Groovy Grails Company) was founded in
2007 by the Groovy and Grails project leads
In November 2008 G2One was acquired by SpringSource
In August 2009 SpringSource was acquired by VMware for
$420m
SpringSource is now a division of VMware
{ Agile Development } { Ruby on Rails } { Java / J2EE }
38. Groovy & Grails
Grails Stack
Grails
Other
JEE Spring Hibernate
Libraries
Groovy
Java Development Kit
Java Language
(JDK)
Java Virtual Machine
{ Agile Development } { Ruby on Rails } { Java / J2EE }
39. Groovy & Grails
Grails Command Line
grails create-app book
grails create-domain-class nl.kabisa.book
grails create-controller nl.kabisa.book
grails generate-all nl.kabisa.book
grails install plugin acegi
grails run-app
grails test-app
grails war
grails console
..
Custom commands (scripts) can be added to project
{ Agile Development } { Ruby on Rails } { Java / J2EE }
40. Groovy & Grails
Grails Project Breakdown
grails-app Top level source folder with Grails artifacts
• conf Configuration sources
• controlllers Controller layer
• domain Model layer
• i18n Internationalized Resource Bundles
• services Service layer
• taglib Dynamic Tag Libraries
• views Groovy Server Pages (GSP)
web-app Stylesheets, Javascript, ...
scripts Custom command-line scripts
src Other project sources
• groovy Other Groovy project sources
• java Other Java project sources
lib 3th Party Libraries
test Unit, Integration and Functional tests
{ Agile Development } { Ruby on Rails } { Java / J2EE }
41. Groovy & Grails
Configuration per environment
dataSource {
pooled = true
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = true
cache.provider_class = "net.sf.ehcache.hibernate.EhCacheProvider"
}
// environment specific settings
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
url = "jdbc:hsqldb:mem:devDB"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
}
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
42. Groovy & Grails
GORM
GORM (Grails Object Relational Mapping)
• Domain Modeling
• Basic CRUD methods
• Dynamic Finders
• Events and Auto Timestamping
• Validations
• Custom ORM mappings with ORM Domain Specific Language
{ Agile Development } { Ruby on Rails } { Java / J2EE }
43. Groovy & Grails
GORM
GORM (Grails Object Relational Mapping)
• Domain Modeling
• Basic CRUD methods
• Dynamic Finders
• Events and Auto Timestamping
• Validations
• Custom ORM mappings with ORM Domain Specific Language
NO MIGRATIONS
• LiquiBase Plugin
{ Agile Development } { Ruby on Rails } { Java / J2EE }
44. Groovy & Grails
GORM
GORM (Grails Object Relational Mapping)
• Domain Modeling
• Basic CRUD methods
• Dynamic Finders
• Events and Auto Timestamping
• Validations
• Custom ORM mappings with ORM Domain Specific Language
NO MIGRATIONS
• LiquiBase Plugin
Domain model is OOP based, not database based (as in
Rails)
{ Agile Development } { Ruby on Rails } { Java / J2EE }
45. Groovy & Grails
Domain Classes
Grails Rails
class Book { class User < ActiveRecord::Base
String title end
String isbn
BigDecimal price
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
46. Groovy & Grails
Domain Classes
Grails Rails
class Author { class Auhor < ActiveRecord::Base
static hasMany = [books: Book] has_many :books
String name end
}
class Book { class Book < ActiveRecord::Base
static belongsTo = [author: Author] belongs_to :author
String title end
String isbn
BigDecimal price
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
47. Groovy & Grails
Validations, Events, Auto Timestamping, Mappings
class Book {
static belongsTo = [author: Author]
String title
String isbn
BigDecimal price
Date dateCreated
Date lastUpdated
def beforeInsert() {
dateCreated = new Date()
}
static constraints = {
title(blank: false, maxSize: 100)
isbn(blank: false, matches: "[0-9]13", minSize: 13, maxSize: 13, unique: true)
price(nullable: true, min: 0.0, max: 9999.99, scale: 2)
}
static mapping = {
table "books"
price column: "sales_price"
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
48. Groovy & Grails
Basic CRUD methods
Grails Rails
// create # create
def a = new Author(name: "Rowling") a = Author.new(:name => "Rowling")
a.save() a.save
// read # read
def a = Author.get(1) a = Author.find(1)
// update # update
def a = Author.get(1) a = Author.find(1)
a.name = "J.K. Rowling" a.name = "J.K. Rowling"
a.save() a.save
// delete # delete
def a = Author.get(1) a = Author.find(1)
a.delete() a.delete
{ Agile Development } { Ruby on Rails } { Java / J2EE }
51. Groovy & Grails
Criteria and HQL
// using criteria builder
def c = Book.createCriteria()
def books = c {
like("title", "Harry P%")
and {
between("price", 10.0, 20.0)
}
order("title", "asc")
}
// using HQL (Hibernate Query Language)
def books = Book.findAll("from Book as b where b.title like ?", ["Harry P%"])
{ Agile Development } { Ruby on Rails } { Java / J2EE }
52. Groovy & Grails
Controllers
Responsible for handling requests
Render or prepare responses
Bind request data to the model (including type conversions)
Support interceptors
Support content negotiation
class SomeController {
def action = {
// do controller logic
// create model
return model
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
53. Groovy & Grails
Controllers
Grails
class BookController {
def list = {
[bookList: Book.list()]
}
}
<ul>
<g:each in="${bookList}">
<li>${it.title}</li>
</g:each>
</ul>
{ Agile Development } { Ruby on Rails } { Java / J2EE }
54. Groovy & Grails
Controllers
Grails
class BookController {
def list = {
[bookList: Book.list()]
}
}
<ul>
<g:each in="${bookList}">
<li>${it.title}</li>
</g:each>
</ul>
Rails
class BooksController < ApplicationController
def list
@books = Book.all
end
end
{ Agile Development } { Ruby on Rails } { Java / J2EE }
55. Groovy & Grails
Example Controller
class BookController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index = { redirect(action: "list", params: params) }
def list = {
[bookInstanceList: Book.list(params), bookInstanceTotal: Book.count()]
}
def create = {
def bookInstance = new Book()
bookInstance.properties = params
return [bookInstance: bookInstance]
}
def save = {
def bookInstance = new Book(params)
if (bookInstance.save()) {
redirect(action: "show", id: bookInstance.id)
}
else {
render(view: "create", model: [bookInstance: bookInstance])
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
57. Groovy & Grails
Example Controller
def delete = {
def bookInstance = Book.get(params.id)
if (bookInstance) {
bookInstance.delete(flush: true)
redirect(action: "list")
}
else {
redirect(action: "list")
}
}
def show = {
def bookInstance = Book.get(params.id)
if (!bookInstance) {
redirect(action: "list")
}
else {
[bookInstance: bookInstance]
}
}
def beforeInterceptor = { // do something }
def afterInterceptor = { // do something }
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
58. Groovy & Grails
XML Responses
def list = {
def bookList = Book.list()
render(contentType: "text/xml") {
books {
for (b in bookList) {
book(title: b.title)
}
}
}
}
// automatic xml marshalling
def list = {
render Book.list() as XML
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
59. Groovy & Grails
Content Negotiation
You can use HTTP Accept Header
You can use format request paramter (/book/list?format=xml)
You can use URI extension (/book/list.xml)
Use the withFormat method to deal with different
formats
class BookController {
def list = {
def books = Book.list()
withFormat {
html bookList:books
js { render "alert('hello')" }
xml { render books as XML }
}
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
60. Groovy & Grails
Views
Groovy Server Pages (GSP)
• Similar like technologies like JSP and ASP
• A mix of markup and GSP tags
• Groovy code can be embedded, but is discouraged
{ Agile Development } { Ruby on Rails } { Java / J2EE }
61. Groovy & Grails
Views
Groovy Server Pages (GSP)
• Similar like technologies like JSP and ASP
• A mix of markup and GSP tags
• Groovy code can be embedded, but is discouraged
NO HAML :-(
{ Agile Development } { Ruby on Rails } { Java / J2EE }
62. Groovy & Grails
Views
Groovy Server Pages (GSP)
• Similar like technologies like JSP and ASP
• A mix of markup and GSP tags
• Groovy code can be embedded, but is discouraged
NO HAML :-(
def show = {
[book: Book.get(params.id)]
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
63. Groovy & Grails
Views
Groovy Server Pages (GSP)
• Similar like technologies like JSP and ASP
• A mix of markup and GSP tags
• Groovy code can be embedded, but is discouraged
NO HAML :-(
def show = {
[book: Book.get(params.id)]
}
<%= book.title %>
{ Agile Development } { Ruby on Rails } { Java / J2EE }
64. Groovy & Grails
Views and Tag Libraries
Embedded Groovy code
<html>
<body>
<% [1, 2, 3, 4].each { num ->
if (num > 2) { %>
<p><%= "Hello ${num}!" %></p>
<% }
} %>
</body>
</html>
{ Agile Development } { Ruby on Rails } { Java / J2EE }
65. Groovy & Grails
Views and Tag Libraries
Embedded Groovy code
<html>
<body>
<% [1, 2, 3, 4].each { num ->
if (num > 2) { %>
<p><%= "Hello ${num}!" %></p>
<% }
} %>
</body>
</html>
Use Tag Libraries instead
<html>
<body>
<g:each in="${[1, 2, 3, 4]}" var="num">
<g:if test="${num > 2}">
<p>Number ${num}</p>
</g:if>
</g:each>
</body>
</html>
{ Agile Development } { Ruby on Rails } { Java / J2EE }
66. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
{ Agile Development } { Ruby on Rails } { Java / J2EE }
67. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
{ Agile Development } { Ruby on Rails } { Java / J2EE }
68. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
Logic and Iteration <g:if> <g:else> <g:elsif> <g:each> <g:while>
{ Agile Development } { Ruby on Rails } { Java / J2EE }
69. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
Logic and Iteration <g:if> <g:else> <g:elsif> <g:each> <g:while>
Links and Resources
<g:link action="show" id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book" action="list">Book List</g:link>
{ Agile Development } { Ruby on Rails } { Java / J2EE }
70. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
Logic and Iteration <g:if> <g:else> <g:elsif> <g:each> <g:while>
Links and Resources
<g:link action="show" id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book" action="list">Book List</g:link>
Forms and Fields
<g:textField name="title" value="${bookInstance.title}" />
<g:select name="author.id" from="${Author.list()}" value="${bookInstance.author.id}" />
<g:datePicker name="publishDate" value="${bookInstance.publishDate}" />
{ Agile Development } { Ruby on Rails } { Java / J2EE }
71. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
Logic and Iteration <g:if> <g:else> <g:elsif> <g:each> <g:while>
Links and Resources
<g:link action="show" id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book" action="list">Book List</g:link>
Forms and Fields
<g:textField name="title" value="${bookInstance.title}" />
<g:select name="author.id" from="${Author.list()}" value="${bookInstance.author.id}" />
<g:datePicker name="publishDate" value="${bookInstance.publishDate}" />
Formatting
{ Agile Development } { Ruby on Rails } { Java / J2EE }
72. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
Logic and Iteration <g:if> <g:else> <g:elsif> <g:each> <g:while>
Links and Resources
<g:link action="show" id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book" action="list">Book List</g:link>
Forms and Fields
<g:textField name="title" value="${bookInstance.title}" />
<g:select name="author.id" from="${Author.list()}" value="${bookInstance.author.id}" />
<g:datePicker name="publishDate" value="${bookInstance.publishDate}" />
Formatting
Ajax
{ Agile Development } { Ruby on Rails } { Java / J2EE }
73. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
Logic and Iteration <g:if> <g:else> <g:elsif> <g:each> <g:while>
Links and Resources
<g:link action="show" id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book" action="list">Book List</g:link>
Forms and Fields
<g:textField name="title" value="${bookInstance.title}" />
<g:select name="author.id" from="${Author.list()}" value="${bookInstance.author.id}" />
<g:datePicker name="publishDate" value="${bookInstance.publishDate}" />
Formatting
Ajax
and more...
{ Agile Development } { Ruby on Rails } { Java / J2EE }
74. Groovy & Grails
Core Tag Libraries
Much more attractive than embedded Groovy code
Like helpers in Rails
Logic and Iteration <g:if> <g:else> <g:elsif> <g:each> <g:while>
Links and Resources
<g:link action="show" id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book" action="list">Book List</g:link>
Forms and Fields
<g:textField name="title" value="${bookInstance.title}" />
<g:select name="author.id" from="${Author.list()}" value="${bookInstance.author.id}" />
<g:datePicker name="publishDate" value="${bookInstance.publishDate}" />
Formatting
Ajax
and more...
{ Agile Development } { Ruby on Rails } { Java / J2EE }
75. Groovy & Grails
Custom Tag Libraries
Very complex and painful in standard Java
• Complex interfaces to implement
• Additional Tag Library Descriptors (XML) must be written
• And need to be configured in web.xml
{ Agile Development } { Ruby on Rails } { Java / J2EE }
76. Groovy & Grails
Custom Tag Libraries
Very complex and painful in standard Java
• Complex interfaces to implement
• Additional Tag Library Descriptors (XML) must be written
• And need to be configured in web.xml
But so easy in Grails
class SimpleTagLib {
static namespace = "auth"
def isAdmin = { attrs, body ->
if (attrs.user.admin)
out << body()
}
}
<auth:isAdmin user="${session.user}">
// some restricted content
</auth:isAdmin>
{ Agile Development } { Ruby on Rails } { Java / J2EE }
78. Groovy & Grails
URL Mappings
Used for mapping URL’s to controllers
• Similar like routes in Rails
• Default convention is /controller/action/id
{ Agile Development } { Ruby on Rails } { Java / J2EE }
79. Groovy & Grails
URL Mappings
Used for mapping URL’s to controllers
• Similar like routes in Rails
• Default convention is /controller/action/id
class UrlMappings {
static mappings = {
"/product" (controller: "product", action: "list")
"/product/$id" (controller: "product")
"/$blog/$year/$month/$day/$id" (controller: "blog", action: "show")
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
80. Groovy & Grails
Filters
Controllers already support fine grained interceptors but
these are difficult to manage in larger applications
{ Agile Development } { Ruby on Rails } { Java / J2EE }
81. Groovy & Grails
Filters
Controllers already support fine grained interceptors but
these are difficult to manage in larger applications
Use filters instead
• A Domain Specific Language is available for defining filters
• You can define scopes (all controllers, a specific controller/action, URI pattern)
• You can define interceptor types (before, after, afterView)
• You can use variables (params, request, response, session, grailsApplication)
{ Agile Development } { Ruby on Rails } { Java / J2EE }
82. Groovy & Grails
Filters
Controllers already support fine grained interceptors but
these are difficult to manage in larger applications
Use filters instead
• A Domain Specific Language is available for defining filters
• You can define scopes (all controllers, a specific controller/action, URI pattern)
• You can define interceptor types (before, after, afterView)
• You can use variables (params, request, response, session, grailsApplication)
class SecurityFilters {
def filters = {
loginCheck(controller: '*', action: '*') {
before = {
if(!session.user && !actionName.equals('login')) {
redirect(action: 'login')
return false
}
}
}
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
83. Groovy & Grails
Services
Don’t put core/reusable logic in controllers, but instead
use the service layer
Services are by default transactional
Services can be scoped
class BookService {
static scope = "singleton" // other options include prototype, request, session
static transactional = true
def doSomething() {
// TODO: implement
}
}
{ Agile Development } { Ruby on Rails } { Java / J2EE }
84. Groovy & Grails
Plugins
Grails is designed with a plugin architecture in mind
Grails core features are built on plugins
Plugins can provide basic artifacts
• Domain Classes, Tag Libraries, Services, ...
Plugins can provide new artifact types
Plugins can hook into build events
Plugins can hook into runtime configuration
Plugins can add dynamic methods at runtime
{ Agile Development } { Ruby on Rails } { Java / J2EE }
85. Groovy & Grails
Plugins
Spring Security LDAP
Quartz Commentable
Searchable Selenium RC
Mail Fixtures
Canoo Webtest ReCaptcha
GWT LiquiBase
Feeds GORM-JPA
Taggable iWebKit
Rateable Webdriver
XFire Axis2
Spring WS Wicket
{ Agile Development } { Ruby on Rails } { Java / J2EE }
86. Groovy & Grails
Tooling
Integrated Development Environments
• SpringSource Tool Suite (STS)
• NetBeans
• IDEA IntelliJ
TextMate
{ Agile Development } { Ruby on Rails } { Java / J2EE }