Grails Goodness: Custom JSON and Markup Views For Default REST Resources
In Grails we can use the @Resource
annotation to make a domain class a REST resource.
The annotation adds a controller as URL endpoint for the domain class.
Values for the domain class properties are rendered with a default renderer.
We can use JSON and markup views to customize the rendering of the domain class annotated with a @Resource
annotation.
First we must make sure we include views plugin in our build configuration.
Then we must create a directory in the grails-app/views
directory with the same name as our domain class name.
Inside the directory we can add JSON and markup views with names that correspond with the controller actions.
For example a file index.gson
or index.gml
for the index
action.
We can also create a template view that is automatically used for a resource instance by adding a view with the name of the domain class prefixed with an underscore (_
).
In the next example application we create a custom view for the Book
domain class that is annotated with the @Resource
annotation:
package mrhaki.sample
import grails.rest.Resource
@Resource(uri = '/books')
class Book {
String title
String isbn
static constraints = {
title blank: false
isbn blank: false
}
}
Next we must make sure the Grails views code is available as a dependency.
In our build.gradle
file we must have the following dependencies in the dependencies {}
block:
...
dependencies {
....
// Support for JSON views.
compile "org.grails.plugins:views-json:1.1.5"
// Support for markup views.
compile "org.grails.plugins:views-markup:1.1.5"
....
}
...
It is time to create new JSON views for JSON responses. We create the directory grails-app/views/book/
and the file _book.gson
.
This template file is automatically used by Grails now when a Book
instances needs to be rendered:
import grails.util.Environment
import mrhaki.sample.Book
model {
Book book
}
json {
id book.id
version book.version
title book.title
isbn book.isbn
information {
generatedBy 'Sample application'
grailsVersion Environment.grailsVersion
environment Environment.current.name
}
}
We also create the file index.gson
to support showing multiple Book
instances:
import mrhaki.sample.Book
model {
List bookList
}
// We can use template namespace
// method with a Collection.
json tmpl.book(bookList)
If we also want to support XML we need to create extra markup views. First we a general template for a Book
instance with the name _book.gml
:
import grails.util.Environment
import mrhaki.sample.Book
model {
Book book
}
xmlDeclaration()
book {
id book.id
title book.title
isbn book.isbn
information {
generatedBy 'Sample application'
grailsVersion Environment.grailsVersion
environment Environment.current.name
}
}
Next we create the file index.gml
to show Book
instances. Note we cannot use the template namespace in the markup view opposed to in the JSON view:
import grails.util.Environment
import mrhaki.sample.Book
model {
List<Book> bookList
}
xmlDeclaration()
books {
bookList.each { bookInstance ->
book {
id bookInstance.id
title bookInstance.title
isbn bookInstance.isbn
information {
generatedBy 'Sample application'
grailsVersion Environment.grailsVersion
environment Environment.current.name
}
}
}
}
We start our Grails application and use cUrl
to invoke our REST resource:
$ curl -H Accept:application/xml http://localhost:8080/books/1
1Gradle Dependency Management978-1784392789 Sample application3.2.6development 2Gradle Effective Implementation Guide978-1784394974 Sample application3.2.6development
$ curl -H Accept:application/xml http://localhost:8080/books/1
1Gradle Dependency Management978-1784392789 Sample application3.2.6development
$ curl -H Accept:application/json http://localhost:8080/books
[
{
"id": 1,
"version": 0,
"title": "Gradle Dependency Management",
"isbn": "978-1784392789",
"information": {
"generatedBy": "Sample application",
"grailsVersion": "3.2.6",
"environment": "development"
}
},
{
"id": 2,
"version": 0,
"title": "Gradle Effective Implementation Guide",
"isbn": "978-1784394974",
"information": {
"generatedBy": "Sample application",
"grailsVersion": "3.2.6",
"environment": "development"
}
}
]
$ curl -H Accept:application/json http://localhost:8080/books/1
{
"id": 1,
"version": 0,
"title": "Gradle Dependency Management",
"isbn": "978-1784392789",
"information": {
"generatedBy": "Sample application",
"grailsVersion": "3.2.6",
"environment": "development"
}
}
$
Written with Grails 3.2.6.