SlideShare une entreprise Scribd logo
1  sur  59
Télécharger pour lire hors ligne
What’s New in GWT 2.2
           David Chandler
           Google Web Toolkit Team
           Atlanta, GA USA
           drfibonacci@google.com




Monday, March 21, 2011               1
Agenda
                   Demos

                   New tools (GWT Designer)

                   New features




Monday, March 21, 2011                        2
GWT in 10 sec


                         Asynchronous
                         JavaScript
                         And
                         XML++



Monday, March 21, 2011                  3
Browser-Proof Your JS Code


                                 IE



                               Firefo
                                     x


                                   i
                              Safar e
                                   m
                              Chro


                                Opera




                          4
Monday, March 21, 2011                   4
No plugins required
                                           Silverlight
                         VML   Flash




                                       5
Monday, March 21, 2011                                   5
Eating our own dogfood




                         += AdSense, Maps, Docs, Groups, Blogger...
                                             6
Monday, March 21, 2011                                                6
New tools




Monday, March 21, 2011               7
Google Plugin for Eclipse




Monday, March 21, 2011                  8
GWT Quickstart
              > svn checkout https://google-web-toolkit.googlecode.com/
              svn/trunk/samples/expenses expenses
              > cd expenses/src/main/webapp
              > mvn -f ../../../pom.xml gwt:run (dev mode)
              (note: most projects can use mvn gwt:run in the dir containing pom.xml--this
              one is special because it loads test data from a .txt file in src/main/webapp)

              1.Browse to http://127.0.0.1:8888/LoadExpensesDB.html?
              gwt.codesvr=127.0.0.1:9997
              2.Click Generate Data button
              3.Browse to Expenses.html to run the app

              To create an Eclipse project:
              1.Install Sonatype m2eclipse and m2extras
              2.File | Import | Existing maven project, select expenses/
              pom.xml

Monday, March 21, 2011                                                                         9
GWT Designer Java, ui.xml




Monday, March 21, 2011                  10
GWT Designer & UiBinder




Monday, March 21, 2011                11
GWT Designer CSS Editor




Monday, March 21, 2011                12
Optimize with Speed Tracer




Monday, March 21, 2011                   13
Launch SpeedTracer
             From Chrome...




             Or from Eclipse...


Monday, March 21, 2011            14
Server traces GAE, tcServer




Monday, March 21, 2011                    15
One click deploy to GAE




Monday, March 21, 2011                16
New features




Monday, March 21, 2011                  17
What’s new in 2.2?
                   SafeHTML wrappers

                   Application framework

                         -   RequestFactory

                         -   Activities and Places

                   Cell Widgets and Editor framework

                   GWT Canvas

                   Built-in logging


Monday, March 21, 2011                                 18
Four flavors of RPC
            1. RequestBuilder + JSONParser (see RESTY-GWT)

            2. RequestBuilder + XMLParser

            3. GWT-RPC (easiest)

            4. RequestFactory (new in 2.1)




Monday, March 21, 2011                                       19
GWT-RPC
              @RemoteServiceRelativePath("greet")
              public interface GreetingService extends RemoteService {
              	 String greetServer(String name) throws IllegalArgumentException;
              }



              public interface GreetingServiceAsync {
              	 void greetServer(String input, AsyncCallback<String> callback)
              	 	 	 throws IllegalArgumentException;
              }



              public class GreetingServiceImpl extends RemoteServiceServlet implements
              	 	 GreetingService
              {
              	 public String greetServer(String input) throws IllegalArgumentException {
              	 ...
                 }
              }




Monday, March 21, 2011                                                                      20
Simple, powerful GWT-RPC
                   Send / receive Plain Old Java Objects (POJO)

                         -   Easy: interface, async, & implementation

                         -   Versioned to help keep client & server in sync

                         -   Even smaller than JSON

                         -   Supports polymorphism

                         -   No JavaScript hijacking risk (JSON attack)

                         -   Easy to find all calls to given service in IDE




Monday, March 21, 2011                                                        21
GWT 2.1 RequestFactory
                   Newer alternative to GWT-RPC

                   Designed for data-oriented services

                         -   Higher level of abstraction than GWT-RPC

                         -   Foundation for future caching / batching

                   Even faster than GWT-RPC

                         -   JSON-based == very fast (no serialization /
                             deserialization required)

                         -   Tracks changes on the client and sends only diffs


Monday, March 21, 2011                                                           22
RequestFactory
                   The entity / DTO problem

                   EntityProxy / ValueProxy

                   Service stub interfaces extend RequestContext

                   AppRequestFactory extends RequestFactory

                   GWT.create(MyAppRequestFactory.class)




Monday, March 21, 2011                                             23
EntityProxy
              @Entity
              public class ItemList extends DatastoreObject
              {
              	 private String name;
              	 private Key<AppUser> owner;
              	 private ListType listType;
              	 @Embedded
              	 private List<ListItem> items; // value type
                 ...
              }

              @ProxyFor(ItemList.class)
              public interface ItemListProxy extends DatastoreObjectProxy
              {
              	 // TODO enums work!
              	 public enum ListType {NOTES, TODO}
              	 String getName();
              	 void setName(String name);
              	 List<ListItemProxy> getItems();
                 AppUserProxy getOwner(); // NOT Key
                 ...
              }




Monday, March 21, 2011                                                      24
DatastoreObject
              package com.listwidget.domain;
              public class DatastoreObject
              {
              	 @Id
              	 private Long id;
              	 private Integer version = 0;
              	
              	 @PrePersist
              	 void onPersist()
              	 {
              	 	 this.version++;
              	 }
                 ...
              }


              package com.listwidget.shared.proxy;
              public interface DatastoreObjectProxy extends EntityProxy
              {
              	 Long getId();
              	 Integer getVersion();
              }




