REST

Customize Resource Mappings

Since Grails 2.3 it is very easy to define RESTful URL mappings for a controller. We can use the resources and resource attribute and use a controller name as the value. Grails will then automatically create a couple of URL mappings. Suppose we use the following mapping in grails-app/conf/UrlMappings.groovy: "/api/users"(resources: 'user'), then the following mappings are automatically created:

"/api/users/create"(controller: 'user', action: 'create', method: 'GET')
"/api/users/(*)/edit"(controller: 'user', action: 'edit', method: 'GET')
"/api/users(.(*))?"(controller: 'user', action: 'save', method: 'POST')
"/api/users(.(*))?"(controller: 'user', action: 'index', method: 'GET')
"/api/users/(*)(.(*))?"(controller: 'user', action: 'delete', method: 'DELETE')
"/api/users/(*)(.(*))?"(controller: 'user', action: 'update', method: 'PUT')
"/api/users/(*)(.(*))?"(controller: 'user', action: 'show', method: 'GET')

When we use the resource attribute to define a mapping like "/api/user"(resource: 'user') the following mappings are created by Grails:

"/api/user/create"(controller: 'user', action: 'create', method: 'GET')
"/api/user/edit"(controller: 'user', action: 'edit', method: 'GET')
"/api/user(.(*))?"(controller: 'user', action: 'delete', method: 'DELETE')
"/api/user(.(*))?"(controller: 'user', action: 'update', method: 'PUT')
"/api/user(.(*))?"(controller: 'user', action: 'save', method: 'POST')

Well there are a lot of mappings created for us! But maybe we don’t need all created mappings in our application. For example the mappings with /create and /edit are created by Grails to support also a UI variant for the controller actions, but we might want to leave them out when we only deal with JSON or XML payloads. We can use the includes and excludes attributes on the mapping to explicitly define which actions we want to support in our controller.

In the following sample UrlMappings.groovy configuration we exclude the create and edit actions in the first mapping. In the second mapping we only include the show and index actions:

// File: grails-app/conf/UrlMappings.groovy
import static org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingEvaluator.*

import org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingEvaluator

class UrlMappings {

    static mappings = {
        // Exclude the 'create' and 'edit' actions for the 
        // automatically created mappings.
        "/api/users"(resources: 'user', excludes: [ACTION_CREATE, ACTION_EDIT])

        // Include only the 'index' and 'show' actions for the 
        // automatically created mappings.
        "/api/products"(resources: 'product', includes: [ACTION_INDEX, ACTION_SHOW])
    }
}

Code written with Grails 2.3.

Original blog post written on November 15, 2013.

Pretty Print XML and JSON Output

If our Grails application renders XML or JSON output we can set configuration properties to enable pretty printing. This can be useful in for example in the development environment where we enable pretty printing and disable it for other environments. We set the configuration property grails.converters.default.pretty.print with the value true to enable pretty printing for both XML and JSON output. If we only want to pretty print XML we use the property grails.converters.xml.pretty.print and for JSON we use grails.converters.json.pretty.print.

First we look at the XML and JSON output when we don’t enable pretty printing for a simple book resource:

<?xml version="1.0" encoding="UTF-8"?><book id="1"><isbn>0451169514</isbn>\
<numberOfPages>1104</numberOfPages><title>It</title></book>
{"class":"com.mrhaki.grails.sample.Book","id":1,"isbn":"0451169514","numberOfPages":1104,"title":"It"}

Now we get the same book resource but with the following grails-app/conf/Config.groovy snippet:

...
environments {
    development {
        // Enable pretty print for JSON.
        //grails.converters.json.pretty.print = true

        // Enable pretty print for XML.
        //grails.converters.xml.pretty.print = true

        // Enable pretty print for JSON and XML.
        grails.converters.default.pretty.print = true
        ...
    }
}        
...

The following output shows how the representation is formatted nicely:

<?xml version="1.0" encoding="UTF-8"?>
<book id="1">
  <isbn>
    0451169514
  </isbn>
  <numberOfPages>
    1104
  </numberOfPages>
  <title>
    It
  </title>
</book>
{
  "class": "com.mrhaki.grails.sample.Book",
  "id": 1,
  "isbn": "0451169514",
  "numberOfPages": 1104,
  "title": "It"
}

