Almost every controller action looks up one or more entities based on some user input. For some time I've been wanting to remove some of this boring, dry-breaking, boilerplate code:
def show = {
def entity = null
if (params.id && params.id.isLong() && params.id.toLong() >= 0)
entity = Book.get(params.id.toLong())
if (!entity) {
flash.message = "Could not find, blah blah blah"
return redirect(...)
}
// Useful code
}
My current approach involves injecting a findEntry method into all controllers.
void injectFindEntryMethod() {
grailsApplication.controllerClasses.each { def c ->
c.metaClass.findDomainEntry = { def domainClass, def entryId ->
def entry = null
if (entryId && entryId.isLong() && entryId.toLong() >= 0)
entry = domainClass.findById(entryId)
if (!entry)
throw new DomainInstanceNotFoundException(domainClass, entryId)
return entry
}
}
}
The basic idea behind this method is that it will throw an exception when an entry can't be found. Currently I'm "catching" this exception by using the "declarative error handling" functionality in Grails 1.1.
"500"(controller: "error", action: 'domainInstanceNotFound', exception: DomainInstanceNotFoundException)
The neat thing about this solution is that the bloated code in the show action is reduced to:
def show = {
def entry = findDomainEntry(BlogEntry, params.id)
// Useful code
}
Unfortunately this also comes with a few drawbacks, but hey, that's why we have Stackoverflow right? :-)
Issues / drawbacks:
- This will cause the stacktrace of the exception to be logged, which is annoying since I'm handling the exception in my ErrorController.
- I can't access the exception object inside the action method, but the object is accessible by ${exception} inside the view (I can't understand why it's implemented this way).
What do you guys think of this approach? Any ways to improve it? Any advices or soultions to the drawbacks I mentioned above? I'm sorry if the scope of my question(s) is too big, it just doesn't make sense to split it into multiple questions.