Monday, March 21, 2011                                                    25
ValueProxy
              public class ListItem // POJO
              {
              	 private String itemText;
              	 private Date dateCreated;
              	
              	 public Date getDateCreated()
              	 {
              	 	 return dateCreated;
              	 }
              }



              @ProxyFor(value = ListItem.class)
              public interface ListItemProxy extends ValueProxy
              {
              	 String getItemText();
              	 void setItemText(String itemText);
              	 Date getDateCreated();
              }




Monday, March 21, 2011                                            26
Making a RequestFactory
             public interface ListwidgetRequestFactory extends RequestFactory
             {
             	 @Service(value = ItemListDao.class, locator = DaoServiceLocator.class)
             	 interface ItemListRequestContext extends RequestContext
             	 {
             	 	 Request<List<ItemListProxy>> listAll();
             	 	 Request<Void> save(ItemListProxy list);
             	 	 Request<ItemListProxy> saveAndReturn(ItemListProxy newList);
             	 }
             	 ItemListRequestContext itemListRequest();
             }



             private final ListwidgetRequestFactory rf =
                GWT.create(ListwidgetRequestFactory.class);




Monday, March 21, 2011                                                                  27
Using RequestFactory
              	    @Override
              	    public void persistList(String listName)
              	    {
              	    	 final ListwidgetRequestFactory rf = this.clientFactory
              	    	 	 	 .getRequestFactory();
              	    	 ItemListRequestContext reqCtx = rf.itemListRequest();
              	    	 final ItemListProxy newList = reqCtx.create(ItemListProxy.class);
              	    	 newList.setName(listName);
              	    	 newList.setListType(ListType.TODO);
              	    	 reqCtx.saveAndReturn(newList).fire(new Receiver<ItemListProxy>()
              	    	 {
              	    	 	 @Override
              	    	 	 public void onSuccess(final ItemListProxy savedList)
              	    	 	 {
              	    	 	 	 // Refresh table
              	    	 	 	 listDataProvider.getData();
              	    	 	 }
              	    	 });
              	    }




Monday, March 21, 2011                                                                   28
Using RequestFactory
              	    @Override
              	    public void update(int index, ItemListProxy obj, final String newName)
              	    {
              	    	 ItemListRequestContext reqCtx = clientFactory.getRequestFactory()
              	    	 	 	 .itemListRequest();
              	    	 ItemListProxy editable = reqCtx.edit(obj);
              	    	 editable.setName(newName);
              	    	 reqCtx.save(editable).fire(new Receiver<Void>()
              	    	 {
              	    	 	 @Override
              	    	 	 public void onSuccess(Void response)
              	    	 	 {
              	    	 	 	 eventBus.fireEvent(new MessageEvent(newName + " updated",
              	    	 	 	 	 	 MessageType.INFO));
              	    	 	 }
              	    	 });
              	    }




Monday, March 21, 2011                                                                      29
Using RequestFactory
              	     private void getData()
              	     {
                       // To retrieve relations and value types, use .with()
              	     	 Request<List<ItemListProxy>> findAllReq = rf.itemListRequest()
              	     	 	 	 .listAll().with("owner");
                       // Receiver specifies return type
              	     	 findAllReq.fire(new Receiver<List<ItemListProxy>>()
              	     	 {
              	
              	
                    	 	 @Override
                                                   Text
                    	 	 public void onSuccess(List<ItemListProxy> response)
              	     	 	 {
              	     	 	 	 updateRowData(0, response);
              	     	 	 }
              	     	 });
              	     }




Monday, March 21, 2011                                                                 30
Using RequestFactory
             	     editList = reqCtx.edit(editList);
             	     List<ListItemProxy> items = editList.getItems();
             	     // must initialize collections
             	     if (items == null)
             	     {
             	     	 editList.setItems(new ArrayList<ListItemProxy>());
             	     }
             	     editList.getItems().add(newItem);
             	     reqCtx.save(editList).with("items").to(new Receiver<Void>()
             	     {
             	     	 @Override
             	     	 public void onSuccess(Void response)
             	     	 {
             	     	 	 itemsProvider.setList(editList.getItems());
             	     	 	 itemsProvider.refresh();
             	     	 }
             	     }).fire();




Monday, March 21, 2011                                                           31
GWT MVP - Concepts
                   View

                         -   Interface + implementation

                         -   Interface enables testing without GWTTestCase

                         -   Typically expensive to construct so make reusable

                   Presenter

                         -   No Widgets, just business logic

                         -   Middle man between service layer and views



Monday, March 21, 2011                                                           32
GWT MVP - Concepts
                   Place

                         -   Place represents bookmarkable state of an activity

                         -   PlaceController makes back button / bookmarks
                             work like users expect

                         -   PlaceTokenizers map to / from String tokens on URL




Monday, March 21, 2011                                                            33
Demo
                   third_party/java_src/gwt/svn/trunk/samples/
                   expenses




Monday, March 21, 2011                                           34
Place
              public class EditListPlace extends Place
              {
              	 private String token;
              	 public EditListPlace(String token)
              	 {
              	 	 this.token = token;
              	 }
              	 public String getToken()
              	 {
              	 	 return token;
              	 }
              	 public static class Tokenizer implements PlaceTokenizer<EditListPlace>
              	 {
              	 	 public EditListPlace getPlace(String token)
              	 	 {
              	 	 	 return new EditListPlace(token);
              	 	 }
              	 	 public String getToken(EditListPlace place)
              	 	 {
              	 	 	 return place.getToken();
              	 	 }
              	 }
              }



