Last active
May 28, 2019 16:08
-
-
Save aeischeid/4152409 to your computer and use it in GitHub Desktop.
Alternate grails controller template and url mapping for adding a scaffolded JSON API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package gvl | |
import grails.converters.JSON | |
class ErrorController { | |
// Forbidden | |
def error403() { | |
withFormat { | |
html { render(view: 'error403') } | |
json { | |
render(status: 403, text:'', contentType: 'application/json') | |
} | |
} | |
} | |
// Not Found | |
def error404() { | |
withFormat { | |
html { | |
//String missingPage = request.getAttribute('javax.servlet.error.message') | |
//log.info("404 when trying to access page ${missingPage}") | |
render(view: 'error404') | |
} | |
json { | |
render(status: 404, text:'', contentType: 'application/json') | |
} | |
} | |
} | |
// Conflict | |
def error409() { | |
withFormat { | |
html { render(view: 'error409') } | |
json { | |
render(status: 409, text:'', contentType: 'application/json') | |
} | |
} | |
} | |
def error500() { | |
def exception = request.exception | |
withFormat { | |
html { render(view: '/error') } | |
json { render exception as JSON} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%=packageName ? "package ${packageName}\n\n" : ''%>import org.springframework.dao.DataIntegrityViolationException | |
import grails.converters.JSON | |
class ${className}Controller { | |
static allowedMethods = [list:'GET', | |
show:'GET', | |
edit:['GET', 'POST'] | |
save:'POST', | |
update:['POST','PUT'], | |
delete:['POST','DELETE']] | |
def index() { | |
redirect(action: "list", params: params) | |
} | |
def list(Integer max) { | |
params.max = Math.min(max ?: 25, 100) | |
def list = ${className}.list(params) | |
withFormat { | |
html { | |
[${propertyName}List: list, ${propertyName}Total: ${className}.count()] | |
} | |
json { | |
render list as JSON | |
} | |
} | |
} | |
def create() { | |
[${propertyName}: new ${className}(params)] | |
} | |
def save() { | |
def ${propertyName} = new ${className}(params) | |
if (!${propertyName}.save(flush: true)) { | |
withFormat { | |
html {render(view: "create", model: [${propertyName}: ${propertyName}])} | |
json { | |
response.status = 400 | |
render ${propertyName}.errors as JSON | |
} | |
} | |
return | |
} | |
withFormat { | |
html { | |
flash.message = message(code: 'default.created.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id]) | |
redirect(action: "show", id: ${propertyName}.id) | |
} | |
json { | |
response.status = 201 | |
render ${propertyName} as JSON | |
} | |
} | |
} | |
def show(Long id) { | |
def ${propertyName} = ${className}.get(id) | |
if (!${propertyName}) { | |
withFormat { | |
html { | |
flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), id]) | |
redirect(action: "list") | |
} | |
json {render(status: 404, text:'', contentType: 'application/json')} | |
} | |
return | |
} | |
withFormat { | |
html {[${propertyName}: ${propertyName}]} | |
json { render ${propertyName} as JSON } | |
} | |
} | |
def edit(Long id) { | |
def ${propertyName} = ${className}.get(id) | |
if (!${propertyName}) { | |
flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), id]) | |
redirect(action: "list") | |
return | |
} | |
[${propertyName}: ${propertyName}] | |
} | |
def update(Long id, Long version) { | |
def ${propertyName} = ${className}.get(id) | |
if (!${propertyName}) { | |
withFormat { | |
html { | |
flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id]) | |
redirect(action:"list") | |
} | |
json {render(status: 404, text:'', contentType: 'application/json')} | |
} | |
return | |
} | |
if (version != null) { | |
if (${propertyName}.version > version) {<% def lowerCaseName = grails.util.GrailsNameUtils.getPropertyName(className) %> | |
${propertyName}.errors.rejectValue("version", "default.optimistic.locking.failure", | |
[message(code: '${domainClass.propertyName}.label', default: '${className}')] as Object[], | |
"Another user has updated this ${className} while you were editing") | |
withFormat { | |
html {render(view: "edit", model: [${propertyName}: ${propertyName}])} | |
json {render(status: 409, text:'', contentType: 'application/json')} | |
} | |
return | |
} | |
} | |
${propertyName}.properties = params | |
if (!${propertyName}.save(flush: true)) { | |
withFormat { | |
html {render(view: "edit", model: [${propertyName}: ${propertyName}])} | |
json { | |
response.status = 400 | |
render ${propertyName}.errors as JSON | |
} | |
} | |
return | |
} | |
withFormat { | |
html { | |
flash.message = message(code: 'default.updated.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id]) | |
redirect(action: "show", id: ${propertyName}.id) | |
} | |
json { render ${propertyName} as JSON } | |
} | |
} | |
def delete(Long id) { | |
def ${propertyName} = ${className}.get(id) | |
if (!${propertyName}) { | |
withFormat { | |
html { | |
flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), id]) | |
redirect(action: "list") | |
} | |
json {render(status: 404, text:'', contentType: 'application/json')} | |
} | |
return | |
} | |
try { | |
${propertyName}.delete(flush: true) | |
withFormat { | |
html { | |
flash.message = message(code: 'default.deleted.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), id]) | |
redirect(action: "list") | |
} | |
json {render(status: 204, text:'', contentType: 'application/json')} | |
} | |
} | |
catch (DataIntegrityViolationException e) { | |
withFormat { | |
html { | |
flash.message = message(code: 'default.not.deleted.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), id]) | |
redirect(action: "show", id: id) | |
} | |
json { response.sendError(500) } | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UrlMappings { | |
static mappings = { | |
"/$controller/$action?/$id?"{ | |
constraints { | |
// apply constraints here | |
} | |
} | |
name api0: "/api/$controller/$id"(parseRequest:true){ | |
action = [GET: "show", PUT: "update", DELETE: "delete"] | |
constraints { | |
id(matches:/\d+/) | |
} | |
} | |
name api1: "/api/$controller"(parseRequest:true){ | |
action = [GET: "list", POST: "save"] | |
} | |
name api2: "/api/$controller/$action"(parseRequest:true) | |
name api3: "/api/$controller/$action/$id"(parseRequest:true) | |
"/"(view:"/index") | |
"403"(controller: "error", action: "error403") | |
"404"(controller: "error", action: "error404") | |
"409"(controller: "error", action: "error409") | |
"500"(controller: "error", action: "error500") | |
"500"(controller: "error", action: "error403", exception: AccessDeniedException) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment