10.5.1 Extending the RestfulController super class

The easiest way to get started doing so is to create a new controller for your resource that extends the grails.rest.RestfulController super class. For example:

  1. class BookController extends RestfulController<Book> {
  2. static responseFormats = ['json', 'xml']
  3. BookController() {
  4. super(Book)
  5. }
  6. }

To customize any logic you can just override the appropriate action. The following table provides the names of the action names and the URIs they map to:

HTTP MethodURIController Action
GET/booksindex
GET/books/createcreate
POST/bookssave
GET/books/${id}show
GET/books/${id}/editedit
PUT/books/${id}update
DELETE/books/${id}delete
The create and edit actions are only needed if the controller exposes an HTML interface.

As an example, if you have a nested resource then you would typically want to query both the parent and the child identifiers. For example, given the following URL mapping:

  1. "/authors"(resources:'author') {
  2. "/books"(resources:'book')
  3. }

You could implement the nested controller as follows:

  1. class BookController extends RestfulController {
  2. static responseFormats = ['json', 'xml']
  3. BookController() {
  4. super(Book)
  5. }
  6. @Override
  7. protected Book queryForResource(Serializable id) {
  8. Book.where {
  9. id == id && author.id == params.authorId
  10. }.find()
  11. }
  12. }

The example above subclasses RestfulController and overrides the protected queryForResource method to customize the query for the resource to take into account the parent resource.

Customizing Data Binding In A RestfulController Subclass

The RestfulController class contains code which does data binding for actions like save and update. The class defines a getObjectToBind() method which returns a value which will be used as the source for data binding. For example, the update action does something like this…​

  1. class RestfulController<T> {
  2. def update() {
  3. T instance = // retrieve instance from the database...
  4. instance.properties = getObjectToBind()
  5. // ...
  6. }
  7. // ...
  8. }

By default the getObjectToBind() method returns the request object. When the request object is used as the binding source, if the request has a body then the body will be parsed and its contents will be used to do the data binding, otherwise the request parameters will be used to do the data binding. Subclasses of RestfulController may override the getObjectToBind() method and return anything that is a valid binding source, including a Map or a DataBindingSource. For most use cases binding the request is appropriate but the getObjectToBind() method allows for changing that behavior where desired.

Using custom subclass of RestfulController with Resource annotation

You can also customize the behaviour of the controller that backs the Resource annotation.

The class must provide a constructor that takes a domain class as it’s argument. The second constructor is required for supporting Resource annotation with readOnly=true.

This is a template that can be used for subclassed RestfulController classes used in Resource annotations:

  1. class SubclassRestfulController<T> extends RestfulController<T> {
  2. SubclassRestfulController(Class<T> domainClass) {
  3. this(domainClass, false)
  4. }
  5. SubclassRestfulController(Class<T> domainClass, boolean readOnly) {
  6. super(domainClass, readOnly)
  7. }
  8. }

You can specify the super class of the controller that backs the Resource annotation with the superClass attribute.

  1. import grails.rest.*
  2. @Resource(uri='/books', superClass=SubclassRestfulController)
  3. class Book {
  4. String title
  5. static constraints = {
  6. title blank:false
  7. }
  8. }