Monday, March 21, 2011                                                                   35
PlaceHistoryMapper
              /**
                * PlaceHistoryMapper interface is used to attach all places which the
                * PlaceHistoryHandler should be aware of. This is done via the @WithTokenizers
                * annotation or by extending PlaceHistoryMapperWithFactory and creating a
                * separate TokenizerFactory.
                */
              @WithTokenizers({ ListsPlace.Tokenizer.class, EditListPlace.Tokenizer.class })
              public interface AppPlaceHistoryMapper extends PlaceHistoryMapper
              {
              }




Monday, March 21, 2011                                                                           36
Hello Places
                // Start PlaceHistoryHandler with our PlaceHistoryMapper
             PlaceHistoryMapper historyMapper = clientFactory.getHistoryMapper();
             PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(hisoryMapper);
             historyHandler.register(placeController, eventBus, defaultPlace);
             // Goes to place represented on URL or default place
             historyHandler.handleCurrentHistory();




Monday, March 21, 2011                                                                     37
Places: Moving parts




Monday, March 21, 2011             38
Places: Go to




Monday, March 21, 2011      39
Places: Back and forth




Monday, March 21, 2011               40
Activities
                   Activity, ActivityManager are not required!

                   ActivityManager

                         -   Owns a region of the window

                         -   Choose what to do with it on place change

                   Activity (“wake up, set up, show up”)

                         -   Started by ActivityManager

                         -   Provides a widget to display, asynchronously

                         -   Can refuse to relinquish screen

Monday, March 21, 2011                                                      41
Activity
              public class EditListActivity extends AbstractActivity implements Presenter
              {
              	 private ClientFactory clientFactory;
              	 private EventBus eventBus;

              	     public EditListActivity(ClientFactory cf, EditListPlace editListPlace)
              	     {
              	     	 this.clientFactory = cf;
              	     	 this.itemListToken = editListPlace.getToken();
              	     }

              	     @Override
              	     public void start(final AcceptsOneWidget panel, EventBus eventBus)
              	     {
              	     	 this.eventBus = eventBus;
                        ...
                        panel.setWidget(clientFactory.getEditListView());
                    }
                    ...
              }




Monday, March 21, 2011                                                                       42
ActivityMapper
             public class AppActivityMapper implements ActivityMapper {

             	     private ClientFactory clientFactory;

             	     public AppActivityMapper(ClientFactory clientFactory) {
             	     	 super();
             	     	 this.clientFactory = clientFactory;
             	     }

             	     @Override
             	     public Activity getActivity(Place place) {
             	     	 if (place instanceof EditListPlace) {
             	     	 	 return new EditListActivity(clientFactory, (EditListPlace) place);
             	     	 }
             	     	 if (place instanceof ListsPlace)
             	     	 {
             	     	 	 return new ListsActivity(clientFactory);
             	     	 }
             	     	 return null;
             	     }
             }




Monday, March 21, 2011                                                                      43
ActivityMapper Idioms
                   Disposable Activities, shared views:

                         if (place instanceof FooPlace) {
                           return new FooActivity(theOnlyFooView);
                         }

                   Singleton:

                         if (place instanceof FooPlace) {
                           theOnlyFooActivity.update((FooPlace) place);
                           return theOnlyFooActivity;
                         }



Monday, March 21, 2011                                                    44
Get activated




Monday, March 21, 2011      45
Strategies




Monday, March 21, 2011   46
Strategies




Monday, March 21, 2011   47
Activities and Places wiring
             // Start ActivityManager for the nav (west) panel with our WestActivityMapper
             ActivityMapper westActivityMapper = new WestActivityMapper(clientFactory);
             ActivityManager westActivityManager =
                new ActivityManager(westActivityMapper, eventBus);
             westActivityManager.setDisplay(westPanel);

             // Start ActivityManager for the main (center) panel with our CenterActivityMapper
             ActivityMapper centerActivityMapper = new CenterActivityMapper(clientFactory);
             ActivityManager centerActivityManager =
                new ActivityManager(centerActivityMapper, eventBus);
             centerActivityManager.setDisplay(centerPanel);

             // Start PlaceHistoryHandler with our PlaceHistoryMapper
             PlaceHistoryMapper historyMapper = GWT.create(AppPlaceHistoryMapper.class);
             PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
             historyHandler.register(placeController, eventBus, defaultPlace);

             RootPanel.get().add(dockLayoutPanel);
             // Goes to place represented on URL or default place
             historyHandler.handleCurrentHistory();




Monday, March 21, 2011                                                                            48
Cell Widgets
                   Fast, lightweight table rendering

                   Data binding with
                   DataProviders, ValueUpdaters

                   Scrolling and paging controls

                   Sortable columns, adjustable width

                   TextBox, IntegerBox, ValueBox<T>




Monday, March 21, 2011                                  49
Cell Widgets




Monday, March 21, 2011     50
Editable Column
              // Editable column for list name
              nameColumn = new Column<ItemListProxy,String>(new EditTextCell())
              {
              	 @Override
              	 public String getValue(ItemListProxy list)
              	 {
              	 	 return list.getName();
              	 }
              };