Code written with Grails 2.3.2.

Original blog post written on November 20, 2013.

Include Domain Version Property in JSON and XML Output

We can include the version property of domain classes in rendered JSON or XML output. By default the version property is not included in generated XML and JSON. To enable inclusion of the version property we can set the configuration property grails.converters.domain.include.version with the value true. With this property for both XML and JSON the version property is included in the output. To only enable this for XML we use the property grails.converters.xml.domain.include.version and for JSON we use the property grails.converters.json.domain.include.version.

The following snippet is from grails-app/conf/Config.groovy where the properties are defined:

...
// Include version for JSON generated output.
//grails.converters.json.domain.include.version = true

// Include version for XML generated output.
//grails.converters.xml.domain.include.version = true

// Include version for both XML and JSON output.
grails.converters.domain.include.version = true
...

The following samples show a representation of a book resources, which is a domain class and we see the version property as attribute of the book XML tag.

<?xml version="1.0" encoding="UTF-8"?>
<book id="1" version="0">
  <isbn>
    0451169514
  </isbn>
  <numberOfPages>
    1104
  </numberOfPages>
  <title>
    It
  </title>
</book>

In JSON the version is included as property.

{
  "class": "com.mrhaki.grails.sample.Book",
  "id": 1,
  "version": 0,
  "isbn": "0451169514",
  "numberOfPages": 1104,
  "title": "It"
}

Code written with Grails 2.3.2.

Original blog post written on November 20, 2013.

Enable Accept Header for User Agent Requests

Especially when we use Grails to create a RESTful API we want to enable the request header Accept, so Grails can do content negotiation based on the value in the header. For example we could use the request header Accept: application/json to get a JSON response. Grails will look at the boolean configuration property grails.mime.use.accept.header to see if the Accept header must be parsed. The default value is true so the Accept header is used. But there is another property which determines if the Accept header is used: grails.mime.disable.accept.header.userAgents. The value must contain a list or a regular expression pattern of user agents which are ignored for the Accept header. The default value is ~/(Gecko(?i)|WebKit(?i)|Presto(?i)|Trident(?i))/. So for any request from these user agents, mostly our web browser, the Accept header is ignored.

If we use REST web services test tools from our browser, for example Postman, then any Accept header we set in the tool is ignored by Grails. We must change the value of the configuration property grails.mime.disable.accept.header.userAgents to for example an empty list. Then we know for every request send to our Grails application, either from a web browser or command-line tool like curl, the Accept header is interpreted by Grails.

The following sample shows how we make sure the Accept header is always used:

// File: grails-app/conf/Config.groovy
...
grails.mime.use.accept.header = true // Default value is true.
grails.mime.disable.accept.header.userAgents = []
...

Written with Grails 2.4.1.

Original blog post written on July 08, 2014.

Custom Controller Class with Resource Annotation

In Grails we can apply the @Resource AST (Abstract Syntax Tree) annotation to a domain class. Grails will generate a complete new controller which by default extends grails.rest.RestfulController. We can use our own controller class that will be extended by the @Resource transformation. For example we might want to disable the delete action, but still want to use the @Resource transformation. We simply write a new RestfulController implementation and use the superClass attribute for the annotation to assign our custom controller as the value.

First we write a new RestfulController and we override the delete action. We return a HTTP status code 405 Method not allowed:

// File: grails-app/controllers/com/mrhaki/grails/NonDeleteRestfulController.groovy
package com.mrhaki.grails

import grails.rest.*

import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED

/**
 * Custom RestfulController where we disable the delete action.
 */
class NonDeleteRestfulController<T> extends RestfulController<T> {

    // We need to provide the constructors, so the 
    // Resource transformation works.
    NonDeleteRestfulController(Class<T> domainClass) {
        this(domainClass, false)
    }

    NonDeleteRestfulController(Class<T> domainClass, boolean readOnly) {
        super(domainClass, readOnly)
    }

    @Override
    def delete() {
        // Return Method not allowed HTTP status code.
        render status: METHOD_NOT_ALLOWED
    }
    
}

Next we indicate in the @Resource annotation with the superClass attribute that we want to use the NonDeleteRestfulController:

// File: grails-app/domain/com/mrhaki/grails/User.groovy
package com.mrhaki.grails

