Archiv für Februar 2009

Filters in Grails

Nur, damit ich es selbst im Kopf behalte… die Filterkette in Grails ist ja richtig kompliziert! Sie läuft in folgender Reihenfolge ab:

  1. Servlet Filter before chain.doFilter() (Acegi runs here)
  2. GrailsDispatcherServlet.doDispatch() starts
  3. Spring MVC Interceptors preHandle() (OSIVI opens session)
  4. Grails Filters “before” closure
  5. Controller beforeInterceptor
  6. Controller action
  7. Controller afterInterceptor
  8. Grails Filters “after” closure
  9. Spring MVC Interceptors postHandle
  10. View rendering
  11. Grails Filters “afterView” closure
  12. Spring MVC Interceptors afterCompletion() (OSIVI closes session)
  13. Grails DispatcherServlet.doDispatch() ends
  14. Servlet Filter after chain.doFilter() (Sitemesh runs here)

Uff!

IT-Matrix überall

Anscheinend bin ich nicht der Einzige, der für seine IT-haltigen Vorträge Metaphern aus dem Film “Matrix” verwendet. Wie ich hörte, haben Martin Fowler und Rebecca Parsons auf der QCon 2008 in ihrem Vortrag Agilists and Architects — Allies not Adversaries die Szene aus Matrix verwendet, in der Neo auf “den Architekten” trifft.

In der Tat kann die Begegnung mit einem Architekten manchmal seltsam sein – ich muss es wissen, denn ich bin unter anderem selbst so einer. :-)

Mit TDD schreibt man Spezifikationen

Wenn man testgetriebene Entwicklung (TDD = test driven development) an Entwicklungsteams “verkaufen” möchte, trifft man oft auf Hindernisse oder Einwände:

  • Wir können nicht Code testen, der noch nicht existiert
  • Warum sollte ich Tests schreiben, das machen doch die Tester
  • Ich bin ein guter Entwickler, ich brauche keine Tests als Beweis, dass mein Code funktioniert
  • Entwickler sollten nicht ihren eigenen Code testen, das führt zu selbsterfüllenden Prophezeiungen
  • Tester wissen viel besser wie man testet als Entwickler
  • Testen in der frühen Phase kostet Zeit, die wir nicht haben
  • usw.

Was dabei außer Acht gelassen wird: TDD ist viel eher eine Art und Weise zu spezifizieren als zu testen! Ich schreibe eine Spezifikation als Erwartung (expectation) hin, spreche darüber mit dem Kunden, ob er das genauso sieht und implementiere dann bis die Spezifikation “läuft”.

Selbst wenn jemand kein Java programmieren kann, kann er dieses hier mit etwas Übung lesen lernen und sich dadurch mit kommunikationsstarken Entwicklern (ja, die gibt’s!) abstimmen (siehe diese Seite über BDD = behaviour driven development):

public class BalancetransferServiceBehaviour extends TestCase {
    public void shouldTransferBalanceFromAccountWithSufficientFunds() {
        // create mock instances
        Mock fromAccount = mock(Account.class);
        Mock toAccount = mock(Account.class);
 
        // set expectations
        fromAccount.expects(once()).method(“debit”).with(20).isVoid();
        toAccount.expects(once()).method(“credit”).with(20).isVoid();
    }
}

Der Code muss dazu nicht existieren – die ausführbare Spezifikation (früher sagte man auch: “der Test”) wird fehlschlagen, und der Entwickler kann den Code so schreiben, dass er die Spezifikation erfüllt.

[Diese Idee der ausführbaren Spezifikation ist schon sehr alt und wird jetzt anscheinend wieder in neuer Form populär. Witzig ist, dass es z.B. ein Open Source Tool (TestDox) gibt, das versucht, aus solchen Spezifikationen (Tests) normale Textdokumente zu generieren.]

Also sind Konflikte mit Testern eigentlich überflüssig, sobald diese sehen, dass es um maschinell ausführbare Spezifikationen als Vorgabe für Entwickler geht. Tester haben immer noch genug zu tun: Akzeptanztests, Usability-Tests, Performance- und Lasttests, Security-Tests, usw. — kein Problem!

Ist es schwierig, spirituell zu leben?

Alistair Cockburn zitiert einen unbekannten Autor mit einem schönen Text über spirituellen Lebensstil.

