RJUG : 12-Mar-2012                                                                                 © Copyright 2013, Softw...
RJUG : 12-Mar-2012                                                                                         © Copyright 201...
RJUG : 12-Mar-2012                                          © Copyright 2013, Software Alchemy                            ...
RJUG : 12-Mar-2012                                    © Copyright 2013, Software Alchemy                                  ...
RJUG : 12-Mar-2012                                                   © Copyright 2013, Software Alchemy                   ...
RJUG : 12-Mar-2012                                                                                                        ...
RJUG : 12-Mar-2012                                                                                                        ...
RJUG : 12-Mar-2012                                                                                                        ...
RJUG : 12-Mar-2012                                       © Copyright 2013, Software Alchemy                               ...
RJUG : 12-Mar-2012                                   © Copyright 2013, Software Alchemy                                  S...
RJUG : 12-Mar-2012                                               © Copyright 2013, Software Alchemy                       ...
RJUG : 12-Mar-2012                                        © Copyright 2013, Software Alchemy                              ...
RJUG : 12-Mar-2012                                                                                            © Copyright ...
RJUG : 12-Mar-2012                                                          © Copyright 2013, Software Alchemy            ...
RJUG : 12-Mar-2012                                                           © Copyright 2013, Software Alchemy           ...
RJUG : 12-Mar-2012                                                              © Copyright 2013, Software Alchemy        ...
RJUG : 12-Mar-2012                                                     © Copyright 2013, Software Alchemy                 ...
RJUG : 12-Mar-2012                                                                © Copyright 2013, Software Alchemy      ...
RJUG : 12-Mar-2012                                             © Copyright 2013, Software Alchemy                         ...
RJUG : 12-Mar-2012                                                             © Copyright 2013, Software Alchemy         ...
RJUG : 12-Mar-2012                                                          © Copyright 2013, Software Alchemy            ...
RJUG : 12-Mar-2012                                          © Copyright 2013, Software Alchemy                            ...
RJUG : 12-Mar-2012                                                                                                        ...
RJUG : 12-Mar-2012                                                      © Copyright 2013, Software Alchemy                ...
RJUG : 12-Mar-2012                                                       © Copyright 2013, Software Alchemy               ...
RJUG : 12-Mar-2012                                                                               © Copyright 2013, Softwar...
RJUG : 12-Mar-2012                                  © Copyright 2013, Software Alchemy                                  GW...
RJUG : 12-Mar-2012                                                                 © Copyright 2013, Software Alchemy     ...
RJUG : 12-Mar-2012                                  © Copyright 2013, Software Alchemy                                  GW...
RJUG : 12-Mar-2012                                                                                         © Copyright 201...
RJUG : 12-Mar-2012                                                © Copyright 2013, Software Alchemy                      ...
RJUG : 12-Mar-2012                                            © Copyright 2013, Software Alchemy                          ...
RJUG : 12-Mar-2012                                    © Copyright 2013, Software Alchemy                                  ...
RJUG : 12-Mar-2012                                      © Copyright 2013, Software Alchemy                                ...
RJUG : 12-Mar-2012                                      © Copyright 2013, Software Alchemy                                ...
RJUG : 12-Mar-2012                                           © Copyright 2013, Software Alchemy                           ...
RJUG : 12-Mar-2012                                        © Copyright 2013, Software Alchemy                              ...
RJUG : 12-Mar-2012                                                       © Copyright 2013, Software Alchemy               ...
RJUG : 12-Mar-2012                                                                           © Copyright 2013, Software Al...
RJUG : 12-Mar-2012                                           © Copyright 2013, Software Alchemy                           ...
RJUG : 12-Mar-2012                                    © Copyright 2013, Software Alchemy                                  ...
RJUG : 12-Mar-2012                                       © Copyright 2013, Software Alchemy                               ...
RJUG : 12-Mar-2012                                        © Copyright 2013, Software Alchemy                              ...
RJUG : 12-Mar-2012                                                              © Copyright 2013, Software Alchemy        ...
RJUG : 12-Mar-2012                                                                © Copyright 2013, Software Alchemy      ...
RJUG : 12-Mar-2012                                                               © Copyright 2013, Software Alchemy       ...
RJUG : 12-Mar-2012                                                       © Copyright 2013, Software Alchemy               ...
RJUG : 12-Mar-2012                                                                   © Copyright 2013, Software Alchemy   ...
RJUG : 12-Mar-2012                                                     © Copyright 2013, Software Alchemy                 ...
RJUG : 12-Mar-2012                                          © Copyright 2013, Software Alchemy                            ...
RJUG : 12-Mar-2012                                                                                                © Copyri...
RJUG : 12-Mar-2012                                     © Copyright 2013, Software Alchemy                                 ...
RJUG : 12-Mar-2012                                                                                 © Copyright 2013, Softw...
RJUG : 12-Mar-2012                                                     © Copyright 2013, Software Alchemy                 ...
RJUG : 12-Mar-2012                               © Copyright 2013, Software Alchemy                                  Error...
RJUG : 12-Mar-2012                                                              © Copyright 2013, Software Alchemy        ...
RJUG : 12-Mar-2012                                    © Copyright 2013, Software Alchemy                                  ...
RJUG : 12-Mar-2012                                                           © Copyright 2013, Software Alchemy           ...
RJUG : 12-Mar-2012                                            © Copyright 2013, Software Alchemy                          ...
RJUG : 12-Mar-2012                                          © Copyright 2013, Software Alchemy                            ...
RJUG : 12-Mar-2012                                                                                        © Copyright 2013...
RJUG : 12-Mar-2012                                                                                                   © Cop...
RJUG : 12-Mar-2012                                                                                                        ...
RJUG : 12-Mar-2012                                                      © Copyright 2013, Software Alchemy                ...
RJUG : 12-Mar-2012                                                       © Copyright 2013, Software Alchemy               ...
RJUG : 12-Mar-2012                                           © Copyright 2013, Software Alchemy                           ...
RJUG : 12-Mar-2012                                                              © Copyright 2013, Software Alchemy        ...
RJUG : 12-Mar-2012                                         © Copyright 2013, Software Alchemy                             ...
RJUG : 12-Mar-2012                                                      © Copyright 2013, Software Alchemy                ...
RJUG : 12-Mar-2012                                                        © Copyright 2013, Software Alchemy              ...
RJUG : 12-Mar-2012                                           © Copyright 2013, Software Alchemy                           ...
RJUG : 12-Mar-2012                                             © Copyright 2013, Software Alchemy                         ...
RJUG : 12-Mar-2012                                                        © Copyright 2013, Software Alchemy              ...
RJUG : 12-Mar-2012                                                        © Copyright 2013, Software Alchemy              ...
RJUG : 12-Mar-2012                                                               © Copyright 2013, Software Alchemy       ...
RJUG : 12-Mar-2012                                                                                                   © Cop...
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Google Web Toolkit: a case study
Upcoming SlideShare
Loading in...5
×

