Christian Kaltepoth | ingenit GmbH & Co. KG JSF vs. GWT? JSF und GWT!
Christian Kaltepoth | ingenit GmbH & Co. KG
JSF vs. GWT? JSF und GWT!
JavaServer Faces
• „Bodenständige Technologie“• Formularbasierte Anwendungen• Data Lifecycle
– z.B. Konvertierung + Validierung
• Mächtige Komponenten• Support für AJAX, HTML5, etc.
Aber...
• Server als zentrale Instanz– Rendering, Validierung, etc.– Viel Kommunikation mit dem Server
• PPR reicht oft nicht aus• State, State, State, ...
– Muss synchron gehalten werden– Ohne langlebige Scopes geht nichts
Ein Blick über den Tellerrand...
GWT[ i t]ɡʉˑ ˑ
GWT
• „Development toolkit for building [...] complex browser-based applications“
• Veröffentlicht 2006• Geleitet von:
– 2006-2012: Google– Seit 2012: Steering Committee
GWT Compiler
Was ist GWT?
Warum GWT statt JavaScript?
• Java als etablierte Sprache• Gewohntes Tooling
– IDE, Build Tools, Testing, ....
• Starke Typisierung– Compiler Checks, Static Code Analysis, ...
• GWT kümmert sich um:– DOM Garbage Collection– Inkompatibilitäten zwischen Browsern
Server Client
Shared Code!
GWT
• GWT Compiler• Client Bundles• Deferred Binding• RequestBuilder• I18N• Logging• UI Components
• RequestFactory• Testing• GWT-RPC• UI Binder• Editors• JSNI• Code Splitting
GWT
• GWT Compiler• Client Bundles• Deferred Binding• RequestBuilder• I18N• Logging• UI Components
• RequestFactory• Testing• GWT-RPC• UI Binder• Editors• JSNI• Code Splitting
Ist GWT überhaupt noch„State of the Art“?
Google Sheets
Google Shopping Express
Evernote
„Hello World!“ mit GWT
DEMO
Kann man JSF und GWT kombinieren?
Ja, das geht! ☺
JSF & GWT
• Das Ziel:– Clientseitige Funktionalität– Mehr Interaktivität– User Experience
• Die Herausforderung:– Interaktion mit JSF Komponenten– JSF Lifecycle nicht beeinflussen
JSF + GWT
Eine Beispielanwendung
Was ist das BMS?
• Bäckerei Verwaltungssoftware• JEE7 Anwendung mit JSF 2.2• Artikelmanagement
– Stammdaten, Kosten, Preise, ...
• Rezeptverwaltung• Berechnung der Produktionskosten
Sprint 23: Einkaufspreise
Featurewunsch
„Graphische Aufbereitung der Auswirkungen
von Einkaufspreisveränderung auf die Herstellungskosten
der betroffenen Artikel.“
Probleme
• Kostenberechnung im Backend!• JavaScript Komponente sinnvoll!
– Interaktivität (Tooltips, etc.)
• Berechnung auf dem Server?– RTT problematisch!
• Neuimplementierung der Berechnungslogik in JavaScript?
Lösungsansatz
• Implementierung mittels GWT– Eingaben aus JSF Komponenten auf dem
Client auslesen– Berechnungslogik als Shared Code– Nutzung von JavaScript Chart Library für
die Grafik (d3.js)
BMS DEMO
Was brauchen wir?
• Interaktion mit JSF Komponenten➡ GWT Components
• Integration der JavaScript Library➡ JSNI
• Kommunikation mit Server➡ Remoting
GWT Components
GWT Components
• Realisiert als „einfache“ Klassen• Unterklassen von Widget• Tiefe Vererbungshierarchie• Verschiedene Typen:
– Widgets / Panels / Composites
• Component > DOM Element + Kinder
Klassenhierarchie
Quelle: Book of Vaadin - https://vaadin.com/book/
Beispiel: PasswordTextBox
GWT Components
• Basic: – Button– RadioButton– Checkbox– Textbox– Textarea– Listbox– ...
• Advanced:– DatePicker– MenuBar– Tree– SuggestBox– CellTable– Dialog– ...
Komponentenbaum
Label label = new Label("Name:");
TextBox textbox = new TextBox();textbox.setText("Christian");
FlowPanel panel = new FlowPanel();panel.add(label);panel.add(textbox);
RootPanel.get().add(panel);
Eigene Komponenten
<input type="input" placeholder="Enter email" />
Eigene Komponenten
public class Html5TextBox extends TextBox {
public void setPlaceholder(String value) { getElement().setPropertyString("placeholder", value); }
public String getPlaceholder() { return getElement().getPropertyString("placeholder"); }
}
Für uns interessant...<input id="foobar" type="text" />
Element element = Document.get().getElementById("foobar");
TextBox textBox = TextBox.wrap(element);
textBox.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { // ... }});
Was heißt das?
• Zugriff auf DOM Element der JSF Komponenten ist einfach möglich
• Erlaubt uns...– ... aktuelle Werte zu lesen– ... den Zustand zu verändern– ... Listener zu registrieren
JSNI(JavaScript Native Interface)
„We think of JSNI as the web equivalent of inline
assembly code.“
Quelle: http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html
JSNI Beispiel public void someMethod() {
sayHello(); }
private native void sayHello() /*-{
alert('Hello World!');
}-*/;
Beispiel: jQuery Integration
public void someMethod() {
fadeOut("foobar");
}
private native void fadeOut(String className) /*-{
$wnd.jQuery('.' + className).hide(800);
}-*/;
Overlay Types
public native <????????> getKonferenz() /*-{
var konferenz = { name : 'JAX', jahr : 2014 }; return konferenz;
}-*/;
Overlay Typespublic class Konferenz extends JavaScriptObject {
protected Konferenz() {}
public final native String getName() /*-{ return this.name; }-*/;
public final native int getJahr() /*-{ return this.jahr; }-*/;
}
Overlay Typespublic native Konferenz getKonferenz() /*-{
// ...
}-*/;
public void someMethod() {
Konferenz konferenz = getKonferenz();
Window.alert("Hello " + konferenz.getName());
}
Was heißt das?
• Einbindung von JavaScript Komponenten problemlos möglich
• Overlay Types erlauben:– Zugriff auf JavaScript Objekte– „Parsen“ von JSON Dokumenten
Remoting
Optionen für Remoting
• Standard GWT– GWT RPC– RequestBuilder– ...
• 3rd Party Bibliotheken– RestyGWT– ...
GWT RPC
• RPC Framework auf Basis von Servlets• Pro:
– Standard GWT– Geteilte Modellobjekte
• Contra:– Proprietäres Datenformat (kein JSON)– Relativ viele Klassen– Performance
RequestBuilder
• Für GWT optimierter HTTP Client• Pro:
– Standard GWT– Nutzung von Standard JSON APIs
• Contra:– Benötigt Overlay Types– Manuelles Erstellen der URL
JAX-RS Resource@Path("/")public class ZutatenResource {
@GET @Path("/zutat/{name}") @Produces("application/json") public Zutat getByName( @PathParam("name") String name) {
// ...
}
}
JAX-RS Resource
RestyGWT Clientpublic interface ZutatenClient extends RestService {
@GET @Path("/zutat/{name}") public void getByName( @PathParam("name") String name, MethodCallback<Zutat> callback);
}
RestyGWT ClientZutatenClient client = GWT.create(ZutatenClient.class);
client.getArtikel("Zucker", new MethodCallback<Zutat>() {
@Override public void onSuccess(Method method, Zutat response) { // ... }
@Override public void onFailure(Method method, Throwable e) { // ... }
});
Zusammenfassung
GWT RPC
RequestBuilder
RestyGWT
Standard GWT + + -
Shared Model Classes + - +
JSON via JAX-RS - + +
Was heißt das?
• Kommunikation mit dem Server auf verschiedene Arten möglich
• Wir verwenden RestyGWT:– Nutzung von JAX-RS– Modellobjekte als Shared Code
• Funktioniert auch mit JPA Entitäten!
– Stark typisierte Client API
Time for...Source Code!
Fazit
• JSF & GWT lassen sich kombinieren• Keine „Lösung für Alles“• Kann sinnvoll sein, wenn...
– geteilter Code benötigt wird– bestehende JSF Anwendungen mehr
„Interaktivität“ benötigen– Typensicherheit gewünscht wird
Vielen Dank für die Aufmerksamkeit!
https://github.com/chkal/jax14-jsf-gwt
Christian [email protected] @chkal