import grails.rest.*

@Resource(uri = '/users', superClass = NonDeleteRestfulController)
class User {

    String username
    String lastname
    String firstname
    String email

    static constraints = {
        email email: true
        lastname nullable: true
        firstname nullable: true
    }

}

When we access the resource /users/{id} with the HTTP DELETE method we get a 405 Method Not Allowed response status code.

Written with Grails 2.4.2.

Original blog post written on July 09, 2014.

Change Response Formats in RestfulController

We can write a RESTful application with Grails and define our API in different ways. One of them is to subclass the grails.rest.RestfulController. The RestfulController already contains a lot of useful methods to work with resources. For example all CRUD methods (save/show/update/delete) are available and are mapped to the correct HTTP verbs using a URL mapping with the resource(s) attribute.

We can define which content types are supported with the static variable responseFormats in our controller. The variable should be a list of String values with the supported formats. The list of supported formats applies to all methods in our controller. The names of the formats are defined in the configuration property grails.mime.types. We can also use a Map notation with the supportedFormats variable. The key of the map is the method name and the value is a list of formats.

// File: grails-app/controllers/com/mrhaki/grails/UserApiController.groovy
package com.mrhaki.grails

import grails.rest.*

class UserApiController extends RestfulController {

    // Use Map notation to set supported formats
    // per action.
    static responseFormats = [
        index: ['xml', 'json'],  // Support both XML, JSON
        show: ['json']           // Only support JSON
    ]

    // We make the resource read-only in
    // the constructor.
    UserApiController() {
        super(User, true /* read-only */)
    }

}

We can also specify supported formats per action using the respond method in our controller. We can define the named argument formats followed by a list of formats when we invoke the respond method. In the following controller we override the index and show methods and use the formats attribute when we use the respond method:

// File: grails-app/controllers/com/mrhaki/grails/UserApiController.groovy
package com.mrhaki.grails

import grails.rest.*

class UserApiController extends RestfulController {

    // We make the resource read-only in
    // the constructor.
    UserApiController() {
        super(User, true /* read-only */)
    }

    @Override
    def index(Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond listAllResources(params), formats: ['xml', 'json']
    }

    @Override
    def show() {
        respond queryForResource(params.id), formats: ['json']
    }

}

Code written with Grails 2.4.2.

Original blog post written on July 09, 2014.

Register Custom Marshaller Using ObjectMarshallerRegisterer

When we convert data to JSON or XML (or any other format actually) in our Grails application we can register custom marshallers. These marshallers must contain the logic to convert an input object to a given format. For example we could have a book class and we want to convert it to our own JSON format. We have different options in Grails to achieve this, but for now we will create a custom marshaller class CustomBookMarshaller. This class must implement the ObjectMarshaller<C> interface. The generic type is the converter the marshaller is for and is in most cases either grails.converters.XML or grails.converters.JSON.

Next we must make sure Grails uses our custom marshaller and we must register it. In the Grails documentation is explained how to do this via grails-app/conf/Bootstrap.groovy where we invoke for example JSON.registerMarshaller(new CustomBookMarshaller()). Or via resources.groovy in the directory grails-app/conf/spring where we must write an extra component with a method annotated @PostConstruct where JSON.registerMarshaller(new CustomBookMarshaller()) is invoked.

But there is also another way using ObjectMarshallerRegisterer. We can find this class in the package org.codehaus.groovy.grails.web.converters.configuration. This is a Spring bean just for configuring extra marshallers. The bean has a priority property we can use to define the priority for this marshaller. Grails will use a marshaller with the highest priority if for the same class multiple marshallers are defined. We can assign a marshaller to the marshaller property. And finally we must set the converter class, for example grails.converters.XML or grails.converters.JSON with the converter property.

In our grails-app/conf/spring/resources.groovy file we define a new instance of ObjectMarshallerRegisterer and assign the appropriate property values. The name of the bean in resources.groovy is not important, but we must make sure there is no name class with other Spring configured beans. Grails looks for all beans of type ObjectMarshallerRegisterer during marshaller configuration and use the information we provide.

// File: grails-app/conf/spring/resources.groovy
import com.mrhaki.json.CustomBookMarshaller
import grails.converters.JSON
import org.codehaus.groovy.grails.web.converters.configuration.\
ObjectMarshallerRegisterer

