I've built my first grails application. My URL mappings are what the default application provides:
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
}
Senario
I have a controller called ColorController
with actions save
and list
. It simply does something like this:
def save () {
def colorInstance = new Color(params)
colorInstance.save(flush: true)
}
def list () {
[colorList: Color.list, colorTotal: Color.count()]
}
I would like to build a simple API for these actions.
- The save action should accept parameters as JSON and provide a successful message if the records save.
- The list action should provide the list as JSON
Questions
- Should I make a separate URL mapping for api? (e.g.
http://<domain>/<app>/rest/controller/action
)
- Should I be making a separate controller for my API's
- I am using spring security plugin for authentication. But at some point I might want to authenticate the restful api as well. What are some solutions for that?
- If I use the same controller, how can I modify these simple actions to do what I need.
Before even looking below for my opinion/answers I would suggest to visit this SO Question for the basic understanding of RESTful WS in Grails.
Opinions:
"The save action should accept parameters as JSON and provide a successful message if the records save" - Save is mapped to POST RESTful. Instead of binding a JSON body to params
it is bound to the request
. In order to access the JSON object you just need to use request.JSON
in the action method.
request.JSON instanceof JSONObject
- "The list action should provide the list as JSON" -
list()
action is mapped to a GET Request and you can render the map as JSON in the list()
as below
//Controller list()
import grails.converter.JSON
def list () {
[colorList: Color.list, colorTotal: Color.count()] as JSON
}
Answers to Questions:-
- Should I make a separate URL mapping for api?
Abiding by the basics of REST, the client should only access the resource (
Color
in this case) and should not bother about the underlying controller
or action
. The server side logic should be abstracted from the client. URL Mapping is what the client would use to as form of request. I would have something like this in my url mapping for Color
Resource.
/color/$id?(resource: "color")
or
/color/$id?(controller: 'color'){
action = [GET: "list", POST: "save"]
}
Should I be making a separate controller for my API's? - Depends on the way the App is designed. You also can have the above controller as the API. For example, currently I am working on a grails app which used AngularJS
in the front End which connects to the Grails APP RESTFully. In order to achieve I had a RestClientController
which works as an API to Angular. The rationale behind having a REST api in the same app is that in future we can expose the underlying service to external clients other than the Angular
client present in the app itself.
I am using spring security plugin for authentication. But at some point I might want to authenticate the restful api as well. What are some solutions for that? - You can use Spring Security here as well. In my case I am using the plugin and I secure the controller
by using the plugin's annotated component @Secured
. I have custom OAuth
enabled as well for authorization which interacts to the company wide LDAP and AD Groups.
If I use the same controller, how can I modify these simple actions to do what I need. - I think you would have got the answer to this question by now (after going through the SO question I mentioned above). Here is my opinion, controller
actions
can route to appropriate service
classes which does the business implementations based on the request parameters.
For example,
//Action
def show(){
if(params.id){
colorService.getColor()
} else {
colorService.searchColor()
}
}
In the above example, the url mapping would be /color/123
or /color
. In the former case, it will get the color
and in the later it will search the colors