... oder wie aus Minor Major wird

Neues in Wicket 1.5

Jochen Mader

Bevor ich diesen Artikel schrieb, musste ich auf Wikipedia nochmal kurz die Definitionen von Minor- und Major-Versionsnummern nachschlagen.
Würde ich Wicket-Versionen danach beurteilen, hätte ich wohl einfach die Versionsnummer in meinem POM hochgedreht und mich dann über die Beschwerden meines Compilers gewundert. Als erfahrener Wicket-User ist man es schon gewohnt, dass hier anders gezählt wird.
Beim Blick in den Migrationguide von Wicket 1.5 wird der Verdacht auch sofort bestätigt. Unter 41 Überpunkten (zum Vergleich: Der Migrationguide für 1.4 enthält 9 Punkte) und entsprechend viel Text verbirgt sich ein astreines Major-Update. Es überrascht also nicht, dass viele von Wicket 2 sprechen.

Im Folgenden möchte ich die wichtigsten, vollkommen subjektiv ausgewählten Änderungen an meinem Lieblingswebframework vorstellen.

Inter component events

Vermutung: Alle Wicket-Projekte kommen irgendwann an den Punkt, an dem es praktisch wäre, Ereignisse zwischen Komponenten austauschen zu können.
Mit Wicket 1.5 haben Callback-Methoden und die Einbindung eigener Messaging-Lösungen endlich ausgedient. Mit der Einführung des API für Inter-component-events wurde eine entsprechende Grundlage geschaffen.

Gerade mal vier Klassen im Package org.apache.wicket.event wurden gebraucht, um eine schmerzliche API-Lücke zu füllen:

  • IEvent ist die Basisklasse für alle Events
  • IEventSource stellt eine Event-Quelle dar
  • IEventSink wird von Receivern implementiert
  • IEventDispatcher erlaubt die Implementierung eigener Strategien mit Events

Alle Basiskomponenten wurden mit den IEventSource und IEventSink-Interfaces ausgestattet und können so mit wenigen Handgriffen Events miteinander austauschen. Zusätzlich liefert Wicket ein Default-Ajax-Event bei jedem erzeugten AjaxRequestTarget aus.
Hier ein einfaches Beispiel.

Beispiel mit dem neuen AjaxRequestTarget-Event

Im Markup einer beliebigen Page Folgendes hinzufügen:

testLink
oldval

In der Klasse dann:

add(new AjaxLink("testLink"){
            @Override
            public void onClick(AjaxRequestTarget ajaxRequestTarget) {
                System.out.println("link clicked");
            }
        });
        add(new Label("testText","alterText") {
           @Override
            public void onEvent(IEvent> event) {
                if (event.getPayload() instanceof AjaxRequestTarget) {
                    setDefaultModelObject("neuerText");
                    ((AjaxRequestTarget)event.getPayload()).add(this);
                }
            }
        }.setOutputMarkupId(true));

Durch das Anklicken des Links ändert sich der Text des Labels, welches auf das Default-Ajax-Event reagiert. Dieses (sehr simple) Beispiel zeigt zwei wichtige Dinge:

  • Komponenten können endlich vollständig voneinander entkoppelt werden. Es ist nicht mehr nötig, im Komponentbaum zu suchen oder finale Member nur zum Zweck der Referenzbeschaffung zu erzeugen.
  • Das Default-Ajax-Event erschlägt mit wenig Code viele Szenarien, in denen man zuvor eine Abhängigkeit zwischen Komponenten erzeugt hätte.

In meinen Augen ist es allerdings etwas gewöhnungsbedürftig, dass die Broadcast-Methode beim Versenden des Events angegeben werden muss.
Warum man diese Wahl hat, ist mir theoretisch klar. Welche messbaren Vorteile dies im Alltag bringen wird, werden aber wohl erst ein paar Tests zeigen.

Pluggable serialization

Größere Wicket-Projekte laufen über kurz oder lang in ein vorhersehbares Problem. Wicket macht intensiven Gebrauch von Objektserialiserung.
Sie erlaubt Wicket, die einzelnen Versionen einer Seite zu speichern und somit den ärgsten Feind einer Web-2.0-Anwendung, den Back-Button, unter Kontrolle zu bekommen.

Der Preis hierfür sind zum einen die Laufzeitkosten für die Serialisierung und zum anderen das Speichern der Objekte. Beides erledigt die JVM zuverlässig und in den meisten Fällen effizient genug.
Es gibt aber Szenarien, in denen dieser Mechanismus an seine Grenzen stößt.
Für diese Fälle wurde das Interface org.apache.wicket.serialize.ISerializer geschaffen, um einen der alternativen Serializer (z.B. Kryo oder Protocol Buffers) nutzen zu können.
Allerdings sollte man keinen simplen DropIn-Ersatz erwarten. Kryo und Co. sind zwar schnell, brauchen aber bei entsprechend komplexen Objektgraphen Hilfe, um ihre Arbeit erledigen zu können.

Der Aufwand dürfte sich allerdings lohnen, da man sowohl die Größe der serialisierten Objekte, als auch die CPU-Last deutlich reduzieren kann.
Um das Gesamtpaket abzurunden, gibt es bei Wicketstuff bereits eine Kryo-basierte Implementierung.

Geschrieben von
Jochen Mader
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.