Monday, March 21, 2011                                                            51
Custom Column type
             // Note Flyweight pattern: only one instance of HyperlinkCell passed to the Column
             Column<ItemListProxy, Hyperlink> linkColumn =
                new Column<ItemListProxy, Hyperlink>(new HyperlinkCell())
             {
             	 @Override
             	 public Hyperlink getValue(ItemListProxy list)
             	 {
             	 	 String proxyToken =
                       clientFactory.getRequestFactory().getHistoryToken(list.stableId());
             	 	 String historyToken =
                       clientFactory.getHistoryMapper().getToken(new EditListPlace(proxyToken));
                    Hyperlink h = new Hyperlink(list.getName(),historyToken);
             	 	 return h;
             	 }
             };




Monday, March 21, 2011                                                                             52
Populating a CellTable
             public static class MyDataProvider extends
             	 	 AsyncDataProvider<ItemListProxy>
             {
             	 @Override
             	 protected void onRangeChanged(HasData<ItemListProxy> display)
             	 {
             	 	 // To retrieve relations and value types, use .with()
             	 	 Request<List<ItemListProxy>> findAllReq = rf.itemListRequest()
             	 	 	 	 .listAll().with("owner");
             	 	 // Receiver specifies return type
             	 	 findAllReq.fire(new Receiver<List<ItemListProxy>>()
             	 	 {
             	 	 	 @Override
             	 	 	 public void onSuccess(List<ItemListProxy> response)
             	 	 	 {
             	 	 	 	 updateRowData(0, response);
             	 	 	 }
             	 	 });
             	 }
             }

             this.myDataProvider = new MyDataProvider(requestFactory);




Monday, March 21, 2011                                                            53
Updating with a CellTable
            public class NameFieldUpdater implements FieldUpdater<ItemListProxy, String>
            {
            	 @Override
            	 public void update(int index, ItemListProxy obj, final String newName)
            	 {
            	 	 ItemListRequestContext reqCtx = clientFactory.getRequestFactory()
            	 	 	 	 .itemListRequest();
            	 	 ItemListProxy editable = reqCtx.edit(obj);
            	 	 editable.setName(newName);
            	 	 reqCtx.save(editable).fire(new Receiver<Void>()
            	 	 {
            	 	 	 @Override
            	 	 	 public void onSuccess(Void response)
            	 	 	 {
            	 	 	 	 eventBus.fireEvent(new MessageEvent(newName + " updated",
            	 	 	 	 	 	 MessageType.INFO));
            	 	 	 }
            	 	 });
            	 }
            };

             // Make list name field editable
             display.getNameColumn().setFieldUpdater(new NameFieldUpdater());



Monday, March 21, 2011                                                                     54
GWT Canvas
                   http://gwtcanvasdemo.appspot.com




Monday, March 21, 2011                                55
GWT Logging
                   GWT now has java.util.Logging emulation




                   Configure in your .gwt.xml



                   Easily enable remote logging, too




Monday, March 21, 2011                                       56
GWT speak
                   “Very productive environment for Java
                   developers, but there is a learning curve”

                   “UI layout and styling is a challenge”

                   “GWT has enabled our team to run much faster
                   than we could otherwise”

                   “Would be impossible to write our app without
                   GWT”




Monday, March 21, 2011                                             57
New GWT book
             http://code.google.com/webtoolkit/books.html




Monday, March 21, 2011                                      58
Thank you!
                         Where to get it:
                          http://code.google.com/webtoolkit/

                         Wiki, issue tracker, source:
                          http://code.google.com/p/google-web-toolkit/

                         Official GWT blog:
                          http://google-web-toolkit.blogspot.com/

                         Twitter:
                          @googledevtools



                                              59
Monday, March 21, 2011                                                   59

Contenu connexe

Similaire à What's New in GWT 2.2

Easing offline web application development with GWT
Easing offline web application development with GWTEasing offline web application development with GWT
Easing offline web application development with GWTArnaud Tournier
 
Softshake 2013: Introduction to NoSQL with Couchbase
Softshake 2013: Introduction to NoSQL with CouchbaseSoftshake 2013: Introduction to NoSQL with Couchbase
Softshake 2013: Introduction to NoSQL with CouchbaseTugdual Grall
 
Javascript Frameworks Comparison - Angular, Knockout, Ember and Backbone
Javascript Frameworks Comparison - Angular, Knockout, Ember and BackboneJavascript Frameworks Comparison - Angular, Knockout, Ember and Backbone
Javascript Frameworks Comparison - Angular, Knockout, Ember and BackboneDeepu S Nath
 
XNAT Open Source Development
XNAT Open Source DevelopmentXNAT Open Source Development
XNAT Open Source DevelopmentJohn Paulett
 
An introduction to OSGi
An introduction to OSGi An introduction to OSGi
An introduction to OSGi Andrea Chiodoni
 
Javascript Frameworks Comparison
Javascript Frameworks ComparisonJavascript Frameworks Comparison
Javascript Frameworks ComparisonDeepu S Nath
 
Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11
Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11
Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11Magecom UK Limited
 
Gerrit linuxtag2011
Gerrit linuxtag2011Gerrit linuxtag2011
Gerrit linuxtag2011thkoch
 
HTML XHTML HTML5
HTML XHTML HTML5HTML XHTML HTML5
HTML XHTML HTML5timstone
 
Integrando Plone con cualquier cosa
Integrando Plone con cualquier cosaIntegrando Plone con cualquier cosa
Integrando Plone con cualquier cosamenttes
 
Android 1.5 to 3.0: a compatibility journey
Android 1.5 to 3.0: a compatibility journeyAndroid 1.5 to 3.0: a compatibility journey
Android 1.5 to 3.0: a compatibility journeyEmanuele Di Saverio
 
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJSMeteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJSJulio Antonio Mendonça de Marins
 
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009Alexandre Morgaut
 
