Udana Warsjawa V – 100. spotkanie WJUG

Nigdy nie piszę relacji z imprez. Dzisiaj mam nastrój.To była V edycja. Dotychczas współorganizowałem edycje III i IV. Tej nie organizowałem i bardzo dobrze, bo powstała nowa zwarta grupa zdolna organizować imprezy WJUGowe. Super.Rozpoczęcie …

Nigdy nie piszę relacji z imprez. Dzisiaj mam nastrój. To była V edycja. Dotychczas współorganizowałem edycje III i IV. Tej nie organizowałem i bardzo dobrze, bo powstała nowa zwarta grupa zdolna organizować imprezy WJUGowe. Super. Rozpoczęcie chwilę po 9 zawierało przemówienie Oćca WJUGa, czyli Jacka, który siedzi teraz na Ukrainie, ale przesłał nam wideo.

Potem ja wspominałem moją przygodę z WJUGiem i okolicami. W ramach tego miałem na sobie 10 T-shirtów, które zebrałem na imprezach, o których opowiadałem. Były to specjalne spotkania WJUG oraz m.in. kolejne wydania Warsjawy i Javarsovii/Confitury.

Zademonstrowałem też unikalną koszulką z okazji 100. JUG.

Po mnie wystąpiło jeszcze kilku kolegów, a następne Grzesiek Duda z 30 minutową opowieścią jak ważne są JUGi i angażowanie się w społeczność Javową.

Rozeszliśmy się do 10 sal, w których odbywały się warsztaty. Ja wybrałem Java + elektronika i było sympatycznie. Nauczyłem się podstaw programowania Arduino, ale i przekonałem się, że Java jest uruchomiona tylko na PC, a nie pakujemy jej do środka Arduino. Z tą Javą to nie taki głupi pomysł i możliwy, np. dzięki

NanoVM. Nie doczekałem do końca imprezy, bo tatowe obowiązki wzywały mnie z domu.

Program i szczegóły na 

www.warsjawa.pl Plusy: * mega dużo warsztatów (słownie 10 sztuk) * bezpłatny obiad w barze Kubuś, na Wydziale MIMUW * sprawna organizacja, żadnych wpadek Minusy: * słaba reklama poza WJUG * ciągłość zajęć (brak przerw) powodowała, że nie było kiedy porozmawiać Co do braku reklamy, to przyczyna była prosta – zanim organizatorzy zdążyli rozgłośnić imprezę gdzieś dalej, miejsca były wyczerpane. Cudownie, tylko ja jednak widzę tu problem, że impreza zrobiła się przez to i lokalna i zarezerwowana tylko dla Warszawiaków/WJUGowców. Martwiła mnie też absencja stoisk sponsorów, których nie brakowało, ale byli nieobecni, poza Outbox. Na miejscu organizujących bym przemyślał wskazane przeze mnie problemy. Na pewno będę miał okazje porozmawiać z nimi o tym. To jest coś, z czym i ja muszę się niejednokrotnie mierzyć podczas organizowania innych imprez. Z punktu widzenia uczestnika 10pkt. Z punktu widzenia organizatora 9pkt. ;)

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)
}
}
}