Einführung in die Entwicklung mit Vaadin

Seite 2: Struktur und Projekt

Inhaltsverzeichnis

Im nächsten Schritt müssen Entwickler im Archetyp-Fenster die Konfiguration "Single-Module Application Project" auswählen: Für die ersten Gehversuche ist es besser, wenn alle Teile der Applikation in einem Modul sitzen. Nach dem Anklicken von Next geben Entwickler einige Metadaten zum zu erzeugenden Code ein: In den folgenden Schritten wird mit dem Namen
HeiseVaadin1 gearbeitet. Danach klicken Entwickler auf Finish, um das Anlegen des neuen Projekts anzustoßen. Sie müssen darauf achten, dass hier eine Internetverbindung besteht, um Maven das Herunterladen der benötigten Pakete zu ermöglichen.

Der Lohn der Mühen ist die in Abbildung 4 gezeigte Projektstruktur, die zum Zeitpunkt der Generierung aus einer .java- und einigen .css-Dateien besteht: Letztere beeinflussen das Aussehen der Steuerelemente.

Die Projektstruktur sieht angesichts der diversen Referenzen sehr kompliziert aus (Abb. 4).

Im nächsten Schritt öffnen Entwickler die Java-Datei MyUI.java – ihr Inhalt sieht folgendermaßen aus:

@Theme("mytheme") 
public class MyUI extends UI {

@Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout();

Da das Projekt vorerst ohne Vaadin Designer auskommt, müssen Entwickler das Benutzer-Interface der Applikation von Hand aus einzelnen, zur Laufzeit zu instanziierenden Steuerelement-Instanzen zusammenbauen. Hier beginnt man mit dem Erzeugen einer Layout-Klasse, die im nächsten Schritt ein Textfeld und einen Knopf bekommt:

final TextField name = new TextField(); 
name.setCaption("Type your name here:");

Button button = new Button("Click Me");
button.addClickListener( e -> {
layout.addComponent(new Label("Thanks " + name.getValue()
+ ", it works!"));
});

Sodann werden die Attribute der diversen Steuerelemente unter Nutzung von Member-Funktionen der Widget-Klassen gesetzt. Die Textbox bekommt einen Hilfstext zugewiesen, während der Knopf mit einem Event-Handler ausgestattet wird.

Die Hauptklasse ist von der Vaadin-Masterklasse UI abgeleitet. Eine UI-Instanz beschreibt dabei ein Render-Fenster, das eine Vaadin-Applikation im Browser darstellt. Die letzte Handlung besteht darin, das Layout mit den Steuerelementen zu versorgen und zu guter Letzt durch Nutzung der setContent-Methode als Inhalt der jeweiligen UI-Klasse festzulegen.

    layout.addComponents(name, button); 
layout.setMargin(true);
layout.setSpacing(true);

setContent(layout);
}

Das Vorhandensein einer UI-Klasse reicht nicht zur fertigen Vaadin-Applikation aus. Für die Verbindung zwischen Java und Vaadin ist eine Instanz der Servlet-Klasse erforderlich, die folgendermaßen aussieht:

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", 
asyncSupported = true)
@VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
}

Aufmerksamkeit verdient vor allem das Attribut urlPatterns: Es legt fest, auf welche eingehenden Adressen das jeweilige Servlet reagieren soll. Mit dem ui-Attribut wird dem Servlet sodann eine UI-Klasse zugewiesen, die im jeweiligen Browserfenster angezeigt beziehungsweise an die jeweiligen Anfrage zurückgegeben werden soll.

In einer idealen Welt könnten Entwickler nun auf Play klicken und sich am laufenden Programm erfreuen. Im Fall von Vaadin ist das nicht der Fall: Zum Ausführen derartiger Projekte ist ein spezielles Programm erforderlich, und zwar ein Applikationsserver beziehungsweise -container. Unter Java hat sich Apache Tomcat als Quasi-Standard etabliert: So gut wie alle Frameworks funktionieren mit Tomcat oder sind zumindest peripher mit ihm kompatibel. Angesichts der Entwicklungsgeschichte des Servers gibt es mittlerweile vier verschiedene Versionen: Für die Arbeit mit Vaadin 7 empfiehlt sich der Einsatz der Version 8.0.

Im Artikel wird Tomcat 8.0.39 verwendet. Entwickler extrahieren das Archiv in einen für sie bequem zugänglichen Ort im Dateisystem. Eclipse ist zur Verwaltung von Applikationsservern befähigt. Das Server-Tab ist nach dem Öffnen der IDE von Haus aus versteckt, lässt sich aber durch Anklicken seines Headers auf den Bildschirm holen (s. Abb. 5).

Dieses Tab muss auf den Bildschirm geholt werden (Abb. 5).

Danach müssen Entwickler den am Bildschirm erschienenen Link anklicken, um den Assistenten zum Erzeugen einer neuen Serverbeziehung zu aktivieren. Die Java-EE-Ausgabe von Eclipse unterstützt von Haus aus eine Gruppe verschiedener Serversysteme: Hier ist die Vorlage "Tomcat V8.0 Server" zu verwenden und danach auf Next zu klicken – der Hostname localhost ist Okay.