Monitoring MySQL with Prometheus, Grafana and Percona Dashboards
Monitoring MySQL with Prometheus, Grafana and Percona DashboardsMonitoring MySQL with Prometheus, Grafana and Percona Dashboards
Monitoring MySQL with Prometheus, Grafana and Percona DashboardsJulien Pivotto
 

Similaire à What's New in GWT 2.2 (20)

Easing offline web application development with GWT
Easing offline web application development with GWTEasing offline web application development with GWT
Easing offline web application development with GWT
 
Softshake 2013: Introduction to NoSQL with Couchbase
Softshake 2013: Introduction to NoSQL with CouchbaseSoftshake 2013: Introduction to NoSQL with Couchbase
Softshake 2013: Introduction to NoSQL with Couchbase
 
RunDeck
RunDeckRunDeck
RunDeck
 
Javascript Frameworks Comparison - Angular, Knockout, Ember and Backbone
Javascript Frameworks Comparison - Angular, Knockout, Ember and BackboneJavascript Frameworks Comparison - Angular, Knockout, Ember and Backbone
Javascript Frameworks Comparison - Angular, Knockout, Ember and Backbone
 
XNAT Open Source Development
XNAT Open Source DevelopmentXNAT Open Source Development
XNAT Open Source Development
 
An introduction to OSGi
An introduction to OSGi An introduction to OSGi
An introduction to OSGi
 
Javascript Frameworks Comparison
Javascript Frameworks ComparisonJavascript Frameworks Comparison
Javascript Frameworks Comparison
 
sidje
sidjesidje
sidje
 
Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11
Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11
Magento NodeJS Microservices — Yegor Shytikov | Magento Meetup Online #11
 
VocBench 2.0: A Web Application for Collaborative Development of Multilingual...
VocBench 2.0: A Web Application for Collaborative Development of Multilingual...VocBench 2.0: A Web Application for Collaborative Development of Multilingual...
VocBench 2.0: A Web Application for Collaborative Development of Multilingual...
 
Gerrit linuxtag2011
Gerrit linuxtag2011Gerrit linuxtag2011
Gerrit linuxtag2011
 
HTML XHTML HTML5
HTML XHTML HTML5HTML XHTML HTML5
HTML XHTML HTML5
 
Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316
 
Integrando Plone con cualquier cosa
Integrando Plone con cualquier cosaIntegrando Plone con cualquier cosa
Integrando Plone con cualquier cosa
 
Android 1.5 to 3.0: a compatibility journey
Android 1.5 to 3.0: a compatibility journeyAndroid 1.5 to 3.0: a compatibility journey
Android 1.5 to 3.0: a compatibility journey
 
Reactjs
ReactjsReactjs
Reactjs
 
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJSMeteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
 
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
 
Monitoring MySQL with Prometheus, Grafana and Percona Dashboards
Monitoring MySQL with Prometheus, Grafana and Percona DashboardsMonitoring MySQL with Prometheus, Grafana and Percona Dashboards
Monitoring MySQL with Prometheus, Grafana and Percona Dashboards
 
Delivering with ember.js
Delivering with ember.jsDelivering with ember.js
Delivering with ember.js
 

Plus de David Chandler

Taking Your GWT App to Tablets with GXT 4.0
Taking Your GWT App to Tablets with GXT 4.0Taking Your GWT App to Tablets with GXT 4.0
Taking Your GWT App to Tablets with GXT 4.0David Chandler
 
StORM: a lightweight ORM for Android SQLite
StORM: a lightweight ORM for Android SQLiteStORM: a lightweight ORM for Android SQLite
StORM: a lightweight ORM for Android SQLiteDavid Chandler
 
Easy REST APIs with Jersey and RestyGWT
Easy REST APIs with Jersey and RestyGWTEasy REST APIs with Jersey and RestyGWT
Easy REST APIs with Jersey and RestyGWTDavid Chandler
 
Cómo trabajan los Googlers
Cómo trabajan los GooglersCómo trabajan los Googlers
Cómo trabajan los GooglersDavid Chandler
 
Google App Engine Update 2012
Google App Engine Update 2012Google App Engine Update 2012
Google App Engine Update 2012David Chandler
 
Scalable Apps with Google App Engine
Scalable Apps with Google App EngineScalable Apps with Google App Engine
Scalable Apps with Google App EngineDavid Chandler
 
The 90-Day Startup with Google AppEngine for Java
The 90-Day Startup with Google AppEngine for JavaThe 90-Day Startup with Google AppEngine for Java
The 90-Day Startup with Google AppEngine for JavaDavid Chandler
 
Securing JSF Applications Against the OWASP Top Ten
Securing JSF Applications Against the OWASP Top TenSecuring JSF Applications Against the OWASP Top Ten
Securing JSF Applications Against the OWASP Top TenDavid Chandler
 

Plus de David Chandler (12)

Taking Your GWT App to Tablets with GXT 4.0
Taking Your GWT App to Tablets with GXT 4.0Taking Your GWT App to Tablets with GXT 4.0
Taking Your GWT App to Tablets with GXT 4.0
 
StORM: a lightweight ORM for Android SQLite
StORM: a lightweight ORM for Android SQLiteStORM: a lightweight ORM for Android SQLite
StORM: a lightweight ORM for Android SQLite
 
Easy REST APIs with Jersey and RestyGWT
Easy REST APIs with Jersey and RestyGWTEasy REST APIs with Jersey and RestyGWT
Easy REST APIs with Jersey and RestyGWT
 
Cómo trabajan los Googlers
Cómo trabajan los GooglersCómo trabajan los Googlers
Cómo trabajan los Googlers
 
Life of an engineer
Life of an engineerLife of an engineer
Life of an engineer
 
