27

I was wondering what would be the best approach to make a Grails app offer a RESTful API (some CRUD actions mainly) that can be used by a web service, e.g. when you want to build a corresponding iOS app to your browser-based app or anything else.

I thought of building a separate part in my Grails application that takes calls from www.mywebapp.com/api/someAction so that I can reuse the Service layer. How would I do the URL mapping then? Only having one big ApiController does not sound very groovy.

Or is there any better approach I did not know of? This approach must support something like OAuth to authenticate the user who is calling the Web service.

cdeszaq
  • 30,869
  • 25
  • 117
  • 173
Sebastian Wramba
  • 10,087
  • 8
  • 41
  • 58
  • See this question and answer: [RESTful grails application: DRYing up UrlMapping][1] [1]: http://stackoverflow.com/questions/955603/restful-grails-application-drying-up-urlmapping – Jay Prall Mar 29 '12 at 21:18
  • Thanks, but then I can only have a single controller that handles it? Or could I map `/rest/foo/$action/$id` e.g. to the `RestFooController`? Would that be possible? – Sebastian Wramba Mar 30 '12 at 09:13
  • Yes, you _could_ map it like that. – cdeszaq May 02 '12 at 18:23

4 Answers4

58

Grails can definitely provide a REST api, but the level of difficulty in doing so varies depending on how mature (aka. how RESTful) you want the API to be.

Basic REST

Getting a basic level of RESTfullness, where you are manipulating json or xml representations of resources using the full span of HTTP verbs and leveraging the HTTP response codes, is pretty easy. There are 3 main pieces to getting that in place:

  1. URL mapping

    Here's an example of how I wrote my URL mappings on a recent project to allow for more RESTful URLs:

    // RESTful list mapping
    name restEntityList: "/$controller"(parseRequest: true) {
        action = [GET: "list", POST: "save"]
    }
    
    // RESTful entity mapping
    name restEntity: "/$controller/$id"(parseRequest: true) {
        action = [GET: "show", PUT: "update", POST: "update", DELETE: "delete"]
        constraints {
            id matches: /\d+/
        }
    }
    
  2. Content negotiation

    The 3 different ways that Grails can handle content negotiation make the framework very flexible, allowing you to support a much broader range of clients who may not be able to set things like the Accept HTTP header.

    You can use the content negotiation to respond to different requests in different ways using the withFormat block based on what the client has indicated they want. This powerful ability can also be used to version your API, much like how Github does.

  3. Response status

    HTTP already has a great response mechanism built into it that allows you to leverage innate abilities in the architecture, like cacheability and indemnipotent operations. While some web browsers don't handle certain response codes very gracefully, client applications using your API can use them to greatly simplify their internal code.

DRY REST

One of the best ways to make your application RESTful and keep it DRY at the same time is to leverage the controller scaffolding as much as possible, since CRUD is essentially the same for all domain objects. This article on making the default controller more RESTful, and this article on simplifying the default controller are both great resources for getting more power from the scaffolding.

Advanced REST

Once you get to that point, you have a pretty functional REST API for your grails application. You can do all basic CRUD operations and the resources are fairly easy to work with.

The next levels of the ladder to a true RESTful hypermedia API, however, are much harder to attain. Fixing this is on the road map for Grails, but currently it's rather painful. These pieces are:

  1. Hypermedia resources
  2. Content types
  3. Versioning

Thankfully, there is a plugin that makes defining custom marshallers very easy, which allows us to fairly easily cover those three remaining pieces of the REST puzzle.

Finally, there is the aspect of securing the whole thing. In general, Spring Security will hold you in good stead as far as securing user-access to your api. Since most API access is from an application, and isn't user-visible, basic or digest authentication is usually the simplest way to go. There is an OAuth plugin that builds on Spring Security. I have not personally used it so I can't vouch for it's stability, but it looks pretty good to me.

In general, Grails is flexible and powerful enough to do REST very, very well, but the work has not been done yet to make it do REST cleanly out-of-the-box.

cdeszaq
  • 30,869
  • 25
  • 117
  • 173
  • Wow, I think, that covers it all. Thank you so much! – Sebastian Wramba May 02 '12 at 19:09
  • 4
    I'm glad to help. Grails is a great framework, and REST is, in my opinion, simply the only architecture that makes sense for things on the web. Feel free to pop in to the #grails IRC channel on Freenode if you have more specific questions or are looking to help out and contribute back to the community. – cdeszaq May 02 '12 at 19:16
  • For those just tuning in, Grails v2.3 is going to get a major REST boost, so stay tuned for more details! – cdeszaq May 06 '13 at 12:51
  • The Github link is broken – biniam Apr 27 '16 at 14:45
6

the grails documentation has a good walk though on setting up a RESTfull api

http://grails.org/doc/latest/guide/webServices.html#13.1

nate_weldon
  • 2,289
  • 1
  • 26
  • 32
1
  • url mapping:

    "/api/element/$version/$master" { controller = "element" action = [GET:"show"] }

This will map the http get to the show method of the controller element.

  • i.e. the show method:

DRY: The api is probably the same logic as the application. The difference is content negociation.

...

def show = {
    def elements = elementService.findByMasterVersion(params.master, params.version)
    withFormat {
        xml {
            render(status:200,text:elements as XML, contentType:"text/xml",encoding:"UTF-8")
        }
        json { ... }
        html { ... }
    }
}
  • Oauth is pretty damn complicated to implement and seems overkill for a lot of situation.
moskiteau
  • 1,104
  • 11
  • 19
1

You can map it anyway, use any url structure. Grails UrlMapping is pretty flexible, it's only default behavior to map to /$controller/$action, but you can use your own mapping, you can event map each url manually, etc.

See UrlMapping docs - http://grails.org/doc/latest/guide/theWebLayer.html#urlmappings

Igor Artamonov
  • 35,450
  • 10
  • 82
  • 113