Publicidad
Publicidad

Más contenido relacionado

Publicidad

Último(20)

GWT – Google Web Toolkit in der Praxis

  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
  3. Einleitung • Ablöse Desktop • Höhere Ansprüche • Stylisch, Intuitiv • International, Sicher, Schnell • Überall verfügbar(Mobile Geräte, Handys) • Kein Rollout 3
  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
  14. UI Binding CmpProfile.java CmpProfile.ui.xml package com.cenarion.client.nexaplus.ui; <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" Import […] xmlns:g="urn:import:com.google.gwt.user.client.ui"> public class CmpProfile extends Composite { <g:HTMLPanel> <g:VerticalPanel ui:field="upper" width="100%"> private static DlgProfileUiBinder uiBinder = GWT <g:FlowPanel ui:field="pnlHeader"> .create(DlgProfileUiBinder.class); <g:Label ui:field="lblHeader"></g:Label> </g:FlowPanel> interface DlgProfileUiBinder extends UiBinder<Widget, CmpProfile>{ <g:Grid> } <g:row> <g:customCell> @UiField <g:Label ui:field="lblLoginText"/> Button btnClose, btnSave; </g:customCell> @UiField <g:customCell> Label lblLogin, lblUsernameText, lblUsername, lblChange_pwdText, lblRepeat_pwdText, lblEmailText, <g:Label ui:field="lblLogin"/> lblEmail, lblPwdChangeText, lblPwdChange, lblOld_pwdText, </g:customCell> lblLoginText, lblHeader; </g:row> […] […] </g:Grid> private PnlHeaderPresenter presenter; <g:FlowPanel ui:field="lower"> <g:Button ui:field="btnSave"></g:Button> public CmpProfile() { <g:Button ui:field="btnClose"></g:Button> […] </g:FlowPanel> } </g:VerticalPanel> </g:HTMLPanel> @UiHandler("btnSave") </ui:UiBinder> void onSaveClick(ClickEvent event) { presenter.saveProfileClicked(txtChangePwd.getText(), txtRepeat_pwd.getText(), txtOldPwd.getText(), null); } } 14
  15. GWT Designer 15
  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
  24. Code Splitting bei Cenarion • Initialisierung: Lade JavaScript 1 • Navigation zu Section 2: Lade JavaScript 2 • Navigation zu Section 3: Lade JavaScript 3 • PlaceChange: Composite Activity Mapper delegiert zur entsprechenden Section Activity 1 Section 1 Activity Mapper Activity 2 Section 1 Section 1 Composite Activity Activity Mapper Activity 3 Mapper Section 2 Section 1 Activity Mapper Section 3 24
  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
  29. How ist GWT used today? 29
  30. Anwendungsgröße* *Size of uncompressed obfuscated JavaScript 30
  31. Anwendungsgröße* *Anzahl Masken 31
  32. Vorteile 32
  33. Größte Baustellen 33
  34. Diskussion 34
  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

Notas del editor

  1. 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. -&gt; 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
  2. -&gt; Dead Code Elimination (Toter Code wird nicht umgewandelt) -&gt; Constant Folding (Wenn zur Compile-Time Ausdrücke bereits aufgelöst werden können, werden diese im Vorhinein kalkuliert und gleich verwendet) -&gt; 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 -&gt; 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.
  3. http://www.javacodegeeks.com/2012/01/gwt-pros-and-cons.html Back-Button-Support mit History Class auch wenn Ajax verwendet wird
  4. Letzten zwei Punkte: http://flashmattic.blogspot.co.at/2011/05/2-reasons-to-avoid-gwt.html
  5. http://www.youtube.com/watch?v=F_sbusEUz5w ~90% im Iphone Store sind mit Box2d geschrieben -&gt; JBox2d -&gt; GWTBox2d http://code.google.com/p/quake2-gwt-port/ http://www.dayzipping.com/cities
Publicidad