The
getRestList() method below inspects the controller class to assemble such a list.Service:
SystemService.groovyclass SystemService implements ApplicationContextAware {
def restPackageName = "com.example.webservice"
def grailsApplication
static String toDash(String camel) {
//Example: "readySetGo" --> "ready-set-go"
def joint = ~/[^A-Za-z0-9]|(?<=[a-z])(?=[A-Z])/
def dashes = ~/-+/
return camel?.trim().replaceAll(joint, "-").replaceAll(
dashes, "-").toLowerCase()
}
def getRestList() {
def rest = [:]
grailsApplication.controllerClasses.each {
if (it.packageName == restPackageName)
rest[toDash(it.name)] =
it.getURIs().collect({ uri -> toDash(
it.getMethodActionName(uri))}).unique().sort() - "index"
}
return rest.sort()
}
}
The result is a Map of Arrays, like the following one.restList: Controller
Map of Action Arrays[
brand: ["list", "update"],
product: ["list", "update", "merge", "delete"]
]
The Map is passed by the controller to the view.Controller:
OpsHubController.groovypublic class OpsHubController {
def systemService
def restTool() {
render (restList: systemService.getRestList)
}
}
Then the view loops through the controllers and their actions to generate the HTML.View:
opsHub/index.gsp...
<div class=rest_controllers>
<g:each in="${restList}">
<label>
<input type=radio name=rest-resource value=${it.key}>${it.key}
</label>
</g:each>
</div>
<div class=rest_actions>
<g:each in="${restList}">
<div id=rest-actions-${it.key}>
<label>
<input type=radio name=rest-action_${it.key} value=index
checked>[none]
</label>
<g:each var="action" in="${it.value}">
<label>
<input type=radio name=rest-action-${it.key}
value=${action}>${action}
</label>
</g:each>
</div>
</g:each>
</div>
...
JavaScript on the client hides actions not applicable to the current selected controller. A couple of fields are added for the resource ID and URL parameters.
*Note: In theory, strictly RESTful approaches use the HTTP methods GET, PUT, POST, and DELETE. However, it's easier to use Grails actions instead of different HTTP methods since browsers do a GET by default.