Im nächsten Schritt fragt der Assistent, wo Tomcat installiert ist – nämlich im Extraktionsverzeichnis aus dem vorhergehenden Schritt. Das Fenster zum Hinzufügen und Entfernen von Ressourcen ist fürs Erste irrelevant. Nach Klick auf Finish, um den Server anzulegen, startet man ihn probeweise über das Server-Tab. Eclipse wird die Ausführung durch Einblenden des Labels "Started" neben dem Servernamen anzeigen – Entwickler dürfen nicht vergessen, ihn durch Klicken von Stop wieder zu beenden.

Das eigentliche Deployment erfolgt durch einen Rechtsklick auf das Projekt im Projekt-Explorer. Entwickler wählen dann die Option Debug | Debug On Server aus und im daraufhin erscheinenden Fenster den im vorherigen Schritt festgelegten Server. Es ist darauf zu achten, dass die Applikation im Deployment-Fenster erscheint und dass man danach auf Finish klickt. Nach dem Start erscheint das Fenster am Bildschirm – sowohl der Knopf als auch die Textbox sind da, wo man sie erwarten würde.

Als erstes interaktives Beispiel wird nun ein zweites Formular eingeblendet: Der Benutzer soll zwischen den beiden hin- und herwechseln können. Das Hantieren mit einem ViewProvider artet in Arbeit aus: Entwickler umgehen das Problem durch eine Navigator-Klasse. Dazu sind einige Änderungen in der Hauptklasse erforderlich – begonnen sei mit dem Anlegen einer globalen Instanz des Navigator:

@Theme("mytheme") 
public class MyUI extends UI {
Navigator myNavigator;

Als Nächstes erfährt init einige
Änderungen:

@Override
protected void init(VaadinRequest vaadinRequest) {
myNavigator = new Navigator(this, this);
NavigatorHolder.myHolder=myNavigator;
myNavigator.addView("", new EnterView());
myNavigator.addView("detail", new DetailView());
}

Statt die Steuerelemente direkt in der init-Methode zu erzeugen, erstellen Entwickler hier nun eine neue Instanz der Navigator-Klasse. Sie bekommt zudem zwei Views, die die eigentliche Anzeigelogik enthalten. Hierbei entstehen im Hintergrund – für Entwickler transparent – zwei ViewProvider, die die Anzeige und das View Switching realisieren.

Die für die eigentliche Realisierung der Views zuständigen Klassen müssen das View-Interface realisieren und sollten zudem eine Ableitung von einer Steuerelementklasse sein: Das ist insofern logisch, da sie als Inhalt des anzuzeigenden Views herangezogen werden.

Damit kann man sich nun der Implementierung der beiden Views zuwenden. Als Erstes sei der Code von EnterView betrachtet:

public class EnterView extends VerticalLayout implements View { 

@Override
public void enter(ViewChangeEvent event) {
removeAllComponents();
setSizeFull();
Button button = new Button("Detailview laden!");
button.addClickListener( e -> {
NavigatorHolder.myHolder.navigateTo("detail");

});

addComponent(button);
setComponentAlignment(button, Alignment.MIDDLE_CENTER);
}

}

Die Enter-Methode wird aufgerufen, wenn die View den Weg auf den Bildschirm antritt. Entwickler beginnen im ersten Schritt mit der Methode removeAllComponents, um noch im Container befindliche Steuerelemente zu eliminieren. Danach errichten sie die schon bekannte Struktur, die nun allerdings nur noch aus einem Knopf besteht.

Interessant ist zudem, wie die Navigation zwischen den einzelnen Files erfolgt. Entwickler rufen die navigateTo-Methode auf und übergeben dabei jenen String, der im Rahmen des Einschreibens der jeweiligen View-Klasse übergeben wurde. Die Navigator-Instanz ist zwischen den verschiedenen Files zu teilen. Man löst das über eine statische Klasse, die eine globale Version von Navigator bereitstellt:

public class NavigatorHolder { 
public static Navigator myHolder;
}

Zum Vermeiden ärgerlicher Tippfehler ist es an der Stelle empfehlenswert, die NavigatorHolder-Klasse um eine Gruppe von Konstanten zu erweitern, die die View-Strings enthalten.

Als Nächstes soll noch ein Blick auf die DetailView geworfen werden. Ihre Implementierung unterscheidet sich nur insofern von der soeben besprochenen, als der Event-Handler des Knopfes dem Navigator nun einen anderen Parameter übergibt:

public class DetailView extends VerticalLayout implements View { 
@Override
public void enter(ViewChangeEvent event) {
removeAllComponents();
setSizeFull();
Button button = new Button("...und wieder heim!");
button.addClickListener( e -> {
NavigatorHolder.myHolder.navigateTo("");
...

Damit ist das vorliegende Programm zur Ausführung bereit: Zu beachten ist, dass sich der Inhalt der Adresszeile des in Eclipse geöffneten Browserfensters beim Wechsel zwischen den Files verändert. Das ist insofern wichtig, als Nutzer so die Adresszeilen nutzen können, um bestimmte Teile des Programms direkt anzuspringen.