Meet Sputnik – static code analyser for Gerrit
Sonar Gerrit Plugin Release
Custom SonarQube rules for Unit Tests
Error generating web.xml file with IntelliJ IDEA
Local Graphite installation on CentOS 5.5 howto
Simple trick to DRY your Grails controller
Grails controllers are not very DRY. It's easy to find duplicated code fragments in default generated controller. Take a look at code sample below. It is duplicated four times in show
, edit
, update
and delete
actions:
class BookController {
def show() {
def bookInstance = Book.get(params.id)
if (!bookInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'book.label', default: 'Book'), params.id])
redirect(action: "list")
return
}
[bookInstance: bookInstance]
}
}
Why is it duplicated?
There is a reason for that duplication, though. If you move this snippet to a method, it can redirect to "list"
action, but it can't prevent controller from further execution. After you call redirect
, response status changes to 302, but after method exits, controller still runs subsequent code.
Solution
At TouK we've implemented a simple trick to resolve that situation:
- wrap everything with a simple
withStoppingOnRender
method, - whenever you want to render or redirect AND stop controller execution - throw
EndRenderingException
.
We call it Big Return - return from a method and return from a controller at once. Here is how it works:
class BookController {
def show(Long id) {
withStoppingOnRender {
Book bookInstance = Book.get(id)
validateInstanceExists(bookInstance)
[bookInstance: bookInstance]
}
}
protected Object withStoppingOnRender(Closure closure) {
try {
return closure.call()
} catch (EndRenderingException e) {}
}
private void validateInstanceExists(Book instance) {
if (!instance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'book.label', default: 'Book'), params.id])
redirect(action: "list")
throw new EndRenderingException()
}
}
}
class EndRenderingException extends RuntimeException {}
Example usage
For simple CRUD controllers, you can use this solution and create some BaseController
class for your controllers. We use withStoppingOnRender
in every controller so code doesn't look like a spaghetti, we follow DRY principle and code is self-documented. Win-win-win! Here is a more complex example:
class DealerController {
@Transactional
def update() {
withStoppingOnRender {
Dealer dealerInstance = Dealer.get(params.id)
validateInstanceExists(dealerInstance)
validateAccountInExternalService(dealerInstance)
checkIfInstanceWasConcurrentlyModified(dealerInstance, params.version)
dealerInstance.properties = params
saveUpdatedInstance(dealerInstance)
redirectToAfterUpdate(dealerInstance)
}
}
}
Read more New HTTP Logger Grails plugin
I've wrote a new Grails plugin - httplogger. It logs:
- request information (url, headers, cookies, method, body),
- grails dispatch information (controller, action, parameters),
- response information (elapsed time and body).
It is mostly useful for logging your REST traffic. Full HTTP web pages can be huge to log and generally waste your space. I suggest to map all of your REST controllers with the same path in UrlMappings
, e.g. /rest/
and configure this plugin with this path.
Here is some simple output just to give you a taste of it.
17:16:00,331 INFO filters.LogRawRequestInfoFilter - 17:16:00,340 INFO filters.LogRawRequestInfoFilter - 17:16:00,342 INFO filters.LogGrailsUrlsInfoFilter - 17:16:00,731 INFO filters.LogOutputResponseFilter - >> #1 returned 200, took 405 ms.
17:16:00,745 INFO filters.LogOutputResponseFilter - >> #1 responded with '{count:0}'
17:18:55,799 INFO filters.LogRawRequestInfoFilter - 17:18:55,799 INFO filters.LogRawRequestInfoFilter - 17:18:55,800 INFO filters.LogRawRequestInfoFilter - 17:18:55,801 INFO filters.LogOutputResponseFilter - >> #2 returned 404, took 3 ms.
17:18:55,802 INFO filters.LogOutputResponseFilter - >> #2 responded with ''
Official plugin information can be found on Grails plugins website here: http://grails.org/plugins/httplogger or you can browse code on github: TouK/grails-httplogger. Read more
New HTTP Logger Grails plugin
I've wrote a new Grails plugin - httplogger. It logs:
- request information (url, headers, cookies, method, body),
- grails dispatch information (controller, action, parameters),
- response information (elapsed time and body).
It is mostly useful for logging your REST traffic. Full HTTP web pages can be huge to log and generally waste your space. I suggest to map all of your REST controllers with the same path in UrlMappings
, e.g. /rest/
and configure this plugin with this path.
Here is some simple output just to give you a taste of it.
17:16:00,331 INFO filters.LogRawRequestInfoFilter - 17:16:00,340 INFO filters.LogRawRequestInfoFilter - 17:16:00,342 INFO filters.LogGrailsUrlsInfoFilter - 17:16:00,731 INFO filters.LogOutputResponseFilter - >> #1 returned 200, took 405 ms.
17:16:00,745 INFO filters.LogOutputResponseFilter - >> #1 responded with '{count:0}'
17:18:55,799 INFO filters.LogRawRequestInfoFilter - 17:18:55,799 INFO filters.LogRawRequestInfoFilter - 17:18:55,800 INFO filters.LogRawRequestInfoFilter - 17:18:55,801 INFO filters.LogOutputResponseFilter - >> #2 returned 404, took 3 ms.
17:18:55,802 INFO filters.LogOutputResponseFilter - >> #2 responded with ''
Official plugin information can be found on Grails plugins website here: http://grails.org/plugins/httplogger or you can browse code on github: TouK/grails-httplogger. Read more