SlideShare a Scribd company logo
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

More Related Content

Similar to 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 GWT
Arnaud 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 Couchbase
Tugdual Grall
 
RunDeck
RunDeckRunDeck
RunDeck
Bruno Bonfils
 
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
Deepu S Nath
 
XNAT Open Source Development
XNAT Open Source DevelopmentXNAT Open Source Development
XNAT Open Source Development
John 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 Comparison
Deepu 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 #11
Magecom UK Limited
 
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...
AIMS (Agricultural Information Management Standards)
 
Gerrit linuxtag2011
Gerrit linuxtag2011Gerrit linuxtag2011
Gerrit linuxtag2011
thkoch
 
Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316
Richmond Java User's Group
 
HTML XHTML HTML5
HTML XHTML HTML5HTML XHTML HTML5
HTML XHTML HTML5
timstone
 
Integrando Plone con cualquier cosa
Integrando Plone con cualquier cosaIntegrando Plone con cualquier cosa
Integrando Plone con cualquier cosa
menttes
 
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
Emanuele Di Saverio
 
Reactjs
ReactjsReactjs
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
Julio 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 2009
Alexandre 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 Dashboards
Julien Pivotto
 
Delivering with ember.js
Delivering with ember.jsDelivering with ember.js
Delivering with ember.js
Andrei Sebastian Cîmpean
 

Similar to 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
 
Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316
 
HTML XHTML HTML5
HTML XHTML HTML5HTML XHTML HTML5
HTML XHTML HTML5
 
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
 

More from 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.0
David 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 SQLite
David 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 RestyGWT
David Chandler
 
Cómo trabajan los Googlers
Cómo trabajan los GooglersCómo trabajan los Googlers
Cómo trabajan los Googlers
David Chandler
 
Life of an engineer
Life of an engineerLife of an engineer
Life of an engineer
David Chandler
 
StORM preview
StORM previewStORM preview
StORM preview
David Chandler
 
Google App Engine Update 2012
Google App Engine Update 2012Google App Engine Update 2012
Google App Engine Update 2012
David Chandler
 
GWT Plus HTML 5
GWT Plus HTML 5GWT Plus HTML 5
GWT Plus HTML 5
David Chandler
 
Scalable Apps with Google App Engine
Scalable Apps with Google App EngineScalable Apps with Google App Engine
Scalable Apps with Google App Engine
David 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 Java
David Chandler
 
GWT MVP Case Study
GWT MVP Case StudyGWT MVP Case Study
GWT MVP Case Study
David 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 Ten
David Chandler
 

More from 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
 

Recently uploaded

Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
Elena Simperl
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 

Recently uploaded (20)

Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 

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