10.11.2 Implementing a Custom Renderer

If you want even more control of the rendering or prefer to use your own marshalling techniques then you can implement your own Renderer instance. For example below is a simple implementation that customizes the rendering of the Book class:

  1. package myapp
  2. import grails.rest.render.*
  3. import grails.web.mime.MimeType
  4. class BookXmlRenderer extends AbstractRenderer<Book> {
  5. BookXmlRenderer() {
  6. super(Book, [MimeType.XML,MimeType.TEXT_XML] as MimeType[])
  7. }
  8. void render(Book object, RenderContext context) {
  9. context.contentType = MimeType.XML.name
  10. def xml = new groovy.xml.MarkupBuilder(context.writer)
  11. xml.book(id: object.id, title:object.title)
  12. }
  13. }

The AbstractRenderer super class has a constructor that takes the class that it renders and the MimeType(s) that are accepted (via the ACCEPT header or file extension) for the renderer.

To configure this renderer, simply add it is a bean to grails-app/conf/spring/resources.groovy:

  1. beans = {
  2. bookRenderer(myapp.BookXmlRenderer)
  3. }

The result will be that all Book instances will be rendered in the following format:

  1. <book id="1" title="The Stand"/>
If you change the rendering to a completely different format like the above, then you also need to change the binding if you plan to support POST and PUT requests. Grails will not automatically know how to bind data from a custom XML format to a domain class otherwise. See the section on "Customizing Binding of Resources" for further information.

Container Renderers

A grails.rest.render.ContainerRenderer is a renderer that renders responses for containers of objects (lists, maps, collections etc.). The interface is largely the same as the Renderer interface except for the addition of the getComponentType() method, which should return the "contained" type. For example:

  1. class BookListRenderer implements ContainerRenderer<List, Book> {
  2. Class<List> getTargetType() { List }
  3. Class<Book> getComponentType() { Book }
  4. MimeType[] getMimeTypes() { [ MimeType.XML] as MimeType[] }
  5. void render(List object, RenderContext context) {
  6. ....
  7. }
  8. }