Archive for the ‘Grails’ Category

Customized Grails Controller for REST

November 22nd, 2011

Grails can do RESTfull easily enough, but I wanted a restful API from grails without throwing out grails scaffolding, So I decided to customize Grails’ controller template.

grails install-templates

then in [app-name]/src/templates/scaffolding/Controller.groovy

import org.springframework.dao.DataIntegrityViolationException
import grails.converters.XML
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() {
		params.max = Math.min(params.max ? params.int('max') : 50, 200)
		def list = ${className}.list(params)
		def listObject = [${propertyName}List: list, ${propertyName}Total: ${className}.count()]
		withFormat {
			html listObject
			json { render list as JSON }
			xml { render listObject as XML }
		}
	}

	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 = 403
					render ${propertyName}.errors as JSON
				}
				xml {
					response.status =403
					render ${propertyName}.errors as XML
				}
			}
			return
		}
		flash.message = message(code: 'default.created.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id])
		withFormat {
			html {
				redirect(action: "show", id: ${propertyName}.id)
			}
			json {
				response.status = 201
				render ${propertyName} as JSON
			}
			xml {
				response.status = 201
				render ${propertyName}.id
			}
		}
	}

	def show() {
		def ${propertyName} = ${className}.get(params.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 { response.sendError(404) }
				xml { response.sendError(404) }
			}
			return
		}
		def object = [${propertyName}: ${propertyName}]
		withFormat {
			html {object}
			json { render object as JSON }
			xml { render object as XML }
		}
	}

	def edit() {
		def ${propertyName} = ${className}.get(params.id)
		if (!${propertyName}) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])
			redirect(action: "list")
			return
		}
		[${propertyName}: ${propertyName}]
	}

	def update() {
		def ${propertyName} = ${className}.get(params.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 { response.sendError(404) }
				xml { response.sendError(404) }
			}
			return
		}

		if (params.version) {
			def version = params.version.toLong()
			if (${propertyName}.version > version) {
				${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 { response.sendError(409) }
					xml { response.sendError(409) }
				}
				return
			}
		}

		${propertyName}.properties = params

		if (!${propertyName}.save(flush: true)) {
			withFormat {
				html {render(view: "edit", model: [${propertyName}: ${propertyName}])}
				json {
					response.status = 403
					render ${propertyName}.errors as JSON
				}
				xml {
					response.status = 403
					render ${propertyName}.errors as XML
				}
			}
			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 {
				response.status = 204
				render ${propertyName} as JSON
			}
			xml {
				response.status = 204
				render ''
			}
		}
	}

	def delete() {
		def ${propertyName} = ${className}.get(params.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 { response.sendError(404) }
				xml { response.sendError(404) }
			}
			return
		}
		try {
			${propertyName}.delete(flush: true)
			withFormat {
				html {
					flash.message = message(code: 'default.deleted.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])
					redirect(action: "list")
				}
				json {
					response.status = 204
					render ''
				}
				xml {
					response.status = 204
					render ''
				}
			}
		}
		catch (DataIntegrityViolationException e) {
			withFormat {
				html {
					flash.message = message(code: 'default.not.deleted.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])
					redirect(action: "show", id: params.id)
				}
				json { response.sendError(500) }
				xml { response.sendError(500) }
			}
		}
	}

}

then modify your UrlMappings.groovy file to look something like this:

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"]
		}
	}
}

I found the JSON Restful plugin a while after I already did most of this, so that is another way to go. Other than it having some issues in grails 2 right now it looks like a really good option, but one thing I like about my approach is that if you want to customize your API in fine detail you can do so. You can always generate individual controllers and modify them of course. Another option is registering custom marshallers. The simple example for customizing your JSON output without changing any controller code would be doing something like this in your Bootstrap.groovy

import grails.converters.JSON
class BootStrap {
  def init = {servletContext ->;
    JSON.registerObjectMarshaller(Person) {
      def returnArray = [:]
      returnArray['name'] = it.name
      returnArray['addrs'] = it.addresses
      return returnArray
    }
    ...
  }

...

RESTfullness and web-frameworks

September 26th, 2011

After working on an offline mobile web app that integrated with a Grails backend, and after that being prompted to explore options for a new some green field development, which lead me to re-evalutate things like REST to NoSQL to MVC frameworks in general to mobile frameworks, to front-end frameworks in general. I feel like I have started to form a more robust comprehension of where web-app development is headed in general, and most of the web-frameworks I know of seem to be missing it so far. This would be hard to articulate briefly, but blogs are good for taking a wild stab at that sort of thing, right? Disclaimer: this is just me sort of thinking out loud, so take it for what it is.

I am coming to the conclusion that I don’t think I want to use Grails anymore. Either that or I want to gut it of a lot of what it does. Sitemesh, don’t need it. Hibernate, don’t really want SQL database anymore, schema’s are so restricting/un-agile, so don’t need it. GORM, dislike it about as much as I find it useful, so could really take it or leave it. if you end up working with a object DB then it is pretty much an unnecessary abstraction anyway. Groovy, well I like it better than Java, but honestly Scala seems like it might be the most promising language on the JVM, and for that matter other non-JVM languages have plenty of appeal too. Resources plugin, Tablibs (built in or customizable), Scaffolding and Templates, i18n… better handled by a front-end framework.

Or…  RESTfullness and MVC are beautifully simple things, and these plus the idea that next generation web applications can no-longer count on consistent and/or high-speed connectivity, but can count on robust javascript engines on the client side means that pushing as much of the application to the client as possible is now something to strongly consider. . Grails (and lets not just pick on Grails, most web-frameworks I know of) is still stuck in the paradigm where views are generated server-side .

Grails, again, to be fair, this seems to be a pattern for web frameworks in general, has been advancing in ways that make it more powerful and thus more complex, not less. True it does a decent job of hiding that complexity away most of the time, but even so, what if  its being there is all unnecessary in the first place? The trend in the way people are using their computers/devices would seem to me to drive rich apps working on the client-side with relatively simple storage and syncing services that they connect to. Maybe what it means for web-frameworks to evolve at this point means to specialize, simplify, and strip down.

Grails active page navigation menu

March 26th, 2010

A Common feature found in many CMS’s or web-apps is a navigation menu with a highlighted active page, or the parent of the current page in a hierarchy. The trick is getting the proper element with an added CSS class of ‘selected’ or ‘active’. There are a number of ways to do this, but I just found a new way to do it in Grails using a Sitemesh’s pageProperty.

In my main layout gsp I have the nav menu


then in the head section of a view gsp’s where I want the appropriate element to have a ‘selected’ or ‘active’ class. I include:


Then in the css have something to deal with the applied class:

  #mainMenu li > a.selected { .... }

Pretty simple! I don’t know if this is very efficient in terms of performance. I can think of other ways to do this with Javascript, or params passed from the controller, but I wanted to find something that used Sitemesh as that seemed like the component that ought to handle this sort of feature. So while this is working for me, and gives a pretty good level of control, I am still wondering if it is really the ‘right’ way to do it.

For a more comprehensive explanation of Sitemesh in Grails visit this blog.