Wicket – Sebastians Blog https://sgaul.de Neues aus den Softwareminen Thu, 13 Mar 2014 20:34:47 +0000 de-DE hourly 1 https://wordpress.org/?v=6.1.7 https://sgaul.de/wp-content/uploads/2019/02/cropped-sgaul-2-1-32x32.jpg Wicket – Sebastians Blog https://sgaul.de 32 32 Compiler-Sicherheit für Wicket: Bindgen und Wicket-ID-Bindings-Generator https://sgaul.de/2013/03/02/compiler-sicherheit-fur-wicket-bindgen-und-wicket-id-bindings-generator/ Sat, 02 Mar 2013 14:01:16 +0000 https://sgaul.de/?p=1962 Compiler-Sicherheit für Wicket: Bindgen und Wicket-ID-Bindings-Generator weiterlesen]]> Eine zentrale Schwachstelle von Apache Wicket ist die fehlende Sicherheit zur Übersetzungszeit. Viele Dinge werden als Strings angegeben, so dass simple Tippfehler erst zur Laufzeit und somit schlimmstenfalls erst beim Kunden auffallen. Betroffen sind vor allem drei Bereiche:

  • PropertyModels, in denen Objektattribute als Strings notiert werden:
    new PropertyModel<String>(person, "name");
  • Wicket-ID-Referenzen, die Komponenten mit ihrem Template verbinden:
    <span wicket:id="myLabel"></span> <-> new Label("myLabel")
  • Propertynamen, die vor allem für Übersetzungen benötigt werden:
    new StringResourceModel("page.welcome", this, null);

Bindgen für Wicket

Für das Model-Problem gibt es mit Bindgen Wicket eine verhältnismäßig prominente Lösung. Hier wurde bereits angefragt, ob das Tool nicht offizieller Teil von Wicket 7 werden könnte.

http://wicket.apache.org/
http://wicket.apache.org/

Bindgen ist ein Annotation Processing Tool. Es erzeugt Meta-Klassen, welche die vom Nutzer geschriebenen Klassen und deren Eigenschaften beschreiben. Property-Models können somit compilersicher beschrieben werden:

// ohne Bindgen:
PropertyModel<String>(person, "name");

// mit Bindgen:
BindingModel.of(person, new PersonBinding().name());

// auch über Objektgrenzen hinweg:
BindingModel.of(person, new PersonBinding().address().street());

Kein wackliger String, sondern sichere, generierte Bindingklassen, welche die Attribute der Basisklasse beschreiben.

Annotationprocessing ist mittlerweile fester Bestandteil moderner IDEs, so dass Bindgen nach der einmaligen Einrichtung in etwa Eclipse keiner weiteren Interaktion bedarf. Die Bindings werden stets automatisch aktualisiert.

Wicket-ID-Bindings-Generator für Property-Dateien und HTML-Templates

Von Bindgen inspiriert, hat Ole Langbehn eine analoge Lösung für Property-Dateien und HTML-Templates geschaffen.

// WelcomePage.html
<h1 wicket:id="heading"></h1>

// WelcomePage_de.properties.xml:
<entry key="greetings">Willkommen</entry>

// ohne Wicket-ID-Bindings-Generator
add(new Label("heading", 
    new StringResourceModel("greetings", this, null));

// mit Wicket-ID-Bindings-Generator
add(new Label(WelcomePageWID.heading,
    new StringResourceModel(WelcomePageI18n.greetings, this, null));

Das offizielle Repository auf Github ist momentan nicht mit Wicket > 1.4 kompatibel. Eine Variante für neuere Versionen habe ich in meinem Fork bereitgestellt:

Ole hat angedeutet die Änderungen zu übernehmen, so dass die Updates auch bald im offiziellen Repo zu finden sein sollten.

Die Autovervollständigung nimmt nun noch mehr Arbeit ab und eine potentielle Fehlerquelle ist eliminiert. Bleibt nur noch zu hoffen, dass Wicket diese oder ähnliche Lösungen zukünftig schon von Haus aus mitbringt.

]]>
Unabhängige Wicket-Elemente zusammen ausblenden https://sgaul.de/2012/10/30/unabhangige-wicket-elemente-zusammen-ausblenden/ Tue, 30 Oct 2012 21:27:58 +0000 https://sgaul.de/?p=1505 Unabhängige Wicket-Elemente zusammen ausblenden weiterlesen]]> Wickets setVisible bzw. setVisibityAllowed kann sehr sperrig sein, wenn man mehrere DOM-Elemente ausblenden möchte, weil ein einzelnes nicht befüllt werden kann. Ist ein beispielsweise ein Autor nicht angegeben, so braucht auch die Beschriftung „Autor“ vor diesem Feld nicht erscheinen:

<dl>
  <!-- dt sollte nur sichtbar sein, wenn auch dd sichtbar ist: -->
  <dt>Autor</dt> 
  <dd wicket:id="author">Klaus</dd>
  <!-- hier analog: -->
  <dt>Veröffentlicht am</dt>
  <dd wicket:id="published">11.11.2012</dd>
</dl>

Ist kein Autor für author angegeben, so soll auch das vorangegangene <dt> nicht angezeigt werden. Nun ließe sich auch die Überschrift als Component realisieren und die Sichtbarkeit im Java-Code prüfen, Wicket bietet von Haus aus aber eine einfachere und schönere Lösung.

<wicket:enclosure>

