GR8 Konferenz zu Groovy und Grails - Kopenhagen - 18. und 19. Mai 2009
Die GR8 Konferenz ist eine zweitägige Konferenz in Kopenhagen (Dänemark) am 18. und 19. Mai, die von SpringSource zusammen mit Javagruppen (dänische JUG) durchgeführt wird. Es geht um die Groovy-Sprache, das Grails Web Framework, das Griffon Swing Framework und andere tolle Technologien.
Die
Agenda und die
Sprecher sind schon online. Dabei gibt es auch viele Hands-On-Demos. Und einen
Twitt gibt es auch.
Labels: GR8, Grails, Groovy, Konferenz
Convention over Configuration?
Zu einem meiner letzten Blog-Posts gab es einen recht interessanten Kommentar, der mehr Support für Convention over Configuration und Configuration by Exception in Spring anmahnte.
Vorab: Convention over Configuration bedeutet, dass man sich auf Konventionen verlässt, die zu Einstellungen führen, die in den meisten Fällen ausreichend sind. Nur in Ausnahmefällen nutzt man Konfiguration, um Dinge dann doch anders einzustellen. Configuration by Exception bedeutet im wesentichen dasselbe. Diese Ansätze sind in Systemen wie Ruby on Rails oder Grails weit verbreitet und führen zu sehr kompakten Code.
Zunächst: Spring kann in zahlreichen Bereichen mit solchen Möglichkeiten aufwarten.
Konkret ging es im kritisierten Beispiel um das Einlesen von Properties. Man kann hier neben Expression Language auch auf die "klassischen" Methoden zugreifen. Und zwar konkret auf den
PropertyOverrideConfigurer, der einfach Properties nimmt und dann Werte von Spring-Bean überschreibt. Dazu muss man in die XML-Konfiguration
<context:property-override location="props.properties" /> einfügen. Wenn in der Datei
props.properties ein Eintrag wie
hallo.name=Ein Name existiert, wird bei der Spring-Bean
hallo die Methode
setName() mit dem Parameter
"Ein Name" aufgerufen. Man kann also ein Default im Code oder in der Spring-Konfiguration haben, und diesen anschließend überschreiben.
Ein anderes Beispiel für Convention over Configuration ist der folgende Web-Controller:
@Controller
public class KundeController {
@RequestMapping
public Kunde showForm() {
return new Kunde("Wolff","Eberhard",42);
}
}
Er wird bei der URL
http://localhost:8080/mywebapp/myservlet/kunde aktiviert, weil er
KundeController heißt. Als View-Name wird kunde genutzt, weil es der letze Teil der URL ist. Und das zurückgegeben Objekt steht untern dem Namen kunde in der View zur Verfügung, weil der Name der Klasse Kunde ist. Wie man sieht, ergibt sich so sehr kompakter Code.
Und schließlich gibt es zahlreiche Möglichkeiten, Autowiring zu nutzen. Zum Beispiel in XML:
<beans default-autowire="byType"
...>
<bean id="orderService" class="....OrderServiceImpl" />
...
oder im Code:
@Service
public class OrderServiceImpl implements OrderService {
private CustomerRepository customerRepository;
@Autowired
public void setCustomerRepository(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
...
}
In beiden Fällen werden typ-kompatible Spring-Beans an diesen Stellen injiziert, so dass man das Wiring der Anwendung nicht weiter definieren muss. Auch das macht den Code wesentlich kompakter.
Das interessante ist nun, dass diese Möglichkeiten existieren, aber durchaus kritisch betrachtet werden:
- Der PropertyOverrideConfigurer erlaubt es, bei beliebigen Spring-Beans beliebige Werte zu überschreiben. Das ist im allgemeinen zu mächtig. Man will meistens kontrollieren, welche Werte wo gesetzt werden können und auch sehen, womit die Werte überschrieben werden. Daher habe ich bisher in der Praxis eigentlich nur den PropertyPlaceholderConfigurer gesehen, der aber wesentlich expliziter und aufwändiger ist.
- Bei den Controllern kommt in Trainings oder Präsentationen oft die Frage, ob man nicht das Mapping zwischen URLs und Code irgendwo zentral im XML konfigurieren kann. Und das, obwohl die Mappings mittlerweile auch von den Tools gut unterstützt werden und man dadurch Übersichtlichkeit hat. Der Aufwand für eine explizite Angabe der URL, des View-Names und der Model-Namens sind auch nicht sehr groß:
@Controller
public class KundeController {
@RequestMapping("/kunde")
public Kunde showForm() {
return new ModelAndView("kunde","kunde",new Kunde("Wolff","Eberhard",42));
}
- Und Autowiring wird auch selten genutzt - das häufigste Gegenargument ist die mangelnde Übersicht, was genau wohin injiziert wird. Das ist vor allem spannend, weil in den meisten Fällen sowieso nur ein typ-kompatible Spring-Bean existiert, weil es eben nur eine Implementierung des Interfaces oder eine Instanz der Klasse gibt. Nur in Ausnahmefällen gibt es eine echte Wahl. Das bedeutet, dass die explizite Konfiguration nicht wesentliche Vorteile bringt - weil in den meisten Fällen sowieso klar ist, was wohin injiziert werden muss.
Was bedeutet das nun? Spring hat Möglichkeiten für Convention over Configuration. Mein Eindruck ist allerdings, dass diese Features zwar bekannt sind, aber in der Praxis wenig genutzt werden, weil man lieber explizit konfiguriert und einstellt, statt sich auf "Magie" zu verlassen. Das bedeutetet, dass Spring-Entwickler entweder andere Vorlieben oder andere Erfahrungen als beispielsweise Ruby-on-Rails-Entwickler haben - weil sie der "Magie" mistrauen oder schon gesehen haben, dass Systeme mit mehr "Magie" schwerer zu verstehen oder zu warten sind. Vielleicht müssen Ruby-on-Rails-Entwickler das noch lernen - oder vielleicht müssen Spring-Entwickler mehr Vertrauen zu der "Magie" entwickeln.
Labels: Convention over Configuration, Spring
Groovy / Grail Training mit Graeme Rocher
Graeme Rocher - einer der Köpfe hinter Groovy und Grails - wird 21.-23.4. in München ein Groovy / Grails-Training durchführen.
Nähere Informationen zum Training finden sich unter
http://www.springsource.com/training/grv001 .
Über das Training in München kann man sich unter
http://www.springsource.com/training/grv001/mun04212009 informieren, dort kann man sich auch registrieren.
Vortrag zu SpringSource dm Server bei JUG Saxony
Am 2.4. um 19:00 ist mein nächster Vortrag: Dieses Mal über den
dm Server bei der JUG Saxony in Dresden. Mehr Infos unter
http://de.amiando.com/jugsaxony-springdm.html .
Core-Spring-Trainings-Video online
Unter
http://www.youtube.com/watch?v=n5Woloa0Xr4 gibt es ein Video mit einigen Impressionen von unserem Core Spring Training - schauen Sie mal rein!
Diesen Dienstag, 24.3. 16:00 Uhr: Spring 3.0 Webinar mit Jürgen Höller
Bitte registrieren Sie Sich unter:
http://www.springsource.com/de/webinarsUnd hier der Abstract:
Die dritte Generation von Spring führt einen überarbeiteten Core auf Basis
von Java 5/6 ein. Die neue Spring Expression Language sowie verfeinerter
Annotation-Support entfalten an vielen Stellen ihre Wirkung. Im Web-Bereich
sind REST, Portlet 2.0 und Konversationsverwaltung die zentralen Themen. In
diesem Webinar stellt Jürgen Höller, der Spring Framework Project Lead, die
neuesten Entwicklungen in ihrer ganzen Breite vor.
Labels: Jürgen Höller, Spring 3.0, Webinar
Bundlor: Ein neuer Ansatz für OSGi-Builds
Im Moment ist es nicht leicht, eine OSGi-Anwendung zu bauen - es gibt zwar einige Ansätze, aber keiner macht richtig glücklich. Unter
http://blog.springsource.com/2009/03/18/our-plans-for-building-osgi-applications/ stellt mein Kollege Rob Harrop das Problem dar und er stellt auch seine Ideen zu Lösung vor - Feedback ist ausdrücklich erwünscht. Das Feedback soll dann in das Bundor-Tool einfließen.
Labels: Bundlor, ivy, Maven, OSGi
Folien und weitere Informationen zum Spring Expert Day
Unter
http://www.springsource.com/springmuenchen stehen nun die Folien des Spring Expert Day zur Verfügung. Außerdem kann man sich dort für das Webinar mit Mike Wiesner anmelden, das die ausgefallene Session mit ihm ersetzt.
Über den Sinn und Unsinn von Pooling
In letzter Zeit tauchte bei meinen Trainings und Beratungen wieder das Thema Pooling auf.
Wir erinnern uns: Man schreibt das Jahr 1998. Alle Welt baut CORBA-Systeme, meistens mit C++. Thread-Sicherheit - gerade mit C++ - ist kompliziert. Neue Objekte zu bauen ist teuer. Also führt man jeden Request mit einem Thread in einem eigenen Objekt aus und um nicht andauernd neue Objekte zu bauen, poolt man sie - denn Objekterzeugung ist teuer. Die Implementierung dazu baut man manuell. Basierend darauf führt EJB dann dieses Modell in die Java-Welt ein, so dass man es einfach nutzen kann, statt es ständig erneut zu implementieren.
Mittlerweile schreiben wir das Jahr 2009. Verschiedene Dinge haben sich geändert:
- Pooling nimmt an, dass das Erzeugen und Zerstören von Objekten teuer ist - sonst könnte man sie ja jedesmal erzeugen und zerstören, statt sie zu poolen. Bei Objekten wie Datenbank-Verbindungen und Threads stimmt das auch nach wie vor. Aber Objekt-Erzeugung und Zerstörung einfacher Java-Objekte ist mittlerweile sehr billig. Kurzlebige Objekte sind praktisch umsonst. Die Hotspot-FAQ warnt sogar vor Pooling: http://java.sun.com/docs/hotspot/HotSpotFAQ.html#gc_pooling
Der Hintergrund ist die Speicherverwaltung von Java. Für ein neues Objekt holt Java sich bei den neueren VMs einfach nur einen neuen Speicherbereich in der Young Generation durch Erhöhen eines Pointers. Wenn die Young Generation voll ist, wird durch einen Copying Garbage Collector die überlebenden Objekte, auf die noch Referenzen existieren, umkopiert. Die Komplexität dieses Garbage Collectors hängt von der Anzahl überlebender Objetke ab. Kurzlebige Objekte bedeuten also nur, dass diese Garbage Collection öfter läuft, aber nicht, das sie länger dauert. Beim Pooling hingegen hat man langliebige Objekte, bei denen die Garbage Collection länger dauert, und durch das Ausgreifen aus dem Pool auch ein Overhead. Übrigens muss C++ bei der Objekt-Erzeugung den Heap nach einem passend großen Speicherplatz durchforsten. Das ist wesentlich komplexer als die Pointer-Manipulation bei Java. Ein Umkopieren der Objekte ist bei C++ nicht möglich und somit ist der Heap nach einiger Zeit fragmentiert, weil Objekte wieder freigegeben werden und so Lücken entstehen. Java und Garbage Collection können also gerade bei Speicherverwaltung effizienter sein als C++.
- Pooling geht ja davon aus, dass nur ein Thread zur Zeit ein Objekt nutzen kann. Aber die typischen Services, DAOs und Repositories heutiger Systeme sind von mehreren Threads parallel nutzbar. Sie sind zustandslos, so dass sie die wesentlichen Informationen über Parameter bekommen oder die Informationen hängen am Thread (zum Beispiel die aktuelle Transaktion oder die Datenbankverbindung). Nur in Ausnahmesituationen ist das Objekt nicht thread-safe - zum Beispiel wenn man statt eine lokalen Variable eine Instanz-Variable nutzt, die dann bei paralleler Ausführung der Methode in mehreren Threads überschrieben wird. Wenn man allerdings die Instanz-Variablen durch lokale ersetzt, hat man kein Problem - also ist das ein handwerklicher Programmierfehler.
Übrigens ist es interessant, dass kaum ein Spring-Entwickler weiß, wie man mit Spring Pooling aktiviert. Das bedeutet, dass es in der Praxis offensichtlich nicht benötigt wird - sonst würden es ja mehr Leute kennen.
Und noch ein Hinweis: EJB 3.1 definiert mittlerweile auch Singletons, wie sie bei Spring schon lange genutzt werden - weil Pooling eben oft unnötig ist. Aber die Annahme der Spezifikation ist offensichtlich, dass man sehr häufig nebenläufigen Zugriff auf die Singletons haben wird, die synchronisiert werden müssen. Wie bereits erwähnt, halt ich das wegen der typischen Zustandslosigkeit für die extreme Ausnahme. Diese Ausnahmen kann man sehr gut mit den Java-Mitteln wie dem
synchronized Schlüsselwort und den Klassen aus
java.util.concurrent zu Leibe rücken. Gerade diese Features heben ja Java von C++ ab. EJB 3.1 führt zusätzlich Annotationen ein, um diesem Problem zu begegnen. Warum die vorhandenen Mittel nicht reichen, ist zumindest mir unklar und ich glaube auch, dass man in den meisten Systemen meistens Singletons haben wird, die eh thread-safe sind. Und: Wenn schon ein neues Concurrency-Modell - warum dann nur für EJBs?
Einer der Gründe, warum SpringSource die Java-EE-6-Spezifikation nicht angenommen hat, sondern sich bei der Abstimmung enthalten hat, ist übrigens, dass dieser Ansatz für Concurrency mit Annotationen noch nie in der Praxis ausprobiert worden ist. Ein weiterer wichtiger Grund ist sicher, dass das ursprünglich geplante minimale Web-Profil nun in der Spezifikation doch nicht enthalten ist - obwohl genau dies die am meisten verwendete Plattform für Enterprise-Java-Entwicklung ist. Die vollständige Abstimmung inkl. unserem Kommentar findet sich unter
http://jcp.org/en/jsr/results?id=4821.
Labels: EJB, Pooling, Spring