Kein Vodafone UMTS nach Mac Update?

Heute meldete sich mal wieder das übliche Apple Update-Programm, und ich akzeptierte das Updaten einiger Komponenten, u.a. habe ich jetzt Leopard 10.5.6. Nach dem Reboot kam ich jedoch mit meinem USB-Stick von Vodafone erst mal nicht mehr ins Internet.

Auf meiner Platte fand sich noch das Installationsprogramm VodafoneMCInstaller.2.11.02.00.dmg.zip. Dieses habe ausgepackt und gestartet, damit die alte Software de-installiert und wieder installiert. Nach einem nochmaligen Reboot ging alles wieder einwandfrei.

Also: Nicht verzweifeln, doch das Installationsprogramm aufheben, das hilft! :-)

JUnitMax: Bei jedem Speichern testen!

Kent Beck hat JUnitMax freigegeben.

“JUnit Max is an Eclipse plug-in that helps programmers stay focused on coding by running tests intelligently and reporting results unobtrusively. Every time you save a Java file, Max will run your tests and report errors like compile errors. In addition, Max runs the tests most likely to fail first, so you only have to pay close attention to test results for a second (literally) before getting back to coding, even if you have a long-running test suite.”

Testen bei jedem Speichern eines Java-Files – Kent, das ist wirklich cool!

I18N-Problem in Grails

Wenn man eine mehrsprachenfähige Webanwendung erstellen will, unterstützt Grails recht gut dabei. Man legt eine messages.properties-Datei (ein Message-Bundle) pro Sprache an und schreibt dort (wie in Java üblich) die Übersetzung von Schlüssel auf Text, so wie es auf der Grails-Website beschrieben ist. Die GSP-Seiten enthalten <g:message>-Tags zur Übersetzung.

Leider gab es bei mir ein Problem: Ich habe eine Grails-Anwendung mit einem deutschen und einem Default-Bundle, das englische Texte enthält und immer dann zum Zuge kommen soll, wenn die Sprache des Browser-Clients eben nicht Deutsch ist. Also:

  • messages_de.properties für Deutsch
  • messages.properties für alle anderen Sprachen

Ich stellte meinen Browser auf Deutsch ein – alles wunderbar, die deutschen Texte kamen einwandfrei. Ich stellte den Browser auf Englisch ein – Enttäuschung: es kamen immer noch deutsche Texte!

Nach einigem Suchen im Quellcode von Grails (ValidationTagLib.groovy) fand ich heraus, dass für die Übersetzung ein Objekt vom Typ ReloadableResourceBundleMessageSource aus dem Spring-Framework verantwortlich ist. Dieses hat eine Property fallbackToSystemLocale, die auf true oder false stehen kann. Sie steht standardmäßig auf true, das heißt, wenn kein Text für das eingestellte Locale gefunden wird, wird nicht etwa der Text aus dem Default-Bundle genommen, sondern noch einmal in demjenigen Message-Bundle gesucht, das dem “system locale” entspricht. Meine Servermaschine läuft auch auf Deutsch, so dass nochmals auf die Texte in message_de.properties zugegriffen wurde.

Abhilfe:

Jetzt war klar, dass diese Property während der Initialisierung auf false gesetzt werden muss. Mit folgenden Zeilen in Boostrap.groovy war der Fehler behoben:

import org.codehaus.groovy.grails.commons.ApplicationAttributes

def init = { servletContext ->
    def ctx = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
    def messageSource = ctx.getBean("messageSource")
    messageSource.fallbackToSystemLocale = false
}

Wenn jetzt ein Request mit englischem Locale eintrifft, wird auf messages.properties zugegriffen, das ergibt das gewünschte Verhalten.

Java resource bundle Editor für Eclipse

Im Jahr 2006 schrieb ich einen Blog-Eintrag über ein komfortables Editor-Plugin für Java resource bundles. Inzwischen gibt es die Website nicht mehr. Das Projektteam, das dieses Plugin auf SourceForge.net entwickelte, hat seine Software der Eclipse Community geschenkt. Das entsprechende Eclipse-Projekt heißt “Babel”.

Die neue Stelle, an der man dieses Plugin findet? Lesen Sie folgenden kurzen Artikel im Eclipse Wiki!