REST Service XML Output in Grails via Content Negotiation

The content negotiation feature in Grails is pretty cool. In a nutshell, it allows you to return different formats based on the request of your page.

A recent project I worked on used Grail’s ability to generate CRUD as GSP pages to provide a basic CMS service, and an Adobe Flex front-end that communicated with Grails via REST services. We needed a solution that will preserve the original GSP html output, as well as the ability to return the data as XML for the REST layer.

Enabling the XMLfication of my components turned out to be dead simple with Grails. Here is what I did:

1. generate the templates by calling grails install-templates

2. open the file src/template/scaffolding/Controller.groovy

Add this line on the top:
import grails.converters.*

Modify the list command into :
 def list = {
        if(!params.max) params.max = 10
            html{ [ ${propertyName}List: ${className}.list( params ) ] }
            xml(contentType:"text/xml"){ render ${className}.list( params ) as XML  }

Modify the show command to be 
    def show = {
                def ${propertyName} = ${className}.get( )
                if(!${propertyName}) {
                    flash.message = "${className} not found with id \${}"
                else { return [ ${propertyName} : ${propertyName} ] }
            xml(contentType:"text/xml"){ render  ${className}.get( ) as XML }

Save the file. Now, every controller that I create will have the ability to render the response as an XML file, which I then parse with my FLEX front end using FLEX’s awesome e4x capabilities

Let’s say we now create a new class blah ( grails create-domain-class blah; grails generate-all blah ). You should see a html list when you do grails run-app and navigate to http://localhost:8080/myapp/blah/list. However, if you call http://localhost:8080/myapp/blah/list.xml or http://localhost:8080/myapp/blah/list?format=xml, you will get an XML result

Let me break that down a bit, the Grails withFormat command parses our request headers for us, and when I call list.xml, it uses that URI to resolve into the right format.  The grails converters then enable to return the output as XML. Simple, elegant and really really cool.

You can even go further, and add new formats with something like

    json(){ render ${className}.list(params) as JSON }

or even create new RSS feeds with the Feeds Plugin with something like

    rss(){ render(feedType:"rss", feedVersion:"2.0") ... 

( see this section for how to do this )

For our project, we only needed to do a display of the objects in XML, but the Grails documentation shows how to do xml submission robustly and has better examples of error checking ( which we do in the client level, so not needed at the server level ). But hopefully this gives a good starting point on how to do REST in Grails.

Have I mentioned how much I love Grails yet?


6 thoughts on “REST Service XML Output in Grails via Content Negotiation

  1. Pingback: SEO for Flex RIA with Grails (overview) « Dump brain here : Flex, AIR, Grails, Groovy, Facebook and all that jazz

  2. Pingback: A simple ActionScript / Flex REST client « Dump brain here : Flex, AIR, Grails, Groovy, Facebook and all that jazz

  3. Matt

    Does this work with dynamic scaffolding? It doesn’t seem to. I tried your instructions (save for general-all) and it doesn’t seem to work. Doesn’t dynamic scaffolding read from src/templates/scaffolding/Controller.groovy? Here’s my modified code:

    Doesn’t work in Firefox 3 or Safari on Leopard with Grails 1.0.3 and Java 5.


  4. Tomas Lin Post author

    Yes, it seems that this is not supported by default scaffolding. You would have to dig in deeper in the way the default scaffolding reads templates or submit a JIRA

  5. Pingback: Excentrix Web » Blog Archive » A Grails, RESTful Services Update

  6. Pingback: grails的controller和action那点事 | 陈霞光的博客

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s