Oracles Project Avatar – Komplettansatz für moderne Webanwendungen

Seite 2: Server-Kommunikation

Inhaltsverzeichnis

Die so generierte Struktur entspricht der einer Java-EE-Web-Anwendung mit einem leeren WEB-INF-Verzeichnis und einer avatar.properties-Datei für erweiterte Einstellungen im root-Verzeichnis. Es sind noch zwei weitere Verzeichnisse möglich (view und service), in die die entsprechenden Komponenten der Anwendung gehören. GlassFish wird bekannter Weise mit

asadmin start-domain

gestartet und mit dem ebenfalls bekannten

asadmin deploy hello 

lässt sich die Avatar-Anwendung bereitstellen. Navigiert man mit dem Browser jetzt auf http://localhost:8080/hello, gelangt man zu der Anwendung.

"Hello Avatar"-Beispielanwendung (Abb. 2)


Dabei handelt es sich um ein sehr einfaches Beispiel, das lediglich ein lokales Datenmodell mit zugehöriger Daten-Bindung demonstriert. Um die Grundprinzipien besser zu verstehen, kann man die Anwendung einfach um einen Service erweitern. Aktuell gibt es keine direkte IDE mit Unterstützung für Avatar-Projekte, was sich frühestens mit der aktuell in der Betaphase befindlichen Version 8.0 von NetBeans ändert. Daher tun es bis auf Weiteres jeder beliebige Texteditor oder spezialisierte IDEs wie WebStorm von JetBrains.

Die Beispielanwendung verwendet jQuery und startet das View-Modul hello über die Avatar.js-API. Den zugehörigen Code findet man in der Datei index.html, die direkt im view-Verzeichnis liegt. Das eigentliche Modul findet sich im src-Unterverzeichnis und heißt hello.html. Es enthält die Daten-Modell-Definition sowie die Bindungen der UI-Elemente an das Modell. Das Modell ist dabei ein einfaches JavaScript-Objekt, dass durch die Konstruktor-Syntax beschrieben ist.

<script data-model="local" data-instance="name"> 
var NameModel = function() {
this.first = "Planet"; this.last = "Earth";
this.clear = function() {
this.first = this.last ="";
};
};
</script>

Das HTML 5 Custom Attribute data-instance stellt das Objekt zum Binding unter dem Namen name zur Verfügung. Die Input-Felder lassen sich direkt mit den aus der Expression Language (EL) bekannten Ausdrücken an das Modell binden.

<input id="fn" type="text"data-value="#{name.first}"/>

Im Beispiel findet keine Server-Kommunikation statt. Es greift lediglich auf ein lokales Modell zu und verändert es. Spannender wird es, wenn die Seite noch die aktuelle Systemzeit anzeigen soll. Letztere kommt via REST vom Server und soll bei einem Klick auf einen Update-Button neu laden.

Erster Schritt ist ein Service-Modul mit der gewünschten Funktion. Auf gleicher Ebene zum view-Verzeichnis legt man ein neues Verzeichnis service und darunter ein Verzeichnis src an und erstellt dort eine Datei mit dem Namen main.js. Nach dem Import der Avatar-Referenz wird eine Funktion getTime mit der aktuellen Uhrzeit implementiert.

var avatar = require("org/glassfish/avatar"); 
var getTime = function() {
var current = new Date();
return {
msg: 'The server time is ',
h:current.getHours(),
m: current.getMinutes(),
s:current.getSeconds() };
};

Jetzt fehlt nur noch der REST-Service, der sich durch die Methode registerRestService integrieren lässt. Ihr wird lediglich der Namensraum der REST-Resource angegeben ("data/time"). Lifecycle-Methoden behandeln die Requests. Standardmäßig geht Avatar davon aus, dass als Mime-Type application/json zum Einsatz kommt. Registrierung und Implementierung der Methode sehen fertig folgendermaßen aus:

avatar.registerRestService({ url: "data/time" },
function() {
this.$onGet = function(request,response){
return response.$send(getTime());
};
}
);

Nach einem Neuladen der Anwendung steht der REST-Service direkt zur Verfügung und lässt sich mit Werkzeugen wie Postman ansprechen. Ein HTTP-GET auf http://localhost:8080/hello/data/time liefert dann

{ 
"msg": "The server time is ",
"h": 10,
"m": 35,
"s": 53
}

Jetzt fehlt nur noch die Einbindung in die View-Komponente. Neben dem Datenmodell und dem REST-Aufruf fehlen noch ein Ausgabebereich und eine Schaltfläche, um die Anzeige zu Aktualisieren:

<script data-model="rest"> 
var Message = function() {
this.msg = this.h = this.m = this.s = '';
};
</script>

<script data-type="Message"
data-instance="message"
data-url="data/time"></script>
<output class="time">#{message.msg}#{message.h}:#{message.m}:#{message.s}</output>
<button onclick="#{message.$get()}">Update</button>

Damit ist der neue Service schon integriert und lässt sich verwenden. Ein Neuladen der Anwendung über den Browser zeigt direkt die veränderte View an.

"Hello Avatar"-Beispielanwendung mit REST (Abb. 3)

Das automatische Kompilieren kann der Entwickler über eine Einstellung in der Datei avatar.properties ausschalten. Dazu entfernt man einfach das Flag debug=true oder setzt es auf false.