GWT wird verwendet um moderne, komplexe Rich Internet Applications zu erstellen. Durch die Generierung von JavaScript aus Java Code können alle Vorteile von Java genützt und gleichzeitig die immer größer werdenden Anforderungen der Web-Benutzer in Bezug auf Style, Performance, Interaktion und Browser-Kompatibilität von Webseiten abgedeckt werden. In dem Vortrag wird GWT vorgestellt und auf dessen Einsatz in der Praxis eingegangen.
1. GWT – Google Web Toolkit
in der Praxis
gerolf.scherr@cenarion.com
11.12.12
2. Vorstellung
Gerolf Scherr
• HTL für Elektronik
• Wirtschaftsinformatik-Studium
• Programmierer seit C64
• Gründer und Geschäftsführer von Cenarion Information Systems GmbH
Cenarion Information Systems GmbH
• 30 Mitarbeiter, Sitz in Wien
• Umfassendes Know-how der Versicherungsbranche
• Enterprise-Applikationen Entwicklung im Java-Umfeld seit über zehn
Jahren
• Dokumenten-, Workflow-, und Wissensmanagement
2
4. Historie
• <form action=„/cgi-bin/bla.pl“><input
type=„submit“> (1995)
• Host(3270) - Formularmetapher
• Ladezeit
• Back, Bookmark
• Ajax (2005)
• Asynchronous JavaScript and XML
• Client/Server
• Javascript, JSON/XML
• Viele Bibiotheken
• Flash, Java-Applets, RCP...
4
5. Vorstellung GWT
• Google 2006: Apache License 2.0
• Framework für Webanwendungen
• Entwicklung von komplexen Enterprise-Anwendungen
• Drei Komponenten
• Java zu JavaScript Compiler
• JRE Emulation Library (Java-API)
• Ui Library (GWT-API)
• Java für Client und Server
• Eclipse als Entwicklungsumgebung
• Kein Java-Plugin am Client
5
6. GWT Komponente: Compiler
•Kompiliert Java zu JavaScript
•Permutationen
• Pro Browser
• Pro Sprache (Internationalisierung)
•Code-Optimierungen
• Dead Code Elimination,
• Constant Folding,
• String Interning, ect.
•Compiler Option Style = pretty / obfuscated / detailed
•Stateful Client / Stateless Server
6
7. Development Mode
GWT Release History
Speed Tracer / Draft
Compile
Code Splitting
GWT 1.0 17.05.2006
Compiler Optimizations
RequestFactory
Declarative Uis
ClientBundle
GWT 2.0 08.12.2009 MVP, Editors
Cell Widgets
UI Designer: drag&drop Logging
HTML5: canvas, audio GWT 2.1 19.10.2010 Safe HTML
and video
New Cell Table column
SafeHtml lenient parser GWT 2.2 11.02.2011 Google API Discovery&Access
Google Project Hosting
Integration
Single Sign-on Support
App Engine Android GWT 2.3 03.05.2011 Local Storage API Availability
Apps Marketplace
GWT-Designer + Super Dev Mode
GWT 2.4 08.09.2011 Elemental
JSR 303
GWT 2.5 26.10.2012 (Aktuell)
7
8. GWT 1 vs. GWT 2
• GWT 1
•Synchrone Methoden am Server
•Asynchrone Methoden am Client
•Homebrewn DTO
•UI prozedural
• GWT 2
•Objekte am Server, Proxies am Client
•Requestfactory
•UI deklarativ, MVP
8
9. Request Factory
• Data Access Layer zwischen Client und Server
• Eigenes Servlet und Protokoll
• CRUD
• DTO Pattern
• Differenz der clientseitigen Änderungen zum Server
9
10. Request Factory
• Entity Type
• Datenbanktabelle
• Value Type
• 1-N Datenbankspalte(n)
• Embedded Objects
• Proxy
• Client-side Interface einer Entity oder eines Value Type
• Repräsentation einer Server Entity am Client
• Beinhalten nur Getter und Setter
10
11. Request Factory
Server Shared Client
Entities Proxy Interface Aufrufe der
Request Interface RequestFactory
RequestFactory Services
Interface
Frontend mit
MVP Pattern
z.B. User UserProxy z.B. Requests.UserRequest().
(nur Getter und resetPassword(object.
Setter) getId()).fire(new
UserRequest(Factory), Receiver<UserProxy>() {…}
Requests(Meta-Factory)
11
12. Aufruf der RequestFactory
Gibt nur die benötigten Teile und nicht
den ganzen Objektgraphen zurück Calls werden immer asynchron durchgeführt
requestFactory.messageRequest().insertMessage(prid, message, type,
receiver).with("processingRequest").fire(
new Receiver<MessageProxy>() {
@Override
public void onSuccess(MessageProxy response) {
…
}
Wenn die Abfrage des asynchronen
@Override Calls fertig und erfolgreich ist,
public void onFailure(ServerFailure error) { wird dieser Code ausgeführt
…
}
}
);
Das Standard Interface AsyncCallback
Benötigt die Implementierung beider Methoden
12
13. UI mit GWT
•Deklaratives Layout mit UiBinder (ab GWT2)
•Widgets (Ui-Componenten: Button / TextBox / DateBox,
VerticalPanel etc.)
•Ui:Binder
• Java Klasse
• Ui.xml (Template)
•Keine Business Logik
•ClientBundle
•Standard.css
•Internationalisierung mit Property Files
13
16. MVP
• Model - View - Presenter
• Designpattern, für GUI Development
• View beinhaltet keine Logik mehr
• Testing und Mocking wird einfacher
• Strengere Trennung der einzelnen
Komponenten im Vergleich zu MVC
16
17. View
Rendering
Model Logik
• MVC
Daten, die Display und
dargestellt und Interaktion mit
manipuliert werden dem Browser
UI Event
Handling Logik
Controller
Rendering
Model Logik
View
Daten, die Display und
• MVP dargestellt und
manipuliert werden
Presenter Interaktion mit
dem Browser
UI Event
Handling Logik
17
18. Places / Activity Framework
• bookmarkable URLs
• Browser History „Back-Button“
• Begriffsdefinitionen
• Activity: „Tätigkeit“
• Place: „Ort“, implementiert einen PlaceTokenizer
• ActivityMapper: Zuordnung von Place und Activity
• ActivityManager: Startet und stoppt Activities
• PlaceHistoryMapper: Deklariert alle Tokenizer Klassen (@WithTokenizers)
• View = Darstellung der Ui Komponenten
18
19. Places / Activity Framework
PlaceChange PlaceHistory
Event Handler
• Benutzer navigiert zu einem neuen
Punkt in der Applikation
• Triggert ein PlaceChangeEvent
ActivityManager
• PlaceHistoryHandler updated die URL
• ActivityManager übergibt das Event
dem entsprechenden ActivityMapper
ActivityMapper
• ActivityMapper findet angefragtes
Place mit zugehöriger Activity und
startet das Activity
• Activity instanziert den View PlaceA ActivityA
Presenter UiA.java UiA.ui.xml
19
20. Editor Framework
• Binder-Framework
• Daten aus dem Objektgraphen werden zum
Ui Field gebunden (laden/speichern)
• Felder nicht einzeln setzen
• Feldname in UI ↔ Entity
20
21. GWT bei Cenarion
• GWT Einsatz bei System „NEXA Plus“
• Spring Roo
• Spring Security
• Maven
• Artifactory (=Maven-Repository-Server)
• REST Schnittstelle
• Selenium für automatisierte Tests
• Entwicklungsumgebung: Eclipse STS / Juno
21
22. Security bei Cenarion
• JavaScript ist anfällig für unterschiedliche Attacken
• „You can‘t trust the client“
• Berechtigungskonzept
• Absicherung der Request Factory
• Absicherung der Entities und Methoden mit Security
Aspekten
• Proxyeinschränkungen mit Annotations (exclude /
readOnly)
22
23. Code Splitting bei Cenarion
• Generiertes JavaScript sehr groß
• Alle Masken in einem File
• Lange Startupzeiten
• → Codesplitting, nachladen on Demand
• GWT.runAsync(new Runnable()...)
• Gliederung der Applikation in klar definierte,
abgrenzbare Sections
• Administrations- und Userbereich
• Allgemeine und branchenspezifische Komponenten
23
25. Vorteile
• Fokussierung auf Java Expertise
• Browserunabhängigkeit
• Kenntnisse über Browser werden unwichtig
• Keine Java Installation beim Endkunden
• Request Factory (u.a. Asynchronität)
• Development mode
• Java Code Analyser Tools (FindBugx, CheckStyle,…)
• I18N und L10N
• Back-Button-Support
• Maximale UI Kapselung mit MVP und deklarativem Layout
25
26. Nachteile
• JavaScript Files werden schnell sehr groß
• → Code Splitting
• IE6??, noScript???
• Security (Absicherung von Proxies)
• Spärliche Dokumentation
• Memory! (insb. IE)
• Lange Compile-Zeiten
26
27. Anwendungsbeispiele
• Spieleentwicklung
• Rovio: Angry Birds
• GWT (mit ForPlay Library)
• HTML5
• Released im Juni 2011
• Chrome Web-Store
• Quake II
• DayZipping
27
28. The Future of GWT Report -
2012
• N: 1.349
• Ziel
“To find people in the community who are highly interested in the future of GWT -
so that we as a community can learn from their experience, benefit from their
feedback, and support their future needs”
“To work with the GWT Steering Committee to provide valuable insights and
information - so that community members can make educated decisions, and non-
GWT users can gain more visibility into the technology - to better understand its
strengths and weaknesses.”
• durchgeführt von Vaadin
28
35. GWT: Asynchronous Requests
• Asynchrone Requests bei der Client-Server
Kommunikation
• Response B kann Response A überholen. → W00t
• Race Conditions
• mehrere Requests greifen auf dieselbe UI-Komponente in
derselben Weise zu (zB enable/disable, visible)
• 'normaler' Code verlässt sich auf Daten, die aus einem
Response kommen.
• Dschungel vs. Labor
35
36. Race Conditions
• Lösung 1: Requests schachteln
+ Easy
+ Simple
– removing the a from asynchronous since 2012.
– Spaghetti-Incident
requestFactory.getFooRequest().enableButtonA().fire(new Receiver<List<X>> {
@OnSuccess
public void onSuccess(List<X> listX) {
if (!listX.isEmpty()) {
view.showButtonA(true);
}
requestFactory.getFooRequest().userHasRights().fire(new Receiver<Boolean> {
@OnSuccess
public void onSuccess(Boolean userHasRights) {
if (hasRights) {
view.enableButtonA(false);
}
}
});
});
}
36
37. Race Conditions
• Lösung 2: Proxy Value
• 1 Request, 1 Response, 2 Daten (ValueProxy)
+ wenn Requests thematisch zusammenhängen, eine sehr logische Lösung
– aufwändiger in der Implementierung
– Viele Kombinationen ungünstig (AandBProxy, AandCProxy, BandZWRProxy...)
– unerwünschte Kopplung wenn nicht zusammenpassend.
requestFactory.getFooRequest().enableButtonA().fire(new Receiver<ValueProxy> {
@OnSuccess
public void onSuccess(final ValueProxy vp) {
if (vp.getRequestBResult()) {
view.showButtonA(false);
}
else if (!vp.getRequestAResult().isEmpty()) {
view.showButtonA(true);
}
}
});
}
37
38. Race Conditions
• Lösung 3: clientseitig synchronisieren: Der Client
weiß, wieviele Requests er abwarten möchte, bevor er
gewisse UI-Komponenten entsprechend setzt.
+ volle Ausnützung der maximalen Performance, da Requests asynchron ablaufen
+ übersichtlicher Code, leicht erweiterbar um weitere Requests
– aufwändiger in der Implementierung als Lösung 1, etwa gleich wie Lösung 2
public class CountDownLatch {
int target;
Runnable action;
public CountDownLatch(int target, Runnable action) {
this.target = target;
this.action = action;
}
void pass() { // no multithreading in javascript, hence no synchronisation necessary
if (target <= 0) throw new IllegalStateException();
if (--target == 0)
action.run();
}
}
38
39. Race Conditions
• Lösung 3: Fortsetzung
public class State {
private boolean enableButtonA = false;
private boolean userHasRights = false;
public void setEnableButtonA(boolean enabled) {
this.enableButtonA = enabled;
}
public boolean isButtonAEnabled() {
return enableButtonA;
}
public void setUserHasRights(boolean hasRights) {
this.userHasRights = hasRights;
}
public boolean getUserHasRights() {
return userHasRights;
}
}
39
40. Race Conditions
• Lösung 3: Fortsetzung
final State state = new State();
final CountDownLatch latch = new CountDownLatch(2, new Runnable() {
public void run() {
// when the latch reaches 0, set the UI components
view.enableButtonA(state.isButtonAEnabled() && state.getUserHasRights());
}
});
public void start() {
requestFactory.getFoobarRequest().enableButtonA().fire(new Receiver<List<X>> {
@OnSuccess
public void onSuccess(List<X> listX) {
if (!listX.isEmpty()) {
state.setEnableButtonA(true);
}
latch.pass();
}
});
requestFactory.getFoobarRequest().userHasRights().fire(new Receiver<Boolean> {
@OnSuccess
public void onSuccess(Boolean hasRights) {
if (hasRights) {
state.setUserHasRights(false);
}
latch.pass();
}
});
}
}
40
41. Literatur
• Essential GWT, Building for the Web with Google Web Toolkit 2; 2011 Pearson
Education Inc.
• Web/Youtube
https://developers.google.com/web-toolkit/
http://www.summa-tech.com/blog/2011/05/03/a-pattern-for-gwt-code-splitting/
http://www.youtube.com/watch?v=imiquTOLl64&feature=relmfu
http://www.youtube.com/watch?v=oiNfPjV72lg
http://www.youtube.com/watch?v=kV5H3rGfqOE
http://www.youtube.com/watch?v=KEkR1ox_K10
http://www.youtube.com/watch?v=imiquTOLl64
http://www.youtube.com/watch?v=g2XclEOJdIc
http://www.youtube.com/watch?v=F_sbusEUz5w
http://tbroyer.posterous.com/gwt-211-requestfactory
http://geekandpoke.typepad.com/
http://xkcd.com/
https://vaadin.com/blog/-/blogs/the-future-of-gwt-report-2012
Notes de l'éditeur
Compiler kommt auf nächster Folie genauer JRE Emulation Library : Wegen der Art und Weise, wie der GWT Compiler funktioniert, muss auf alle Klassen des SourceCode zugegriffen werden können. -> Das überschreitet die Anforderung an die „klassische“ JRE und muss daher eine JRE Emulation Library zur Verfügung stellen. (java.lang, java.lang.annotation, java.util, java.io, java.sql) Ui Library : Große Vielfalt an Standardwidgets, ähnlich zu Swing in Java
-> Dead Code Elimination (Toter Code wird nicht umgewandelt) -> Constant Folding (Wenn zur Compile-Time Ausdrücke bereits aufgelöst werden können, werden diese im Vorhinein kalkuliert und gleich verwendet) -> String Interning (Um zu vermeiden, dass die gleichen Strings immer und immer wieder erzeugt werden, werden alle distinct strings nur einmal erzeugt) Ect = Copy Propagation -> extention to constant folding (wenn man aus den vorkalkulierten Ausdrücken weitere schlüsse ziehen kann. Bsp: a = 15, b = a*a+5 b wird behandelt wie 230 Code Inlining: Für kurze, simple Methoden substituiert GWT die Methode für den originalen Call.
http://www.javacodegeeks.com/2012/01/gwt-pros-and-cons.html Back-Button-Support mit History Class auch wenn Ajax verwendet wird
Letzten zwei Punkte: http://flashmattic.blogspot.co.at/2011/05/2-reasons-to-avoid-gwt.html
http://www.youtube.com/watch?v=F_sbusEUz5w ~90% im Iphone Store sind mit Box2d geschrieben -> JBox2d -> GWTBox2d http://code.google.com/p/quake2-gwt-port/ http://www.dayzipping.com/cities