DevOps Zone is brought to you in partnership with:

Hi all, my name is Hubert A. Klein Ikkink. Not a very common name, right? To make things easier I just picked the first letters of my firstname and surname and came up with haki. So there you have it, now I am also known as Mr. Haki or mrhaki for short. You can read more blog postings at I am a passionate Groovy and Java developer based in Tilburg, The Netherlands. My goal is to write clean, elegant, user-centered and high quality software. You can find me on Google+ and Twitter. Hubert is a DZone MVB and is not an employee of DZone and has posted 167 posts at DZone. You can read more from them at their website. View Full User Profile

Grails Goodness: Customize Resource Mappings

  • submit to reddit

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 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.

Published at DZone with permission of Hubert Klein Ikkink, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)