beans = {

    // The name is not important. The type is picked up 
    // by Grails and must be ObjectMarshallerRegisterer.
    customBookJsonMarshaller(ObjectMarshallerRegisterer) {
        // Assign custom marshaller instance.
        marshaller = new CustomBookMarshaller()

        // Set converter class type.
        converterClass = JSON

        // Optional set priority. Default value is 0.
        priority = 1
    }

}

Code written with Grails 2.3.2

Original blog post written on November 21, 2013.

Using Converter Named Configurations with Default Renderers

Sometimes we want to support in our RESTful API a different level of detail in the output for the same resource. For example a default output with the basic fields and a more detailed output with all fields for a resource. The client of our API can then choose if the default or detailed output is needed. One of the ways to implement this in Grails is using converter named configurations.

Grails converters, like JSON and XML, support named configurations. First we need to register a named configuration with the converter. Then we can invoke the use method of the converter with the name of the configuration and a closure with statements to generate output. The code in the closure is executed in the context of the named configuration.

The default renderers in Grails, for example DefaultJsonRenderer, have a property namedConfiguration. The renderer will use the named configuration if the property is set to render the output in the context of the configured named configuration. Let’s configure the appropriate renderers and register named configurations to support the named configuration in the default renderers.

In our example we have a User resource with some properties. We want to support short and details output where different properties are included in the resulting format.

First we have our resource:

// File: grails-app/domain/com/mrhaki/grails/User.groovy
package com.mrhaki.grails

import grails.rest.*

// Set URI for resource to /users.
// The first format in formats is the default
// format. So we could use short if we wanted
// the short compact format as default for this 
// resources.
@Resource(uri = '/users', formats = ['json', 'short', 'details'])
class User {

    String username
    String lastname
    String firstname
    String email

    static constraints = {
        email email: true
        lastname nullable: true
        firstname nullable: true
    }

}

Next we register two named configurations for this resource in our Bootstrap:

// File: grails-app/conf/Bootstrap.groovy
class Bootstrap {

    def init = { servletContext ->
        ...
        JSON.createNamedConfig('details') {
            it.registerObjectMarshaller(User) { User user ->
                final String fullname = [user.firstname, user.lastname].join(' ')
                final userMap = [
                        id      : user.id,
                        username: user.username,
                        email   : user.email,
                ]
                if (fullname) {
                    userMap.fullname = fullname
                }
                userMap
            }
            // Add for other resources a marshaller within
            // named configuration.
        }

        JSON.createNamedConfig('short') {
            it.registerObjectMarshaller(User) { User user ->
                final userMap = [
                        id      : user.id,
                        username: user.username
                ]
                userMap
            }
            // Add for other resources a marshaller within
            // named configuration.
        }    
        ...
    }
...
}

Now we must register custom renderers for the User resource as Spring components in resources:

// File: grails-app/conf/spring/resources.groovy
import com.mrhaki.grails.User
import grails.rest.render.json.JsonRenderer
import org.codehaus.groovy.grails.web.mime.MimeType

beans = {
    // Register JSON renderer for User resource with detailed output.
    userDetailsRenderer(JsonRenderer, User) {
        // Grails will compare the name of the MimeType
        // to determine which renderer to use. So we 
        // use our own custom name here. 
        // The second argument, 'details', specifies the
        // supported extension. We can now use
        // the request parameter format=details to use
        // this renderer for the User resource.
        mimeTypes = [
            new MimeType('application/vnd.com.mrhaki.grails.details+json', 'details')
        ]
        
        // Here we specify the named configuration
        // that must be used by an instance
        // of this renderer. See Bootstrap.groovy
        // for available registered named configuration.
        namedConfiguration = 'details'
    }

    // Register second JSON renderer for User resource with compact output.
    userShortRenderer(JsonRenderer, User) {
        mimeTypes = [
            new MimeType('application/vnd.com.mrhaki.grails.short+json', 'short')
        ]

        // Named configuration is different for short
        // renderer compared to details renderer.
        namedConfiguration = 'short'
    }

    // Default JSON renderer as fallback.
    userRenderer(JsonRenderer, User) {
        mimeTypes = [new MimeType('application/json', 'json')]
    }

}