<dl>
  <wicket:enclosure child="author">  
    <dt>Autor</dt>
    <dd wicket:id="author">Klaus</dd>
  </wicket:enclosure>
  <wicket:enclosure child="published">
    <dt>Veröffentlicht am</dt>
    <dd wicket:id="published">11.11.2012</dd>
  <wicket:enclosure>
</dl>

Ein <wicket:enclosure>-Element erstellt einen (im generierten HTML unsichtbaren) Container. Dessen Inhalt ist nur dann sichtbar, wenn die im child-Attribut referenzierte Komponente sichtbar ist. Im Beispiel führt ein Unsichtbarschalten einer <dd>-Komponente folglich dazu, dass auch das <dt>-Element nicht im Quelltext erscheint.

Da im Beispiel nur eine Kompontente innerhalb eines <wicket:enclosure>-Elements liegt, kann das child-Attribut auch weggelassen werden.

Enclosure als Attribut

In vielen Umgebungen sind die zusätzlichen <wicket:enclosure>-Tags störend und unnötig. Wicket bringt hierfür ein Attribut mit, welches das selbe leistet, sich aber besser integriert.

<table>
  <tr wicket:enclosure="author">
    <td>Autor</td>
    <td><span wicket:id="author">Klaus</span></td>
  </tr>
  <tr wicket:enclosure="published">
    <td>Veröffentlicht am</td>
    <td><span wicket:id="published">11.11.2012</span></td>
  </tr>
</table>

Beschränkungen

Wickets Enclosure-Funktionalität ist zwar sehr hilfreich, kann jedoch oft nicht eingesetzt werden. Schon die angegebenen Beispiele zeigen das Problem: Ob als Definitionsliste oder Tabelle, beide Ansätze erfordern, dass das Elternelement <dl> bzw. <table> nicht erscheint, wenn keine der Kindkomponenten sichtbar ist.

<!-- Funktioniert NICHT: -->
<table wicket:enclosure="author || published">
  <tr wicket:enclosure="author">
    <td>Autor</td>
    <td><span wicket:id="author">Klaus</span></td>
  </tr>
  <tr wicket:enclosure="published">
    <td>Veröffentlicht am</td>
    <td><span wicket:id="published">11.11.2012</span></td>
  </tr>
</table>

Stattdessen müssen in solchen Situationen größere Geschütze wie ListView aufgefahren werden. Eigentlich schade um das Potential.

]]>
Apache-Wicket-Quickstart unter Ubuntu 12.04 https://sgaul.de/2012/09/08/apache-wicket-quickstart-unter-ubuntu-12-04/ Sat, 08 Sep 2012 13:01:16 +0000 https://sgaul.de/?p=1397 Nachdem ich mich auf Arbeit die letzten Wochen oft über Windows und Tomcat ärgern musste, habe ich heute auf einer frischen Installation von Ubuntu 12.04 ein Demoprojekt mit Apache Wicket eingerichtet. Wicket ist ein Rundumsorglospaket für die Webapp-Entwicklung und in Verbindung mit Maven in 5 Minuten lauffähig. Statt Apache und Tomcat wird für die Entwicklung der handliche Webserver Jetty verwendet.

Java-Umgebung installieren

Alles was ich brauche ist eine Java-Entwicklerumgebung und Maven:

sudo apt-get install openjdk-6-jdk maven

Je nach Bedarf kann man auch die neuere Version 7 wählen. Da diese keine nennenswerten Neuerungen bringt, setze ich auf den (hoffentlich) besser getesteten Vorgänger.

Die Eclipse-Version aus den Ubuntu-Repos ist erfahrungsgemäß alt und problematisch, daher einfach eine aktuelle Version der EE-Variante von der Projektseite laden und z.B. in /opt entpacken.

Nach der Installation starte ich Eclipse schon einmal, damit alle Konfigurationsverzeichnisse angelegt werden.

Wicket-Projekt erstellen

Ich erstelle meine Javaprojekte in $HOME/workspace. Mehr müssen Maven und Eclipse nicht voneinander wissen:

mvn -Declipse.workspace=$HOME/workspace eclipse:add-maven-repo

Nun erstelle ich mit Maven ein neues Wicket-Projekt, das automatisch alle Abhängigkeiten auflöst und das Projektverzeichnis mit allen Dateien erstellt. Für den Befehl gibt es einen Maven-Generator auf der Wicket-Website.

mvn archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=6.0.0 -DgroupId=de.sgaul -DartifactId=myproject -DarchetypeRepository=https://repository.apache.org/ -DinteractiveMode=false

Nun wechsele ich in das Projekt und erstellen mit Maven eine geeignete Eclipse-Konfiguration:

cd myproject
mvn eclipse:eclipse

Das war es schon mit der Einrichtung. Ich kannte Maven bisher nur vom Namen und habe es kaum genutzt. Das wird sich künftig wohl ändern.

Wicket-Projekt mit Eclipse bearbeiten

Nun einfach Eclipse starten und das Projekt importieren: File > Import > Existing Projects into Workspace. Im geöffneten Projekt die Datei Start.java suchen und mit einem Rechtsklick über Run as als Java Application starten. Automatisch wird der kleine Webserver Jetty gestartet (Entwicklung ohne Tomcat, ein Segen) und die Seite ist lokal erreichbar: localhost:8080.

So sollte die Wicket-App anfangs aussehen

Wer Wicket noch nicht kennt, kann nun die Beispiele der Projekteseite nachvollziehen.

]]>