Google Web Toolkit: a case study

2,794

Published on

"Google Web Toolkit" presents a case-study in GWT v2 development. This is an introductory to intermediate talk that looks at solid practices for developing a rich Web GUI within the context of a Spring v3 backend architecture.

In the talk Bryan will present:

* Introduction to GWT (basic demo app)
* Building View
* Building Presenters
* Talking to the Server
* Extending GWT
* DataGrids in GWT

Published in: Software, Technology, Business
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,794
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
71
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Google Web Toolkit: a case study

  1. 1. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy The Google Web Toolkit Getting started Using Building Data Grids Views Google Web Toolkit Extending Building GWT Presenters Talking to the Server Bryan Basham Software Alchemy basham47@gmail.com http://www.linkedin.com/in/SoftwareAlchemistBryan Basham – The Google Web Toolkit Slide 1
  2. 2. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Getting Started... View Presenter Model Like Java RMI MVP ...but asynchronous RPC Single-Page Model Config Getting started DEMO #1 Using Building Data Grids Views Google Web Toolkit Extending Building GWT Presenters Talking to the ServerBryan Basham – The Google Web Toolkit Slide 2
  3. 3. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy GWT Basics ● Single-Page Web Applications ● Rich-client: phat without being fat ● GUI code built in Java but translated into JavaScript at build-time – Java classes represent HTML elements and widgets – Rich client-side domain model using Java POJOs ● Client/server communication via OO-based RPC; a lot like Javas RMIBryan Basham – The Google Web Toolkit Slide 3
  4. 4. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Demo: “Hello World”Bryan Basham – The Google Web Toolkit Slide 4
  5. 5. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Typical GWT Architecture Desktop Internet Server Database User ........... ........... ........... Client-side Server-side Components Components & DTOs & EntitiesBryan Basham – The Google Web Toolkit Slide 5
  6. 6. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Typical GWT Architecture Desktop Internet Server Database User ........... ........... ........... use gen r ac e rate tion sH GWTs serialization and RPC protocol s s all Other TM rc RPC over Ajax/HTTP requests RPC rve Server-side L se /async /impl Components Boundary reads & Entities transfer objects (both directions) DTO GWT ComponentsBryan Basham – The Google Web Toolkit Slide 6
  7. 7. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Typical GWT Architecture Desktop Internet Server Database User ........... ........... ........... use gen L SQ r ac e rate tion sH GWTs serialization and RPC protocol delegate to CRUD s s all TM rc RPC over Ajax/HTTP requests RPC Service DAO rve L se /async /impl s» a te re Boundary reads «c transfer objects (both directions) ? DTO Entity GWT Components Spring ComponentsBryan Basham – The Google Web Toolkit Slide 7
  8. 8. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Typical GWT Architecture Desktop Internet Server Database User ........... ........... ........... use gen L SQ r ac e rate tion sH GWTs serialization and RPC protocol delegate to CRUD s ll s TM ca RPC over Ajax/HTTP requests RPC Service DAO rv er L se /async /impl s» a te re Boundary reads «c into client-side DTO transforms DTO Transformer Entity GWT Components Spring ComponentsBryan Basham – The Google Web Toolkit Slide 8
  9. 9. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Single-Page Web Apps ● All of the GUI is built with GWT Java code, which becomes JavaScript at build-time ● GWT provides a wide variety of panel widgets to hide complexity, such as: – Using a DeckLayoutPanel to manage a deck of sub-panels in a wizard – Using a TabLayoutPanel to manage a complex Domain model ● Use the RootLayoutPanel object to build a GUI that dynamically resizes as the browser resizesBryan Basham – The Google Web Toolkit Slide 9
  10. 10. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy SPWA Structure ● The basic SPWA structure of a GWT app: – A single HTML file – One or more CSS files – An “entry point” class – And the web.xml, of course.Bryan Basham – The Google Web Toolkit Slide 10
  11. 11. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example: GWT Root Page <!doctype html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link type="text/css" rel="stylesheet" href="MyApp.css"> <title>Web Application Starter Project</title> <script type="text/javascript" src="myapp/myapp.nocache.js"></script> </head> <body> <!-- OPTIONAL: include this if you want history support --> <iframe src="javascript:" id="__gwt_historyFrame" tabIndex=-1 style="position:absolute;width:0;height:0;border:0"></iframe> <!-- Main View of the app --> <div id=view></div> </body> </html>Bryan Basham – The Google Web Toolkit Slide 11
  12. 12. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example: Entry Point Class public class MyApp implements EntryPoint { /** * This is the entry point method. */ public void onModuleLoad() { MyPresenter page = new MyPresenter(); RootPanel.get("view").add(page.getView()); } } ● A GWT app could have many presenter/views but typically you will want to create a top-level view for the whole SPWA. ● The MyApp is far too simple to need that, but the Alloy demo will demonstrate this architecture.Bryan Basham – The Google Web Toolkit Slide 12
  13. 13. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Model-View-Presenter ● Similar to the popular Model-View-Controller pattern, but cleaner separation: ls e r cal RPC serv /async user actions signals events generates HTML View sends data Presenter reads User DTO – User interacts with the View – View interacts with the Presenter – Presenter interacts with the Model – Model provides: ● communication with the Server using RPC ● entity representation using DTOsBryan Basham – The Google Web Toolkit Slide 13
  14. 14. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Views ● A View generates the HTML of the page and transfers user actions to the Presenter ● A View is composed of three elements: – The UI-Binder config file (View.ui.xml) declares the layout of the GUIs widgets – The Java file (View.java) provides the code to: ● handle modifying the view when the model changes ● handle user events from the browser – Any static support files, such as style sheets, images and other mediaBryan Basham – The Google Web Toolkit Slide 14
  15. 15. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example: View.ui.xml <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> <ui:UiBinder xmlns:ui=urn:ui:com.google.gwt.uibinder xmlns:g=urn:import:com.google.gwt.user.client.ui> <g:HTMLPanel> <h1>Web Application Starter Project</h1> <table align="center"> <tr> <td colspan="2" style="font-weight:bold;">Please enter your name:</td> </tr> <tr> <td id="nameFieldContainer"> <g:TextBox ui:field="nameField" /> </td> <td id="sendButtonContainer"> <g:Button ui:field="sendButton">Send</g:Button> </td> </tr> <tr> <td colspan="2" style="color:red;" id="errorLabelContainer"> <g:Label ui:field="errorLabel" /> </td> </tr> </table> </g:HTMLPanel> </ui:UiBinder>Bryan Basham – The Google Web Toolkit Slide 15
  16. 16. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example: View.java public class MyView extends Composite { interface MyUiBinder extends UiBinder<HTMLPanel, MyView> { } private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); @UiField Button sendButton; @UiField TextBox nameField; @UiField Label errorLabel; private final MyPresenter myPresenter; private final GreetingDialogBox dialogBox; public MyView(MyPresenter myPresenter) { this.myPresenter = myPresenter; this.dialogBox = new GreetingDialogBox(/* details skipped */); // createAndBindUi initializes fields initWidget(uiBinder.createAndBindUi(this)); // Focus the cursor on the name field when the app loads nameField.setText("GWT User"); nameField.setFocus(true); nameField.selectAll(); sendButton.addStyleName("sendButton"); } // More code on next slideBryan Basham – The Google Web Toolkit Slide 16
  17. 17. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example: View.java (part 2) public class MyView extends Composite { // More code on previous slide public void displayError(String message) { errorLabel.setText(message); } public void showFailure(final String message) { dialogBox.showFailure(message); } public void showSuccess(final String message) { dialogBox.showSuccess(message); } @UiHandler("nameField") void handleEnterKey(final KeyUpEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { sendNameToServer(); } } @UiHandler("sendButton") void handleSendBtn(final ClickEvent event) { sendNameToServer(); } // More code on next slideBryan Basham – The Google Web Toolkit Slide 17
  18. 18. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example: View.java (part 3) public class MyView extends Composite { // More code on previous slide private void sendNameToServer() { // First, we validate the input. errorLabel.setText(""); String name = nameField.getText(); if (!FieldVerifier.isValidName(name)) { errorLabel.setText("Please enter at least four characters"); return; } // Then, we send the input to the server. sendButton.setEnabled(false); dialogBox.reset(name); myPresenter.sendToServer(name); } }Bryan Basham – The Google Web Toolkit Slide 18
  19. 19. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Presenters ● A Presenter component converts User actions, via the View, into Server-side commands using an RPC component. ● A Presenter passes data from the Server to the Views, eg) a list of DTOs to a grid. ● Presenter class should be free of View-related aspects (no interaction with widgets): – Makes the business-logic code cleaner – Permits simple unit-testingBryan Basham – The Google Web Toolkit Slide 19
  20. 20. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example: MyPresenter.java public class MyPresenter { /** Create a remote service proxy to talk to the server-side Greeting service. */ private final GreetingServiceAsync greetingRPC = GWT.create(GreetingService.class); private final MyView view; public MyPresenter() { this.view = new MyView(this); } public MyView getView() { return view; } public void sendToServer(final String name) { greetingRPC.sayHello(name, new AsyncCallback<String>() { public void onFailure(Throwable caught) { view.showFailure(SERVER_ERROR); } public void onSuccess(String result) { view.showSuccess(result); } }); } }Bryan Basham – The Google Web Toolkit Slide 20
  21. 21. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Data Transfer Objects (DTO) ● DTOs provide a client-side representation of the applications Domain Model – Basically just a JavaBean, with a no-arg ctor and properties with get/set methods – Must implement the IsSerializable interface – Property values are limited to: ● Java primitives and wrapper classes ● Most java.util classes (Date, ArrayList, etc) ● Other GWT-serializable DTO classes ● Why not just use your Entity beans?Bryan Basham – The Google Web Toolkit Slide 21
  22. 22. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Remote Procedure Calls (RPC) ● RPC components provide communication with the Server, much like Javas RMI ● GWTs RPC mechanism requires: – The synchronous interface (MyRPC.java) – The implementation class (MyRPCImpl.java) – The asynchronous interface (MyRPCAsync.java) ● The Presenter makes calls to RPC components using the asych interface – This is necessary because Ajax is used, which requires callback functionsBryan Basham – The Google Web Toolkit Slide 22
  23. 23. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy RPC (Architecture Diagram) The Async interface is based upon the Sync interface but with an additional Callback<ReturnType> parameter. «interface» «interface» MyRPCAsync MyRPC This class implementation is provided by GWT which contains boiler-plate code to make Ajax requests. server calls GWTs serialization and RPC protocol delegates to Boundary «class» over Ajax/HTTP requests GWT RPC «class» MyRPCAsync_ servlet MyRPCImpl impl GWT also provides a Servlet which: ● Handles the RPC requests ● De-serializes the arguments ● Delegates the RPC call to the appropriate RPC implementation ● Serializes the method return valueBryan Basham – The Google Web Toolkit Slide 23
  24. 24. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example RPC Component ● GreetingService interface: @RemoteServiceRelativePath("greet") public interface GreetingService extends RemoteService { String sayHello(String name) throws IllegalArgumentException; } ● GreetingService implementation class: public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { public String sayHello(String input) throws IllegalArgumentException { // Verify that the input is valid. if (!FieldVerifier.isValidName(input)) { throw new IllegalArgumentException( "Name must be at least 4 characters long"); } String serverInfo = getServletContext().getServerInfo(); String userAgent = getThreadLocalRequest().getHeader("User-Agent"); return "Hello, " + input + "!<br><br>I am running " + serverInfo + ".<br><br>It looks like you are using:<br>" + userAgent; } }Bryan Basham – The Google Web Toolkit Slide 24
  25. 25. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Example RPC Component (pt 2) ● GreetingServiceAsync interface: public interface GreetingServiceAsync { void sayHello(String input, AsyncCallback<String> callback) throws IllegalArgumentException; } ● web.xml configuration: <servlet> <servlet-name>greetServlet</servlet-name> <servlet-class>com.example.myapp.server.GreetingServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>greetServlet</servlet-name> <url-pattern>/myapp/greet</url-pattern> </servlet-mapping>Bryan Basham – The Google Web Toolkit Slide 25
  26. 26. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy RPC (Interaction Diagram) Boundary «class» GWT RPC GWT RPC «class» MyRPCAsync_ invoker servlet MyRPCImpl impl sayHello(name, callback) payload[sayHello|Fred] sayHello(name) name:String “Fred” name:String “Fred” callback: AsyncCallback<String> return payload[Hello Fred] result:String onSuccess(result) “Hello Fred” result:String “Hello Fred”Bryan Basham – The Google Web Toolkit Slide 26
  27. 27. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy GWT Configuration ● A GWT project is organized into Java src and Webapp files in the war directory. ● The MyApp.gwt.xml file is the primary config file.Bryan Basham – The Google Web Toolkit Slide 27
  28. 28. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy GWT Configuration <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd "> <module rename-to=myapp> <!-- Inherit the core Web Toolkit stuff. --> <inherits name=com.google.gwt.user.User/> <!-- Inherit the default GWT style sheet. --> <inherits name=com.google.gwt.user.theme.clean.Clean/> <!-- Specify the app entry point class. --> <entry-point class=com.example.myapp.client.MyApp/> <!-- Specify the paths for translatable code --> <source path=client/> <source path=shared/> </module>Bryan Basham – The Google Web Toolkit Slide 28
  29. 29. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy GWT Configuration ● The Java code is roughly organized into three packages: – client: on browser – server: on the server – shared: used on both sidesBryan Basham – The Google Web Toolkit Slide 29
  30. 30. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Building Views View Presenter Model Like Java RMI MVP ...but asynchronous RPC Single-Page Model Config Getting Panels Widgets started DEMO #1 Raw DEMO #2 Binding Using Building Data Grids Views UI-Binding Styles / CSS Google Web Toolkit Extending Building GWT Presenters Talking to the ServerBryan Basham – The Google Web Toolkit Slide 30
  31. 31. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy DEMO #2 ● Alloy is a Monitor & Control app on a document processing pathway: .... .. ..... .... document1 Datamart1 User .... .. ..... Prospective Warehouse .... document2 Datamart2 .... .. ..... User .... document3 ● Also: search, reports, admin toolsBryan Basham – The Google Web Toolkit Slide 31
  32. 32. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy DEMO #2: Types of Pages ● This app contains these types of pages: – Dashboards: shows high-level status & system health – Monitor: view detail status and content flow – Control: modify system properties and other actions – Search: tools to search on document contentBryan Basham – The Google Web Toolkit Slide 32
  33. 33. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy DEMO #2: DashboardsHeader Bread- crumb Pages Deck FooterBryan Basham – The Google Web Toolkit Slide 33
  34. 34. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy DEMO #2: Monitor pageBryan Basham – The Google Web Toolkit Slide 34
  35. 35. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy DEMO #2: Control pageBryan Basham – The Google Web Toolkit Slide 35
  36. 36. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy GWT Widgets ● GWT provides basic HTML-based widgets – Button, Radio button, Checkbox, Listbox, Textbox, Textarea, Hyperlink, and more ● And some advanced widgets: – DatePicker, ToggleButton, CellList, MenuBar, Tree, SuggestBox, RichTextArea, and more ● Rich table/grid components ● Click here: Widget GalleryBryan Basham – The Google Web Toolkit Slide 36
  37. 37. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Panels ● Panels are complex <div> elements with behavior ● Old-school panels to not handle browser resizing (and put the browser into quirks mode) – HorizontalPanel, VerticalPanel, StackPanel, FlowPanel, DockPanel, PopupPanel, TabPanel ● GWT v2 provides modern, resizable panels – DockLayoutPanel, DeckLayoutPanel, TabLayoutPanel, ScrollPanel, LayoutPanel – ...and DataGridBryan Basham – The Google Web Toolkit Slide 37
  38. 38. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Resize-able UI ● Fit the whole UI within the browser window ● Use resize-able layouts from outside inward ● Application.ui.xml: <ui:UiBinder xmlns:ui=urn:ui:com.google.gwt.uibinder xmlns:g=urn:import:com.google.gwt.user.client.ui xmlns:alloy=urn:import:com.tr.cmg.alloy.ui.client.screen> <g:DockLayoutPanel unit="PX"> <g:north size="119"><alloy:Header ui:field="header" /></g:north> <g:center> <g:DockLayoutPanel unit="PX"> <g:north size="29"><alloy:Breadcrumb ui:field="breadCrumb" /></g:north> <g:center><g:DeckLayoutPanel ui:field="pageDeck" /></g:center> </g:DockLayoutPanel> </g:center> <g:south size="30"><alloy:Footer ui:field="footer" /></g:south> </g:DockLayoutPanel> </ui:UiBinder>Bryan Basham – The Google Web Toolkit Slide 38
  39. 39. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Alloys Core GUI Architecture ● Application contains many Pages with one View each: Extending this class forces each page «GWT Widget» view to be resize-able. It is the developers responsibility to decide how the pages Resize layout is constructed to support resizing. Composite 1..* «Presenter» 1 «View» «GWT EntryPoint» Abstract Abstract Application pages view Page PageView ... ... «Presenter» «View» Prospective Prospective FeedLoadPage FeedLoadViewBryan Basham – The Google Web Toolkit Slide 39
  40. 40. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Raw UI-binding ● GWT provides full access to the pages DOM – One-to-one methods for Element and Node APIs – Plus additional APIs to simplify common tasks, like adding/removing CSS classes ● GWT provides programmatic APIs to compose higher-level widgets (which encode DOM Elements)Bryan Basham – The Google Web Toolkit Slide 40
  41. 41. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Raw UI-binding Techniques ● Create strings of content and/or HTML tags and use setInnerHTML method. ● Create Element objects and perform inserts ● Create Widget objects and perform adds ● Use raw binding sparingly; better to use the XML UI-binding config (as seen in other examples)Bryan Basham – The Google Web Toolkit Slide 41
  42. 42. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Raw UI-binding ExampleBryan Basham – The Google Web Toolkit Slide 42
  43. 43. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Raw UI-binding Example <g:ScrollPanel> <g:HTMLPanel> <!-- Date selection form --> <g:HTMLPanel ui:field="statsGrid"> <table border=1 cellpadding=5px> <thead> <tr> <th>Station</th> <th>Category</th> <th><!-- Date goes here --></th> <th>Last 7 days</th> <th>Last 30 days</th> <th>Last 60 days</th> <th>Last year</th> </tr> </thead> <tbody> <!-- View code fills the body --> </tbody> </table> </g:HTMLPanel> <!-- Reload button form --> </g:HTMLPanel> </g:ScrollPanel>Bryan Basham – The Google Web Toolkit Slide 43
  44. 44. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Raw UI-binding Example public class DailyLoadStatsView extends AbstractPageView { // Skipping lots of other View code private void populateStatsGrid(final LoadStatsModelDTO loadStats) { final Document DOM = Document.get(); List<String> categories = loadStats.getCategories(); // get TABLE element Element gridEl = statsGrid.getElement(); Element tableEl = gridEl.getFirstChildElement(); // put date into "day" header Element theadEl = tableEl.getFirstChildElement(); Element theadTR = theadEl.getFirstChildElement(); Element dateTH = theadTR.getFirstChildElement() .getNextSiblingElement().getNextSiblingElement(); Date reportDate = loadStats.getDailyLoadStats().getDateOfStats(); dateTH.setInnerText(DateUtils.asString(reportDate)); // More code on next slide } }Bryan Basham – The Google Web Toolkit Slide 44
  45. 45. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Raw UI-binding Example private void populateStatsGrid(final LoadStatsModelDTO loadStats) { // More code on previous slide // build new TBODY tbodyEl = DOM.createTBodyElement(); for (PathwayStation station : PathwayStation.values()) { boolean first = true; boolean odd = true; // Add a row for each category for (String category : categories) { TableRowElement rowEl = DOM.createTRElement(); tbodyEl.appendChild(rowEl); rowEl.addClassName((odd) ? "odd" : "even"); if (first) { // Insert the header on the first category for each station TableCellElement stationTH = DOM.createTHElement(); stationTH.setInnerText(station.name()); stationTH.setRowSpan(categories.size() + 1); rowEl.appendChild(stationTH); first = false; } // Skipping the rest of the code (you get the point) } }Bryan Basham – The Google Web Toolkit Slide 45
  46. 46. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy XML UI-binding ● Separation of concerns – View.ui.xml: ● Layout of View widgets ● Styles of widgets within the View – View.java: ● Inject data into the Views widgets ● Handle user events on the Views widgets – Other CSS files: ● Styles of more generic aspects of the UI ● Styles of custom widgetsBryan Basham – The Google Web Toolkit Slide 46
  47. 47. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy XML UI-binding Example <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> <ui:UiBinder xmlns:ui=urn:ui:com.google.gwt.uibinder xmlns:g=urn:import:com.google.gwt.user.client.ui xmlns:c=urn:import:com.google.gwt.user.cellview.client> Widget libraries <ui:style> .body { margin: 1em; } .button { margin-top: 0 !important; Page-specific CSS styles margin-bottom: 0 !important; margin-left: 0 !important; margin-right: 0.25em !important; } </ui:style> <g:DockLayoutPanel unit="EM" styleName="{style.body}"> <g:north size="17"> <!-- Search form --> Fixed-width dock region </g:north> <g:center> <c:DataGrid ui:field=settingsGrid /> Resize-able dock region </g:center> </g:DockLayoutPanel> </ui:UiBinder>Bryan Basham – The Google Web Toolkit Slide 47
  48. 48. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy XML UI-binding Example <!-- Search form --> <g:north size="17"> <g:DockLayoutPanel unit="EM"> <g:north size="2"> <g:FlowPanel width="100%"> <g:Label stylePrimaryName="alloyLabel">User Group:</g:Label> <g:ListBox ui:field="userGroupList" stylePrimaryName="alloyLabel" width="250" /> </g:FlowPanel> </g:north> <g:center> <g:DockLayoutPanel unit="EM"> <g:north size="2"> <g:FlowPanel width="100%"> <g:Label stylePrimaryName="alloyLabel">Content Set:</g:Label> <g:ListBox ui:field="productList" stylePrimaryName="alloyLabel" width="250" /> </g:FlowPanel> </g:north> <g:center> <g:FlowPanel width="100%"> <g:Label stylePrimaryName="alloyLabel">Collection:</g:Label> <g:ListBox ui:field="collectionList"width="250" multipleSelect="true" /> <!-- Collection selection buttons --> <g:Button ui:field="selectAllBtn">Select All</g:Button> <g:HTML height="1px"> <br /> </g:HTML> <g:Button ui:field="deselectAllBtn">Deselect All</g:Button> </g:FlowPanel> </g:center> </g:DockLayoutPanel> <!-- More View config skipped to fit the slide --> </g:north>Bryan Basham – The Google Web Toolkit Slide 48
  49. 49. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy XML UI-binding Example public class FeedLoadSettingsView extends AbstractPageView { interface MyUiBinder extends UiBinder<DockLayoutPanel, FeedLoadSettingsView>{} private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); /* Search criteria fields */ @UiField ListBox userGroupList; @UiField ListBox productList; @UiField ListBox collectionList; @UiField Button selectAllBtn; @UiField Button deselectAllBtn; /* Action Buttons */ @UiField Button searchBtn; @UiField Button saveBtn; @UiField Button resetBtn; /* Feed/Load Setting grid */ @UiField(provided = true) DataGrid<FeedLoadSettingsDTO> settingsGrid; public FeedLoadSettingsView(final FeedLoadSettingsPage page) { super(page); // pre-binding initialization (“provides” the Grid object) initialize(); // createAndBindUi initializes fields initWidget(uiBinder.createAndBindUi(this)); // post-binding initialization userGroupList.getElement().setId(makeFieldId("userGroupList")); // Skipping more code to fit the slideBryan Basham – The Google Web Toolkit Slide 49
  50. 50. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy View Styles ● Use stand-alone CSS files for generic classes of styles; usually for custom widgets ● Use UI-binding styles for Page-specific styles ● Use programmatic controls to change styles at run-time – Do this sparingly – Favor changing classes rather than hard-coding style values – Use GWTs getStyle().setXyzProperty() as a last resortBryan Basham – The Google Web Toolkit Slide 50
  51. 51. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Building Presenters View Presenter Model Like Java RMI MVP ...but asynchronous RPC Single-Page Model Config Getting Panels Widgets started DEMO #1 Raw DEMO #2 Binding Using Building Data Grids Views UI-Binding Styles / CSS Google Web Toolkit Application Error Extending Building Handling GWT Presenters Security Dashboard Talking to History the Server Pages Search View FormBryan Basham – The Google Web Toolkit Slide 51
  52. 52. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Presenters == Business Logic ● Application-level logic – Security constraints – Page management and flow ● Page-level logic – Data management & caching – Validation – Server communication ● Widget-level logicBryan Basham – The Google Web Toolkit Slide 52
  53. 53. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Application Entry-Point ● GWT starts up and invokes the onModuleLoad method on the apps entry-point class: «GWT EntryPoint» «RPC» GWT onModuleLoad Application getInitialState ApplicationRPC «DTO» «DTO» Application UserDTO StateDTO username : String environment : String roles : Set<RoleDTO> version : String user : UserDTO properties : Map<S,S>Bryan Basham – The Google Web Toolkit Slide 53
  54. 54. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Application Entry-Point public class Application implements EntryPoint { private static final ApplicationRPCAsync appRPC = ApplicationRPC.Util.getInstance(); private static ApplicationStateDTO APP_STATE; public final void onModuleLoad() { initializeGUI(); } public final void initializeGUI() { appRPC.getIntialState(new CallbackAdaptor<ApplicationStateDTO>() { public void onSuccess(final ApplicationStateDTO appState) { APP_STATE = appState; propertyMap = appState.getPropertyMap(); buildNewGUI(); navigateToStartLocation(appState.getPlaceToStartCommand()); }; }); } private void buildNewGUI() { homePage = new AlloyHomePage(null); view = new ApplicationView(homePage); // Add the application View directly to the HTML <body> RootLayoutPanel.get().add(view); DOM.getElementById("alloy-loading").getStyle().setDisplay(Display.NONE); } }Bryan Basham – The Google Web Toolkit Slide 54
  55. 55. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Error Handling ● RPC calls can throw Java exceptions ● The AsyncCallback interface provides the onFailure method hook ● The application can register an exception handler to handle these globallyBryan Basham – The Google Web Toolkit Slide 55
  56. 56. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Error Handling public final void onModuleLoad() { // Save the Singleton instance created by GWT INSTANCE = this; GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { public void onUncaughtException(final Throwable error) { if (error != null) { if (error.getCause() != null) { ErrorPopup.center(error.getCause()); } else { ErrorPopup.center(error); } } else { Log.error("Uncaught exception, but error is null"); } } }); initializeGUI(); }Bryan Basham – The Google Web Toolkit Slide 56
  57. 57. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Alloys Error PopupBryan Basham – The Google Web Toolkit Slide 57
  58. 58. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Application Security ● The Application Singleton provides security query methods: public static boolean isUserInAnyRole(final RoleDTO... roles) { for (RoleDTO role : roles) { if (getCurrentUser().hasRole(role)) { return true; } } return false; } ● Which are then used by Header to filter out specific menus or disable menu items: private MenuBar createMenuBar() { MenuBar menubar = new MenuBar(); if (Application.isUserInRole(RoleDTO.ROLE_MONITOR)) { menubar.addMenu(createProspectiveMenu()); }Bryan Basham – The Google Web Toolkit Slide 58
  59. 59. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Types of Pages ● Alloy uses four basic types of pages: – Dashboards: shows high-level status & system health – Monitor: view detail status and content flow – Control: modify system properties and other actions – Search: tools to search on document content ● AbstractPage and AbstractDashboardPage provide basic features of Alloy pagesBryan Basham – The Google Web Toolkit Slide 59
  60. 60. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy GWT History Management ● Because a GWT app is a single HTML page, user navigation is a little tricky – The browsers back button, for example, will normally take you back to the page before you entered the GWT app – GWT provides a hidden <iframe> to manage an internal view transition management – GWT v2 provides a formal Places/Activities framework, but not used in AlloyBryan Basham – The Google Web Toolkit Slide 60
  61. 61. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Alloys History Management «History Listener» GWT 1:onValueChange HistoryCmd Manager e ag eP ge ang Pa h ge T oC an k h 2:o 4:c 5:displayPage «Singleton» «Presenter» Application Page2 7:setState 3:isDirty 6:execute 8:reset currentPage «Presenter» Page2History Page1 ChangeHandlerBryan Basham – The Google Web Toolkit Slide 61
  62. 62. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Talking to the Server View Presenter Model Like Java RMI MVP ...but asynchronous RPC Single-Page Model Config Getting Panels Widgets started DEMO #1 Raw DEMO #2 Binding Using Building Data Grids Views UI-Binding Styles / CSS Google Web Toolkit Application Error Extending Building Handling GWT Presenters Security Dashboard Talking to History the Server Pages Thinking Search Asynchronously Spring Integration View Form DTOs & Callback Transformers AdaptorBryan Basham – The Google Web Toolkit Slide 62
  63. 63. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Spring Integration ● Remember the architecture: Desktop Internet Server Database User ........... ........... ........... use gen L SQ r ac e rate tion sH GWTs serialization and RPC protocol delegate to CRUD s ll s TM ca RPC over Ajax/HTTP requests RPC Service DAO rv er L se /async /impl s» a te re Boundary reads «c into client-side DTO transforms DTO Transformer Entity GWT Components Spring ComponentsBryan Basham – The Google Web Toolkit Slide 63
  64. 64. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Spring Integration ● Based upon a blog post by Chris Lee: GWT-RPC with Spring 2.x ● Uses annotations on POJOs that implement the RPC sync interface: @GwtRpcEndPoint public class ProspectiveRPCImpl implements ProspectiveRPC { ... } ● Eliminates web.xml configuration of RPC servlets but must include simple declarations in dispatcher-servlet.xml (see next slide)Bryan Basham – The Google Web Toolkit Slide 64
  65. 65. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Spring Integration <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" ...> <bean class="org.springframework.web.servlet.mvc.anno.AnnoMethodHandlerAdapter" /> <bean id="gwtAnnotationHandlerMapping" class="com.tr.cmg.alloy.ui.server.rpc.GwtAnnotationHandlerMapping" p:suffix=".rpc" p:prefix="/application/" p:order="1" /> <bean id="urlMapping" class="org.springframework.web.servlet.mvc.annno.DefaultAnnoHandlerMapping" p:order="2" /> <bean id="warehouseRPC" class="com.tr.cmg.alloy.ui.server.rpc.warehouse.WarehouseRPCImpl" /> <bean id="delDatamartRPC" class="com.tr.cmg.alloy.ui.server.rpc.datamart.delivery.DelDatamartRPCImpl" /> <!-- Many others... --> </beans>Bryan Basham – The Google Web Toolkit Slide 65
  66. 66. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Callback Adaptor ● The AsyncCallback has two methods: – onSuccess: successful response – onFailure: any HTTP error or service exception ● But usually, you only care about onSuccess ● So... create a CallbackAdaptor which implements the onFailure method – This is a good place to handle any expected exceptions, such as security exceptions – Let unexpected exceptions be handled by the Application-level global handlerBryan Basham – The Google Web Toolkit Slide 66
  67. 67. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Callback Adaptor public abstract class CallbackAdaptor<T> implements AsyncCallback<T> { @Override public void onFailure(final Throwable exception) { if (exception instanceof SessionTimeoutException) { MessageDialog.show(SESSION_TIMEOUT_MSG, GWT_RELOAD_ACTION); } else if (exception instanceof GWTSecurityException) { SecurityDialog.show((GWTSecurityException) exception, securityAction); } else if (is404(exception)) { MessageDialog.show(APPLICATION_REBOOT_MSG); } else if (exception.getMessage().contains(JDBC_CONNECTION_ERROR)) { String message = "A connection to the database could not be established"; String alert = "Database Connection Alert"; ErrorPopup.center(alert, message, exception); } else { ErrorPopup.center(exception); } } @Override public abstract void onSuccess(T result); }Bryan Basham – The Google Web Toolkit Slide 67
  68. 68. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Callback Decorators ● Do not embed too much extraneous logic in callback methods ● Rather use the Decorator pattern to wrap the primary callback with additional behavior ● Alloy provides several decorators: – ServerWaitDecorator: provides the screen mask – LoggingDecorator: provides logging of the result – Lots of other possibilities...Bryan Basham – The Google Web Toolkit Slide 68
  69. 69. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Callback Decorator Example public final class ServerWaitDecorator<T> extends CallbackDecorator<T> { public ServerWaitDecorator(final String maskText, final AsyncCallback<T> wrappedCallback) { super(Preconditions.checkNotNull(wrappedCallback)); // Start the masking process startMask(maskText); } @Override public void onFailure(final Throwable caught) { stopMask(); // Stop the masking process super.onFailure(caught); } @Override public void onSuccess(final T result) { stopMask(); // Stop the masking process super.onSuccess(result); } private void startMask(final String maskText) { ServerWaitPopup.show(maskText); } private void stopMask() { ServerWaitPopup.hide(); } }Bryan Basham – The Google Web Toolkit Slide 69
  70. 70. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Callback Decorator Example // request settings from the Server AsyncCallback<List<FeedLoadSettingsDTO>> callbackChain = new CallbackAdaptor<List<FeedLoadSettingsDTO>>() { @Override public void onSuccess(final List<FeedLoadSettingsDTO> result) { settings = result; getView(FeedLoadSettingsView.class).setSettingsData(settings); // reset book-keeping data structures resetChanges(); } }; // decorate the callback callbackChain = new ServerWaitDecorator<List<FeedLoadSettingsDTO>>( "Retrieving settings; please wait...", callbackChain); // invoke the RPC call prospectiveRPC.retrieveFeedLoadSettings(Arrays.asList(collections), callbackChain);Bryan Basham – The Google Web Toolkit Slide 70
  71. 71. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy DTOs and Transformers ● You could pass server-side Entity POJOs across the GWT RPC “wire”, but... – Muddies Entities with GWT-specific interface – Must be in the “GWT shared” package ● If you are using Hibernate and/or JPA, then Entity POJOs are decorated with objects that are not GWT-serializable ● Thus, I recommend separating Entity and DTOs and using transformers at the RPC tierBryan Basham – The Google Web Toolkit Slide 71
  72. 72. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy DTOs and Transformers ● Furthermore, there could be real differences between the Entity and DTO classes – Entity classes might have much more data than the client-side DTO needs – DTO might have methods that are unique to the needs of the View or Presenter components ● Transformers are basically implementations of the Guava Function<T,F> interface – Only need to transform individuals – Let GWTs serializer handle lists, sets, maps, etcBryan Basham – The Google Web Toolkit Slide 72
  73. 73. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Transformer Example @GwtRpcEndPoint public class ProspectiveRPCImpl implements ProspectiveRPC { @Autowired private ProspectiveService proService; private final Function<ProspectiveHealth, ProspectiveHealthDTO> healthTFM = new Function<ProspectiveHealth, ProspectiveHealthDTO>() { @Override public ProspectiveHealthDTO apply(@Nullable ProspectiveHealth input) { return new ProspectiveHealthDTO( input.getRequestProcessorHost(), input.getWorkGeneratorHost(), input.getFinalizerHost(), input.getCleanupHost(), input.getCleanupTimestamp()); } }; public ProspectiveHealthDTO getStationHealth(boolean forceRefresh) { // Delegate to Service ProspectiveHealth entity = proService.getStationHealth(forceRefresh); // Transform to client-side representation return healthTFM.apply(entity); } }Bryan Basham – The Google Web Toolkit Slide 73
  74. 74. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Thinking Asynchronously ● Any event-driven environment, such as a user interface, requires the developer to think asynchronously. ● A web UI is doubly so because of the use of Ajax and therefore callbacks to handle the server response. ● Whats wrong with this? public void preparePage(final HistoryCommand pendingHistoryCmd) { retrievePathwayConfigFromServer(); retrieveUserGroupsFromServer(); sendSearchRequestToServer(); }Bryan Basham – The Google Web Toolkit Slide 74
  75. 75. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Thinking Asynchronously public void preparePage(final HistoryCommand pendingHistoryCmd) { AsyncCallback<PathwayConfigurationDTO> firstCallback = new CallbackAdaptor<PathwayConfigurationDTO>() { @Override public void onSuccess(PathwayConfigurationDTO result) { // store pathway config pathwayConfig = result; // next get the user groups AsyncCallback<List<UserGroupDTO>> secondCallback = new CallbackAdaptor<List<UserGroupDTO>>() { @Override public void onSuccess(List<UserGroupDTO> result) { // store user groups userGroups = result; // finally send the search request AsyncCallback<List<String>> thirdCallback = new CallbackAdaptor<List<String>>() { @Override public void onSuccess(List<String> result) { // send search to the View getView().displaySearch(result); } }; myRPC.sendSearchRequest(thirdCallback); } }; myRPC.retrievePathwayConfig(secondCallback); } }; myRPC.retrievePathwayConfig(firstCallback); }Bryan Basham – The Google Web Toolkit Slide 75
  76. 76. RJUG : 12-Mar-2012 © Copyright 2013, Software Alchemy Extending GWT View Presenter Model Like Java RMI MVP ...but asynchronous RPC Single-Page Model Config Getting Panels Widgets started DEMO #1 Raw DEMO #2 Binding Using Building Data Grids Views UI-Binding Styles / CSS Google Web Toolkit Dialog Application Gadgets Error Extending Building Handling Complex Widget GWT Presenters Security Simple Dashboard Widget Talking to History Widgets & the Server Pages Gadgets Thinking Search Asynchronously Spring Integration View Form DTOs & Callback Transformers AdaptorBryan Basham – The Google Web Toolkit Slide 76
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×