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:
// File: grails-app/domain/mrhaki/sample/Book.groovy 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:
// File: build.gradle ... 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:
// File: grails-app/views/book/_book.gson 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:
// File: grails-app/views/book/index.gson import mrhaki.sample.Book model { List<Book> 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
:
// File: grails-app/views/book/_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:
// File: grails-app/views/book/index.gml 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 <?xml version='1.0' encoding='UTF-8'?> <books> <book> <id>1</id><title>Gradle Dependency Management</title><isbn>978-1784392789</isbn><information> <generatedBy>Sample application</generatedBy><grailsVersion>3.2.6</grailsVersion><environment>development</environment> </information> </book><book> <id>2</id><title>Gradle Effective Implementation Guide</title><isbn>978-1784394974</isbn><information> <generatedBy>Sample application</generatedBy><grailsVersion>3.2.6</grailsVersion><environment>development</environment> </information> </book> </books> $ curl -H Accept:application/xml http://localhost:8080/books/1 <?xml version='1.0' encoding='UTF-8'?> <book> <id>1</id><title>Gradle Dependency Management</title><isbn>978-1784392789</isbn><information> <generatedBy>Sample application</generatedBy><grailsVersion>3.2.6</grailsVersion><environment>development</environment> </information> </book> $ 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.