StORM preview
StORM previewStORM preview
StORM preview
 
Google App Engine Update 2012
Google App Engine Update 2012Google App Engine Update 2012
Google App Engine Update 2012
 
GWT Plus HTML 5
GWT Plus HTML 5GWT Plus HTML 5
GWT Plus HTML 5
 
Scalable Apps with Google App Engine
Scalable Apps with Google App EngineScalable Apps with Google App Engine
Scalable Apps with Google App Engine
 
The 90-Day Startup with Google AppEngine for Java
The 90-Day Startup with Google AppEngine for JavaThe 90-Day Startup with Google AppEngine for Java
The 90-Day Startup with Google AppEngine for Java
 
GWT MVP Case Study
GWT MVP Case StudyGWT MVP Case Study
GWT MVP Case Study
 
Securing JSF Applications Against the OWASP Top Ten
Securing JSF Applications Against the OWASP Top TenSecuring JSF Applications Against the OWASP Top Ten
Securing JSF Applications Against the OWASP Top Ten
 

Dernier

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Bhuvaneswari Subramani
 

Dernier (20)

Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 

What's New in GWT 2.2

  • 1. What’s New in GWT 2.2 David Chandler Google Web Toolkit Team Atlanta, GA USA drfibonacci@google.com Monday, March 21, 2011 1
  • 2. Agenda Demos New tools (GWT Designer) New features Monday, March 21, 2011 2
  • 3. GWT in 10 sec Asynchronous JavaScript And XML++ Monday, March 21, 2011 3
  • 4. Browser-Proof Your JS Code IE Firefo x i Safar e m Chro Opera 4 Monday, March 21, 2011 4
  • 5. No plugins required Silverlight VML Flash 5 Monday, March 21, 2011 5
  • 6. Eating our own dogfood += AdSense, Maps, Docs, Groups, Blogger... 6 Monday, March 21, 2011 6
  • 8. Google Plugin for Eclipse Monday, March 21, 2011 8
  • 9. GWT Quickstart > svn checkout https://google-web-toolkit.googlecode.com/ svn/trunk/samples/expenses expenses > cd expenses/src/main/webapp > mvn -f ../../../pom.xml gwt:run (dev mode) (note: most projects can use mvn gwt:run in the dir containing pom.xml--this one is special because it loads test data from a .txt file in src/main/webapp) 1.Browse to http://127.0.0.1:8888/LoadExpensesDB.html? gwt.codesvr=127.0.0.1:9997 2.Click Generate Data button 3.Browse to Expenses.html to run the app To create an Eclipse project: 1.Install Sonatype m2eclipse and m2extras 2.File | Import | Existing maven project, select expenses/ pom.xml Monday, March 21, 2011 9
  • 10. GWT Designer Java, ui.xml Monday, March 21, 2011 10
  • 11. GWT Designer & UiBinder Monday, March 21, 2011 11
  • 12. GWT Designer CSS Editor Monday, March 21, 2011 12
  • 13. Optimize with Speed Tracer Monday, March 21, 2011 13
  • 14. Launch SpeedTracer From Chrome... Or from Eclipse... Monday, March 21, 2011 14
  • 15. Server traces GAE, tcServer Monday, March 21, 2011 15
  • 16. One click deploy to GAE Monday, March 21, 2011 16
  • 18. What’s new in 2.2? SafeHTML wrappers Application framework - RequestFactory - Activities and Places Cell Widgets and Editor framework GWT Canvas Built-in logging Monday, March 21, 2011 18
  • 19. Four flavors of RPC 1. RequestBuilder + JSONParser (see RESTY-GWT) 2. RequestBuilder + XMLParser 3. GWT-RPC (easiest) 4. RequestFactory (new in 2.1) Monday, March 21, 2011 19
  • 20. GWT-RPC @RemoteServiceRelativePath("greet") public interface GreetingService extends RemoteService { String greetServer(String name) throws IllegalArgumentException; } public interface GreetingServiceAsync { void greetServer(String input, AsyncCallback<String> callback) throws IllegalArgumentException; } public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { public String greetServer(String input) throws IllegalArgumentException { ... } } Monday, March 21, 2011 20
  • 21. Simple, powerful GWT-RPC Send / receive Plain Old Java Objects (POJO) - Easy: interface, async, & implementation - Versioned to help keep client & server in sync - Even smaller than JSON - Supports polymorphism - No JavaScript hijacking risk (JSON attack) - Easy to find all calls to given service in IDE Monday, March 21, 2011 21
  • 22. GWT 2.1 RequestFactory Newer alternative to GWT-RPC Designed for data-oriented services - Higher level of abstraction than GWT-RPC - Foundation for future caching / batching Even faster than GWT-RPC - JSON-based == very fast (no serialization / deserialization required) - Tracks changes on the client and sends only diffs Monday, March 21, 2011 22
  • 23. RequestFactory The entity / DTO problem EntityProxy / ValueProxy Service stub interfaces extend RequestContext AppRequestFactory extends RequestFactory GWT.create(MyAppRequestFactory.class) Monday, March 21, 2011 23
  • 24. EntityProxy @Entity public class ItemList extends DatastoreObject { private String name; private Key<AppUser> owner; private ListType listType; @Embedded private List<ListItem> items; // value type ... } @ProxyFor(ItemList.class) public interface ItemListProxy extends DatastoreObjectProxy { // TODO enums work! public enum ListType {NOTES, TODO} String getName(); void setName(String name); List<ListItemProxy> getItems(); AppUserProxy getOwner(); // NOT Key ... } Monday, March 21, 2011 24
  • 25. DatastoreObject package com.listwidget.domain; public class DatastoreObject { @Id private Long id; private Integer version = 0; @PrePersist void onPersist() { this.version++; } ... } package com.listwidget.shared.proxy; public interface DatastoreObjectProxy extends EntityProxy { Long getId(); Integer getVersion(); } Monday, March 21, 2011 25
  • 26. ValueProxy public class ListItem // POJO { private String itemText; private Date dateCreated; public Date getDateCreated() { return dateCreated; } } @ProxyFor(value = ListItem.class) public interface ListItemProxy extends ValueProxy { String getItemText(); void setItemText(String itemText); Date getDateCreated(); } Monday, March 21, 2011 26
  • 27. Making a RequestFactory public interface ListwidgetRequestFactory extends RequestFactory { @Service(value = ItemListDao.class, locator = DaoServiceLocator.class) interface ItemListRequestContext extends RequestContext { Request<List<ItemListProxy>> listAll(); Request<Void> save(ItemListProxy list); Request<ItemListProxy> saveAndReturn(ItemListProxy newList); } ItemListRequestContext itemListRequest(); } private final ListwidgetRequestFactory rf = GWT.create(ListwidgetRequestFactory.class); Monday, March 21, 2011 27
  • 28. Using RequestFactory @Override public void persistList(String listName) { final ListwidgetRequestFactory rf = this.clientFactory .getRequestFactory(); ItemListRequestContext reqCtx = rf.itemListRequest(); final ItemListProxy newList = reqCtx.create(ItemListProxy.class); newList.setName(listName); newList.setListType(ListType.TODO); reqCtx.saveAndReturn(newList).fire(new Receiver<ItemListProxy>() { @Override public void onSuccess(final ItemListProxy savedList) { // Refresh table listDataProvider.getData(); } }); } Monday, March 21, 2011 28
  • 29. Using RequestFactory @Override public void update(int index, ItemListProxy obj, final String newName) { ItemListRequestContext reqCtx = clientFactory.getRequestFactory() .itemListRequest(); ItemListProxy editable = reqCtx.edit(obj); editable.setName(newName); reqCtx.save(editable).fire(new Receiver<Void>() { @Override public void onSuccess(Void response) { eventBus.fireEvent(new MessageEvent(newName + " updated", MessageType.INFO)); } }); } Monday, March 21, 2011 29
  • 30. Using RequestFactory private void getData() { // To retrieve relations and value types, use .with() Request<List<ItemListProxy>> findAllReq = rf.itemListRequest() .listAll().with("owner"); // Receiver specifies return type findAllReq.fire(new Receiver<List<ItemListProxy>>() { @Override Text public void onSuccess(List<ItemListProxy> response) { updateRowData(0, response); } }); } Monday, March 21, 2011 30
  • 31. Using RequestFactory editList = reqCtx.edit(editList); List<ListItemProxy> items = editList.getItems(); // must initialize collections if (items == null) { editList.setItems(new ArrayList<ListItemProxy>()); } editList.getItems().add(newItem); reqCtx.save(editList).with("items").to(new Receiver<Void>() { @Override public void onSuccess(Void response) { itemsProvider.setList(editList.getItems()); itemsProvider.refresh(); } }).fire(); Monday, March 21, 2011 31
  • 32. GWT MVP - Concepts View - Interface + implementation - Interface enables testing without GWTTestCase - Typically expensive to construct so make reusable Presenter - No Widgets, just business logic - Middle man between service layer and views Monday, March 21, 2011 32
  • 33. GWT MVP - Concepts Place - Place represents bookmarkable state of an activity - PlaceController makes back button / bookmarks work like users expect - PlaceTokenizers map to / from String tokens on URL Monday, March 21, 2011 33
  • 34. Demo third_party/java_src/gwt/svn/trunk/samples/ expenses Monday, March 21, 2011 34
  • 35. Place public class EditListPlace extends Place { private String token; public EditListPlace(String token) { this.token = token; } public String getToken() { return token; } public static class Tokenizer implements PlaceTokenizer<EditListPlace> { public EditListPlace getPlace(String token) { return new EditListPlace(token); } public String getToken(EditListPlace place) { return place.getToken(); } } } Monday, March 21, 2011 35
  • 36. PlaceHistoryMapper /** * PlaceHistoryMapper interface is used to attach all places which the * PlaceHistoryHandler should be aware of. This is done via the @WithTokenizers * annotation or by extending PlaceHistoryMapperWithFactory and creating a * separate TokenizerFactory. */ @WithTokenizers({ ListsPlace.Tokenizer.class, EditListPlace.Tokenizer.class }) public interface AppPlaceHistoryMapper extends PlaceHistoryMapper { } Monday, March 21, 2011 36
  • 37. Hello Places // Start PlaceHistoryHandler with our PlaceHistoryMapper PlaceHistoryMapper historyMapper = clientFactory.getHistoryMapper(); PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(hisoryMapper); historyHandler.register(placeController, eventBus, defaultPlace); // Goes to place represented on URL or default place historyHandler.handleCurrentHistory(); Monday, March 21, 2011 37
  • 38. Places: Moving parts Monday, March 21, 2011 38
  • 39. Places: Go to Monday, March 21, 2011 39
  • 40. Places: Back and forth Monday, March 21, 2011 40
  • 41. Activities Activity, ActivityManager are not required! ActivityManager - Owns a region of the window - Choose what to do with it on place change Activity (“wake up, set up, show up”) - Started by ActivityManager - Provides a widget to display, asynchronously - Can refuse to relinquish screen Monday, March 21, 2011 41
  • 42. Activity public class EditListActivity extends AbstractActivity implements Presenter { private ClientFactory clientFactory; private EventBus eventBus; public EditListActivity(ClientFactory cf, EditListPlace editListPlace) { this.clientFactory = cf; this.itemListToken = editListPlace.getToken(); } @Override public void start(final AcceptsOneWidget panel, EventBus eventBus) { this.eventBus = eventBus; ... panel.setWidget(clientFactory.getEditListView()); } ... } Monday, March 21, 2011 42
  • 43. ActivityMapper public class AppActivityMapper implements ActivityMapper { private ClientFactory clientFactory; public AppActivityMapper(ClientFactory clientFactory) { super(); this.clientFactory = clientFactory; } @Override public Activity getActivity(Place place) { if (place instanceof EditListPlace) { return new EditListActivity(clientFactory, (EditListPlace) place); } if (place instanceof ListsPlace) { return new ListsActivity(clientFactory); } return null; } } Monday, March 21, 2011 43
  • 44. ActivityMapper Idioms Disposable Activities, shared views: if (place instanceof FooPlace) { return new FooActivity(theOnlyFooView); } Singleton: if (place instanceof FooPlace) { theOnlyFooActivity.update((FooPlace) place); return theOnlyFooActivity; } Monday, March 21, 2011 44
  • 48. Activities and Places wiring // Start ActivityManager for the nav (west) panel with our WestActivityMapper ActivityMapper westActivityMapper = new WestActivityMapper(clientFactory); ActivityManager westActivityManager = new ActivityManager(westActivityMapper, eventBus); westActivityManager.setDisplay(westPanel); // Start ActivityManager for the main (center) panel with our CenterActivityMapper ActivityMapper centerActivityMapper = new CenterActivityMapper(clientFactory); ActivityManager centerActivityManager = new ActivityManager(centerActivityMapper, eventBus); centerActivityManager.setDisplay(centerPanel); // Start PlaceHistoryHandler with our PlaceHistoryMapper PlaceHistoryMapper historyMapper = GWT.create(AppPlaceHistoryMapper.class); PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper); historyHandler.register(placeController, eventBus, defaultPlace); RootPanel.get().add(dockLayoutPanel); // Goes to place represented on URL or default place historyHandler.handleCurrentHistory(); Monday, March 21, 2011 48
  • 49. Cell Widgets Fast, lightweight table rendering Data binding with DataProviders, ValueUpdaters Scrolling and paging controls Sortable columns, adjustable width TextBox, IntegerBox, ValueBox<T> Monday, March 21, 2011 49
  • 51. Editable Column // Editable column for list name nameColumn = new Column<ItemListProxy,String>(new EditTextCell()) { @Override public String getValue(ItemListProxy list) { return list.getName(); } }; Monday, March 21, 2011 51
  • 52. Custom Column type // Note Flyweight pattern: only one instance of HyperlinkCell passed to the Column Column<ItemListProxy, Hyperlink> linkColumn = new Column<ItemListProxy, Hyperlink>(new HyperlinkCell()) { @Override public Hyperlink getValue(ItemListProxy list) { String proxyToken = clientFactory.getRequestFactory().getHistoryToken(list.stableId()); String historyToken = clientFactory.getHistoryMapper().getToken(new EditListPlace(proxyToken)); Hyperlink h = new Hyperlink(list.getName(),historyToken); return h; } }; Monday, March 21, 2011 52
  • 53. Populating a CellTable public static class MyDataProvider extends AsyncDataProvider<ItemListProxy> { @Override protected void onRangeChanged(HasData<ItemListProxy> display) { // To retrieve relations and value types, use .with() Request<List<ItemListProxy>> findAllReq = rf.itemListRequest() .listAll().with("owner"); // Receiver specifies return type findAllReq.fire(new Receiver<List<ItemListProxy>>() { @Override public void onSuccess(List<ItemListProxy> response) { updateRowData(0, response); } }); } } this.myDataProvider = new MyDataProvider(requestFactory); Monday, March 21, 2011 53
  • 54. Updating with a CellTable public class NameFieldUpdater implements FieldUpdater<ItemListProxy, String> { @Override public void update(int index, ItemListProxy obj, final String newName) { ItemListRequestContext reqCtx = clientFactory.getRequestFactory() .itemListRequest(); ItemListProxy editable = reqCtx.edit(obj); editable.setName(newName); reqCtx.save(editable).fire(new Receiver<Void>() { @Override public void onSuccess(Void response) { eventBus.fireEvent(new MessageEvent(newName + " updated", MessageType.INFO)); } }); } }; // Make list name field editable display.getNameColumn().setFieldUpdater(new NameFieldUpdater()); Monday, March 21, 2011 54
  • 55. GWT Canvas http://gwtcanvasdemo.appspot.com Monday, March 21, 2011 55
  • 56. GWT Logging GWT now has java.util.Logging emulation Configure in your .gwt.xml Easily enable remote logging, too Monday, March 21, 2011 56
  • 57. GWT speak “Very productive environment for Java developers, but there is a learning curve” “UI layout and styling is a challenge” “GWT has enabled our team to run much faster than we could otherwise” “Would be impossible to write our app without GWT” Monday, March 21, 2011 57
  • 58. New GWT book http://code.google.com/webtoolkit/books.html Monday, March 21, 2011 58
  • 59. Thank you! Where to get it: http://code.google.com/webtoolkit/ Wiki, issue tracker, source: http://code.google.com/p/google-web-toolkit/ Official GWT blog: http://google-web-toolkit.blogspot.com/ Twitter: @googledevtools 59 Monday, March 21, 2011 59