We have defined some new mime types in grails-app/conf/spring/resources.groovy, but we must also add them to our grails-app/conf/Config.groovy file:

// File: grails-app/conf/spring/resources.groovy
...
grails.mime.types = [
    ...
    short   : ['application/vnd.com.mrhaki.grails.short+json', 'application/json'],
    details : ['application/vnd.com.mrhaki.grails.details+json', 'application/json'],
]
...

Our application is now ready and configured. We mostly rely on Grails content negotiation to get the correct renderer for generating our output if we request a resource. Grails content negotiation can use the value of the request parameter format to find the correct mime type and then the correct renderer. Grails also can check the Accept request header or the URI extension, but for our RESTful API we want to use the format request parameter.

If we invoke our resource with different formats we see the following results:

$ curl -X GET http://localhost:8080/rest-sample/users/1
{
    "class": "com.mrhaki.grails.User",
    "id": 1,
    "email": "hubert@mrhaki.com",
    "firstname": "Hubert",
    "lastname": "Klein Ikkink",
    "username": "mrhaki"
}
$ curl -X GET http://localhost:8080/rest-sample/users/1?format=short
{
    "id": 1,
    "username": "mrhaki"
}
$ curl -X GET http://localhost:8080/rest-sample/users/1?format=details
{
    "id": 1,
    "username": "mrhaki",
    "email": "hubert@mrhaki.com",
    "fullname": "Hubert Klein Ikkink"
}

Code written with Grails 2.4.2.

Original blog post written on July 11, 2014.

Rendering Partial RESTful Responses

Grails 2.3 added a lot of support for RESTful services. For example we can now use a respond() method in our controllers to automatically render resources. The respond() method accepts a resource instance as argument and a map of attributes that can be passed. We can use the includes and excludes keys of the map to pass which fields of our resources need to be included or excluded in the response. This way we can render partial responses based on a request parameter value.

First we start with a simple domain class Book:

// File: grails-app/domain/com/mrhaki/grails/rest/Book.groovy
package com.mrhaki.grails.rest

class Book {

    String title
    String isbn
    int numberOfPages

}

Next we create a controller BookApiController, which we extend from the RestfulController so we already get a lot of basic functionality to render an instance of Book. We overwrite the index() and show() methods, because these are used to display our resource. We use the request parameter fields to define a comma separated list of fields and pass it to the includes attribute of the map we use with the respond() method. Notice we also set the excludes attribute to remove the class property from the output.

// File: grails-app/controllers/com/mrhaki/grails/rest/BookApiController.groovy
package com.mrhaki.grails.rest

import grails.rest.RestfulController

class BookApiController extends RestfulController<Book> {

    // We support both JSON and XML.
    static responseFormats = ['json', 'xml']

    BookApiController() {
        super(Book)
    }

    @Override
    def show() {
        // We pass which fields to be rendered with the includes attributes,
        // we exclude the class property for all responses.
        respond queryForResource(params.id), 
					[includes: includeFields, excludes: ['class']]
    }

    @Override
    def index(final Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond listAllResources(params), 
        			[includes: includeFields, excludes: ['class']]
    }

    private getIncludeFields() {
        params.fields?.tokenize(',')
    }

}

Next we define a mapping to our controller in UrlMappings.groovy:

// File: grails-app/conf/UrlMappings.groovy

class UrlMappings {
    static mappings = {
...
        "/api/book"(resources: "bookApi")
...
    }
}

We are now almost done. We only have to register a new Spring component for the collection rendering of our Book resources. This is necessary to allow the usage of the includes and excludes attributes. These attributes are passed to the so-called componentType of the collection. In our case the componentType is the Book class.

// File: grails-app/conf/spring/resources.groovy

import com.mrhaki.grails.rest.Book
import grails.rest.render.json.JsonCollectionRenderer
import grails.rest.render.xml.XmlCollectionRenderer

beans = {
    // The name of the component is not relevant. 
    // The constructor argument Book sets the componentType for
    // the collection renderer.
    jsonBookCollectionRenderer(JsonCollectionRenderer, Book)
    xmlBookCollectionRenderer(XmlCollectionRenderer, Book)

    // Uncomment the following to register collection renderers
    // for all domain classes in the application.
    // for (domainClass in grailsApplication.domainClasses) {
    //     "json${domainClass.shortName}CollectionRenderer(JsonCollectionRenderer, 
    //	    											   domainClass.clazz)
    //     "xml${domainClass.shortName}CollectionRenderer(XmlCollectionRenderer, 
    //                                                    domainClass.clazz)
    // }
}

