Friday hackathon

Every month we have a Friday Hackathon, where we can code or create anything we want. That’s for the purpose of evaluating new technologies, doing crazy stuff or just having fun.

Beneath that we develop our skills and gain new experience.

Today we have 5 teams, that are doing following projects in various technologies:

  • Ping-pong scoring – we play ping pong a lot, so an app is a must! – Java (Dropwizard), Mongo
  • TouK’s library – we have dozens of books but currently we have a chaos who lends what – Clojure
  • ToukApi – access all internal data (about people, salaries, holidays, auth, projects people are in etc) through REST api – vert.x
  • ID / Drivers license recognition on Mobile – just shoot a photo of an ID and have all data and photo in a few seconds – Kotlin, Android
  • jaIde – I’m going for a sandwich – you can inform other employees that you go for a morning sandwich – that means – Mr Sandwich has just arrived at the kitchen – it’s like a snowball, the more people go for a sandwich the more confident you can be that there are actually sandwiches waiting :) – Swift/Scala/Java

At 4:30 PM we have hackathon summary. Let’s see what projects we will manage to accomplish…

 

rd

DSC_3057 DSC_3056

You May Also Like

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:

  1. wrap everything with a simple withStoppingOnRender method,
  2. 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)
}
}
}