2. Page 2
REST
• Not really a Technology
• More an Architecture
• Simple
• Communication via plain text, xml, json
• Combine with HTTP method
• Resource-Oriented
3. Page 3
Mapping HTTP Method
HTTP Method Action
GET Read ( R )
PUT Update ( U )
POST Create ( C )
DELETE Delete ( D )
4. Page 4
Mapping REST in Grails
• Example
static mappings = {
"/product/$id?"( resource:"product" )
}
HTTP Method Action
GET show
PUT update
POST save
DELETE delete
5. Page 5
Mapping REST in Grails
• Example
static mappings = {
"/product/$id"(controller:"product",
parseRequest:true ){
action = [
GET:"show",
PUT:"update",
DELETE:"delete",
POST:"save“
]
}
}
Automatic XML
or JSON
Marshaling
6. Page 6
Create REST Controller
• grails create-controller product
class ProductController {
def show = {
render “show from rest”
}
def save = {
render “save from rest”
}
def update = {
render “update from rest”
}
def delete = {
render “delete from rest”
}
}
9. Page 9
REST Controller :: Switch on HTTP method
• grails create-controller product
class ProductController {
def index = {
switch(request.method){
case "POST": render "Create"
break
case "GET": render "Retrieve"
break
case "PUT": render "Update"
break
case "DELETE": render "Delete"
break
}
}
}
10. Page 10
Communication via XML
• grails create-controller product
import grails.converters.*
class ProductController {
def list = {
render Product.list() as XML
}
def show = {
render Product.get( params.id ) as XML
}
}
11. Page 11
Domain class :: Product
• grails create-domain-class product
class Product {
String name
Double price
String toString() {
return "id=${id}|name=${name}|price=${price}"
}
}
12. Page 12
Insert data for Test
• File /conf/BootStap.groovy
class BootStrap {
def init = { servletContext ->
if( !Product.count() ) {
new Product(
name:"Product 1",
price:12.9 ).save( failOnError:true )
new Product(
name:"Product 2",
price:20.5 ).save( failOnError:true )
}
}
def destroy = { }
}
13. Page 13
XML Result
<list>
<product id="1">
<name>Product 1</name>
<price>12.9</price>
</product>
<product id="2">
<name>Product 2</name>
<price>20.5</price>
</product>
</list>
18. Page 18
Content Negotiation
• Allow to return different format based on the request.
• All format in file /conf/Config.groovy
grails.mime.types =
[
html: ['text/html','application/xhtml+xml'],
xml: ['text/xml', 'application/xml'],
text: 'text/plain',
js: 'text/javascript',
rss: 'application/rss+xml',
atom: 'application/atom+xml',
css: 'text/css',
csv: 'text/csv',
all: '*/*',
json: ['application/json','text/json'],
form: 'application/x-www-form-urlencoded',
multipartForm: 'multipart/form-data'
]
19. Page 19
Using withFormat
def list = {
if(!params.max) params.max = 10
def productList = Product.list( params )
withFormat {
html { render productList }
xml { render productList as XML }
json { render productList as JSON }
}
}
Default format
html
20. Page 20
How to call ?
• Default
• http://localhost:8080/example/product/list
• URL Extension
• http://localhost:8080/example/product/list.html
• Format request parameter
• http://localhost:8080/example/product/list?format=html
22. Page 22
Define Format parameter in URL Mapping
• Set default format = xml
"/product2/list2" (controller:"product2", action:"list2") {
format = "xml"
}
23. Page 23
How to call ?
• http://localhost:8080/example/product/list.xml
• http://localhost:8080/example/product/list?format=xml
24. Page 24
RSS and Atom
• Using Feed plug-in
•http://docs.codehaus.org/display/GRAILS/Feeds+Plugin
• ROME Library
•https://rome.dev.java.net/
25. Page 25
RSS
• Install plug-in > grails install-plugin feeds
withFormat {
rss {
render(feedType:"rss", feedVersion:"2.0") {
title = "My test feed"
link = "http://www.grails66.com/feed"
description = “Grails 66 feed"
productList.each() { product ->
entry(product.name) {
link ="http://grails66.com//${product.id}"
product.name
}
}
}
}
}