Wer in der Wicket-Community unterwegs ist, hat mitbekommen, dass es etwas länger gedauert hat, aber im Mai 2018 war es endlich soweit: Wicket 8 wurde released.
Klar, Wicket ist nicht mehr der „letzte Schrei“, ist aber schon lange ein stabiles und gut gewartetes Framework – Qualitäten, die in Webentwicklungsframeworks nicht immer selbstverständlich sind, und seit Wicket 6 ist auch die Dokumentation endlich so hilfreich, wie sie sein sollte. Außerdem bleiben wir von großen „Breaking Changes“ wie denen von Wicket 1.5 auf Wicket 6 verschont. Nicht zuletzt wegen dieser Stabilität wird Apache Wicket in Systemen mit höheren Sicherheitsanforderungen und klassischen Web-Frontends, wie zum Beispiel von Banken und Versicherungen, verwendet.
Wir werden in einer Reihe kurzer Blogartikel die wichtigsten Wicket-Features noch einmal kurz zeigen und die interessantesten Änderungen in Wicket 8 erklären. Zuerst widmen wir uns der Änderung, die zumindest auf unsere Projektarbeit den größten Einfluss hat: Models und wie die Arbeit mit ihnen durch Lambdas erleichtert wird:
Models allgemein
Erst einmal ein paar Worte zu Wicket im Allgemeinen: Apache Wicket ist ein auf Java aufsetzendes, komponentenbasiertes Webframework, in dem eine Pageklasse der Controller ist. Diese Page enthält einen Komponentenbaum, der aus Wicket-eigenen Komponenten, wie Links, Labels, Panels, Markupcontainer etc. bestehen kann, aber ebenso aus selbstgeschriebenen Komponenten.
Das Data-Binding in diesem Komponentenbaum wird mit sogenannten Models gemacht. Ein Model ist erstmal nur ein Interface, das zwei Methoden enthält:
getObject()
und setObject(T data)
zum Lesen und Schreiben der Daten.
Im einfachsten Fall ist ein Model also eine herumreichbare, schreibbare Objektreferenz. Durch diese Abstraktion können sich mehrere Komponenten dieselbe Datenquelle teilen, ohne sich untereinander zu kennen – Abhängigkeiten und mögliche Seiteneffekte werden reduziert. Durch Auslagerung dieser Logik in Models muss auch nicht jede Komponente von Hand geupdated werden, sondern die Komponenten selbst holen sich den aktuellen Stand aus ihrem Model.
1HomePage.java:
2IModel model = Model.of("Hello World!");
3add(new Label("output1", model));
4add(new Label("output2", model));
1HomePage.html: 2<span wicket:id="output1"></span> 3<span wicket:id="output2"></span>
Hinter diesem schmalen Interface kann beliebige Logik abstrahiert werden, so dass die Daten auf jede beliebige Art und Weise beschafft und geschrieben werden können.
ResourceModel
Ein häufiger Anwendungsfall ist, auszugebende Strings nicht direkt im Code zu haben, sondern über Java Resource-Bundles zu laden, typischerweise aus .properties
-Dateien. Hier hilft das ResourceModel
. Diese Model-Implementierung übernimmt das Laden des Strings. Im Code wird nur das Model
aus dem vorherigen Beispiel durch ein ResourceModel
ersetzt.
1IModel model = new ResourceModel("greeting");
PropertyModel
Was aber, wenn die Daten nicht über Ressourcen geliefert werden, sondern über Objekte, auf die wir eine Referenz haben? Hierfür gibt es das PropertyModel
, das Attribute von Objekten mittels Reflection ausliest.
1Greetable greetable = new Greetable(); 2IModel model = new PropertyModel<>(greetable, "greeting");
1Greetable.java:
2private String greeting;
3
4public String getGreeting() {
5 return greeting;
6}
Das PropertyModel
ist sehr komfortabel zu benutzen, aber nicht alle fühlen sich wohl damit, Reflection einzusetzen und dadurch ein Stück weit die durch Java gewährleistete Typsicherheit zu verlieren.
IModel
Stattdessen kann man ein IModel
direkt implementieren. Hierfür müssen drei Methoden geschrieben werden, die weiter oben genannten setObject(T data)
und getObject()
, und detach()
. detach()
wird am Requestende aufgerufen, räumt gegebenenfalls auf und gibt Ressourcen frei. Für ein rein lesendes Model würden wir hier also zwei Methoden „leer“ lassen und nur getObject()
implementieren.
1IModel<String> model = new IModel() {
2 @Override
3 public String getObject() {
4 return greetable.getGreeting();
5 }
6
7 @Override
8 public void setObject(String object) {
9 // NOP
10 }
11
12 @Override
13 public void detach() {
14 // NOP
15 }
16 };
Das ist natürlich für den täglichen Gebrauch etwas unhandlich. Für diesen häufigen Fall gab es bisher das AbstractReadOnlyModel
, das setObject
und detach
bereit stellt. Es muss also nur noch getObject
implementiert werden:
1IModel; model = new AbstractReadOnlyModel() {
2 @Override
3 public String getObject() {
4 return greetable.getGreeting();
5 }
6 };
Read-only Models mit Lambdas
Mit dem auf Java 8 ausgerichteten Wicket 8 können wir diesen Anwendungsfall jetzt noch etwas einfacher umsetzen:
In Wicket 8 sind detach()
und setObject()
Default-Methoden geworden, müssen also nicht mehr implementiert werden. Das heißt, AbstractReadOnlyModel
s werden jetzt durch einfach IModel
s ersetzt, in denen nur die getObject
Methode implementiert wird.
1IModel<String> model = new IModel() {
2 @Override
3 public String getObject() {
4 return greetable.getGreeting();
5 }
6 };
Da es jetzt aber nur noch eine einzige abstrakte Methode gibt, können wir nach dem SAM (Single Abstract Method) Pattern einfach ein Lambda verwenden:
1IModel<String> model = () -> greetable.getGreeting();
Fazit: Typsichere Read-Only Models sind mit Wicket 8 jetzt Einzeiler.
Übrigens: Wer in 4 Tagen so richtig viel über Apache Wicket lernen will – uns gibt es auch als Workshop, meldet euch bei Interesse einfach per Mail!
Weitere Beiträge
von Antonia Schmalstieg & Carl-Eric Menzel
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*innen
Antonia Schmalstieg
IT Consultant
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Carl-Eric Menzel
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.