views:

532

answers:

1

Let's say we have a grails web application exposing several resources.

  • tags
  • urls
  • users

The application has a classical web-interface which the users interact with and some administration. We want to expose the resources from the application to clients via a RESTful API and we don't want that part of the app to clutter up the controllers and code we already have. So we came up with the following:

If the web interface offers host/app_path/url/[list|show|create] we want the REST API to be at /host/app_path/rest/url.

So we ended up with the following UrlMappings file:

class UrlMappings {
static mappings = {
 "/$controller/$action?/$id?"{

 }

 /* adding new urls and listing them */
 "/rest/url"{
  controller = "urlRest"
  action = [POST: "save", PUT: "save", GET: "list", DELETE:"error"]
 }

 /* accessing a single url */
 "/rest/url/$id"{
  controller = "urlRest"
  action = [POST: "update", PUT: "update", GET: "show", DELETE: "delete"]
 }

 /* non-crud stuff on urls */
 "/rest/url/$action?/$id?"{
  controller = "urlRest"
 }

 "/"(view:"/index")
 "500"(view:'/error')
}
}

The problem is, that this isn't exactly the most DRY thing here. It gets worse as we add more resources such as tags. They would translate to yet another three blocks of very similar code...

The non-crud functions will be things like searching with specific criterions and such...

We tried generating the mapping closures with a loop, but without success. Are we completely on the wrong track here?

+6  A: 

I would recommend the following mapping:

"/rest/url/$id?"(resource:"urlRest")

Below is the HTTP method to action mapping that this would create for the urlRestController:

GET         show
PUT         update
POST        save
DELETE      delete

I see why you might want to map /rest/url POST to save and /rest/url/id PUT to update, but that goes against the meaning of those verbs. A PUT should be the only way to add a new url and POST the only way to update a url. Doing it the way you have laid out would work and might be the best way if your constraint is to keep your current controller code untouched. However, my guess is that you controller might already be coded to handle the default mappings just fine (update/delete give error if no id, show redirects to list if no id, etc.).

John Wagenleitner
Ahh, the PUT/POST thing :D
kungfoo