Now it is time to see our partial responses in action using some simple cURL invocations:

$ curl -X GET -H "Accept:application/json" \
http://localhost:9000/custom-renderers/api/book?fields=title
[
  {
    "title": "It"
  },
  {
    "title": "The stand"
  }
]
$ curl -X GET -H "Accept:application/xml" \
http://localhost:9000/custom-renderers/api/book?fields=title,isbn
<?xml version="1.0" encoding="UTF-8"?>
<list>
  <book>
    <isbn>
      0451169514
    </isbn>
    <title>
      It
    </title>
  </book>
  <book>
    <isbn>
      0307743683
    </isbn>
    <title>
      The stand
    </title>
  </book>
</list>
$ curl -X GET -H "Accept:application/json" \
http://localhost:9000/custom-renderers/api/book/1
{
  "id": 1,
  "isbn": "0451169514",
  "numberOfPages": 1104,
  "title": "It"
}
$ curl -X GET -H "Accept:application/json" \
http://localhost:9000/custom-renderers/api/book/1?fields=isbn,id
{
  "id": 1,
  "isbn": "0451169514"
}

Code written with Grails 2.3.2

Original blog post written on December 09, 2013.

Customize Root Element Name Collections for XML Marshalling

When we convert a List or Set to XML using the Grails XML marshalling support the name of the root element is either <list> or <set>. We can change this name by extending the CollectionMarshaller in the package org.codehaus.groovy.grails.web.converters.marshaller.xml. We must override the method supports() to denote the type of collection we want to customize the root element name for. And we must override the method getElementName() which returns the actual name of the root element for the List or Set.

Let’s first see the default output of a collection of Book domain classes. In a controller we have the following code:

package com.mrhaki.grails.sample

class SampleController {
    def list() {
        // To force 404 when no results are found
        // we must return null, because respond method
        // checks explicitly for null value and 
        // not Groovy truth.
        respond Book.list() ?: null
    }
}

The XML output is:

<?xml version="1.0" encoding="UTF-8"?>
<list>
  <book id="1" version="0">
    <author id="1" />
    <isbn>
      0451169514
    </isbn>
    <numberOfPages>
      1104
    </numberOfPages>
    <title>
      It
    </title>
  </book>
  <book id="2" version="0">
    <author id="1" />
    <isbn>
      0307743683
    </isbn>
    <numberOfPages>
      1472
    </numberOfPages>
    <title>
      The stand
    </title>
  </book>
</list>

To change the element name list to books we add the following code to the init closure in grails-app/app/BootStrap.groovy:

// File: grails-app/conf/BootStrap.groovy
import com.mrhaki.grails.sample.Book
import grails.converters.XML
import org.codehaus.groovy.grails.web.converters.marshaller.xml.CollectionMarshaller

class BootStrap {

    def init = { servletContext ->
        // Register custom collection marshaller for List with Book instances.
        // The root element name is set to books.
        XML.registerObjectMarshaller(new CollectionMarshaller() {
            @Override
            public boolean supports(Object object) {
                // We know there is at least one result, 
                // otherwise the controller respond method
                // would have returned a 404 response code.
                object instance of List && object.first() instance of Book
            }

            @Override
            String getElementName(final Object o) {
                'books'
            }
        })
    }
}

Now when we render a list of Book instances we get the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book id="1" version="0">
    <author id="1" />
    <isbn>
      0451169514
    </isbn>
    <numberOfPages>
      1104
    </numberOfPages>
    <title>
      It
    </title>
  </book>
  <book id="2" version="0">
    <author id="1" />
    <isbn>
      0307743683
    </isbn>
    <numberOfPages>
      1472
    </numberOfPages>
    <title>
      The stand
    </title>
  </book>
</books>

To customize the XML marshaling output for Map collections we must subclass MapMarshaller in the packag org.codehaus.groovy.grails.web.converters.marshaller.xml.

Code written with Grails 2.3.2

Original blog post written on February 06, 2014.