GWT It’s Java all the way Ophir Radnitz Consultant, AlphaCSP
Mission Statement “ GWT's mission is to  radically improve   the web experience   for users   by enabling developers to use existing Java tools to build no-compromise AJAX for any modern browser. ”
Overview Introduction Demo Features Discussion Summary
Overview Introduction Demo Features Discussion Summary
Overview Java  Javascript compiler (!) Dynamic, reusable UI components Fast, responsive rich interface Easy on the developer Apache v2.0 license
Features  (1 of 2) Cross browser compatibility Highly optimized output A good handle on The Web Browser history management Safe and powerful DOM access Bookmarkable stuff Secure remoting
Features  (2 of 2) Lots  of ready rich components JUnit integration Built-in benchmarking  Easy I18N Debugging Your IDE
… Powered By GWT Google Code Google Health Google Checkout Google Base Lombardi Blueprint Contact Office Compiere Queplix Awdio DimDim Scenechronize QueWeb CRM Applications built at SAP, SAS, Library  of Congress
History May August November February August May Formerly known as  “ Project Red Pill ” Announced on JavaOne 2006
Status Version 1.5 Release Candidate Support for Java 5 features Even more compiler optimizations UI library additions (animations, themes) I18N (Bi-di, pluralizations), accessibility Better DOM API Emerging libraries and integrations
What’s in it? JRE Emulation (java.lang, java.util) GWT Compiler Hosted Browser Class Library
Where does Speed Come From? Fewer Requests (by far) Compiler optimization Javascript Deferred binding Versioned cache Efficient RPC Reduced load on the server
Deferred Binding The GWT Mantra: Why do at runtime what you can do at compile time? MyService  service  =  GWT . create ( MyService . class );
Hosted Mode
Entry Point Anatomy MyPage.html < script   language =&quot;javascript&quot;  src =&quot; com.alphacsp.demo.MyModule.nocache.js “/> com.alphacsp.demo.MyModule. <MD5>.cache.js “
Compiled Javascript function com_alphacsp_contacts_Contacts(){var l='',B='&quot; for &quot;gwt:onLoadErrorFn&quot;',z='&quot; for &quot;gwt:onPropertyErrorFn&quot;',wb='&quot;><\/script>',n='/',kb='226AF0230B73371F6FD432899942EF89.cache.html',ib='6C5371FFFFB5323F9D8058C234E97823.cache.html',jb='86331CB96F6F13236040789304D78367.cache.html',lb='96AB31FA627C259590E8CA143E53C3E0.cache.html',vb='<script id=&quot;',sb=&quot;<script>com_alphacsp_contacts_Contacts.onInjectionDone('com.alphacsp.contacts.Contacts')<\/script>&quot;,v='=',y='Bad handler &quot;',ob='DOMContentLoaded',mb='E6FAB8BEE24B098AC223BA54C66FD81B.cache.html',xb='SCRIPT',ub='__gwt_marker_com.alphacsp.contacts.Contacts',o='base',q='clear.cache.gif',m='com.alphacsp.contacts.Contacts',u='content',db='gecko',eb='gecko1_8',nb='gwt.hybrid',A='gwt:onLoadErrorFn',w='gwt:onPropertyErrorFn',t='gwt:property',hb='hosted.html?com_alphacsp_contacts_Contacts',bb='ie6',pb='iframe',p='img',qb=&quot;javascript:''&quot;,r='meta',gb='moduleRequested',ab='msie',s='name',D='opera',rb='position:absolute;width:0;height:0;border:none',F='safari',tb='selectionDone',cb='selectionStart',x='startup',fb='unknown',C='user.agent',E='webkit';var zb=window,k=document,bc=zb.external,yb=zb.__gwtstatsEvent?function(a,b,c,d){zb.__gwtstatsEvent(a,b,c,d)}:null,oc,ec,Eb,Db=l,hc={},rc=[],nc=[],Cb=[],kc,mc;yb&&yb(m,x,cb,{millis:(new Date()).getTime()});if(!zb.__gwt_stylesLoaded){zb.__gwt_stylesLoaded={}}if(!zb.__gwt_scriptsLoaded){zb.__gwt_scriptsLoaded={}}function dc(){try{return bc&&(bc.gwtOnLoad&&zb.location.search.indexOf(nb)==-1)}catch(a){return false}}function gc(){if(oc&&ec){var c=k.getElementById(m);var b=c.contentWindow;b.__gwt_initHandlers=com_alphacsp_contacts_Contacts.__gwt_initHandlers;if(dc()){b.__gwt_getProperty=function(a){return Fb(a)}}com_alphacsp_contacts_Contacts=null;b.gwtOnLoad(kc,m,Db);yb&&yb(m,x,tb,{millis:(new Date()).getTime()})}}function ac(){var j,h=ub,i;k.write(vb+h+wb);i=k.getElementById(h);j=i&&i.previousSibling;while(j&&j.tagName!=xb){j=j.previousSibling}function d(b){var a=b.lastIndexOf(n);return a>=0?b.substring(0,a+1):l};if(j&&j.src){Db=d(j.src)}if(Db==l){var c=k.getElementsByTagName(o);if(c.length>0){Db=c[c.length-1].href}else{var g=k.location;var e=g.href;Db=d(e.substr(0,e.length-g.hash.length))}}else if(Db.match(/^\w+:\/\//)){}else{var f=k.createElement(p);f.src=Db+q;Db=d(f.src)}if(i){i.parentNode.removeChild(i)}}function lc(){var f=document.getElementsByTagName(r);for(var d=0,g=f.length;d<g;++d){var e=f[d],h=e.getAttribute(s),b;if(h){if(h==t){b=e.getAttribute(u);if(b){var i,c=b.indexOf(v);if(c>=0){h=b.substring(0,c);i=b.substring(c+1)}else{h=b;i=l}hc[h]=i}}else if(h==w){b=e.getAttribute(u);if(b){try{mc=eval(b)}catch(a){alert(y+b+z)}}}else if(h==A){b=e.getAttribute(u);if(b){try{kc=eval(b)}catch(a){alert(y+b+B)}}}}}}function qc(d,e){var a=Cb;for(var b=0,c=d.length-1;b<c;++b){a=a[d[b]]||(a[d[b]]=[])}a[d[c]]=e}function Fb(d){var e=nc[d](),b=rc[d];if(e in b){return e}var a=[];for(var c in b){a[b[c]]=c}if(mc){mc(d,a,e)}throw null}nc[C]=function(){var d=navigator.userAgent.toLowerCase();var b=function(a){return parseInt(a[1])*1000+parseInt(a[2])};if(d.indexOf(D)!=-1){return D}else if(d.indexOf(E)!=-1){return F}else if(d.indexOf(ab)!=-1){var c=/msie ([0-9]+)\.([0-9]+)/.exec(d);if(c&&c.length==3){if(b(c)>=6000){return bb}}}else if(d.indexOf(db)!=-1){var c=/rv:([0-9]+)\.([0-9]+)/.exec(d);if(c&&c.length==3){if(b(c)>=1008)return eb}return db}return fb};rc[C]={gecko:0,gecko1_8:1,ie6:2,opera:3,safari:4};com_alphacsp_contacts_Contacts.onInjectionDone=function(){oc=true;yb&&yb(m,x,gb,{millis:(new Date()).getTime()});gc()};com_alphacsp_contacts_Contacts.onScriptLoad=function(){ec=true;gc()};ac();lc();var pc;if(dc()){pc=hb}else{try{qc([D],ib);qc([F],jb);qc([bb],kb);qc([eb],lb);qc([db],mb);pc=Cb[Fb(C)]}catch(a){return}}var jc;function ic(){if(!Eb){Eb=true;gc();if(k.removeEventListener){k.removeEventListener(ob,ic,false)}if(jc){clearInterval(jc)}}}var cc;function fc(){if(!cc){cc=true;var a=k.createElement(pb);a.src=qb;a.id=m;a.style.cssText=rb;a.tabIndex=-1;k.body.appendChild(a);a.src=Db+pc}}if(k.addEventListener){k.addEventListener(ob,function(){fc();ic()},false)}var jc=setInterval(function(){if(/loaded|complete/.test(k.readyState)){fc();ic()}},50);k.write(sb)}com_alphacsp_contacts_Contacts.__gwt_initHandlers=function(i,e,j){var d=window,g=d.onresize,f=d.onbeforeunload,h=d.onunload;d.onresize=function(a){try{i()}finally{g&&g(a)}};d.onbeforeunload=function(a){var c,b;try{c=e()}finally{b=f&&f(a)}if(c!=null){return c}if(b!=null){return b}};d.onunload=function(a){try{j()}finally{h&&h(a)}}};com_alphacsp_contacts_Contacts();
Project structure Resource Description /client Your client-side stuff /server Your server-side stuff /public Your resources (css, images, js) MyModule.gwt.xml Your module configuration
Configuration A module file: < module >  < inherits  name =“ com.google.gwt.user.User “  / > < entry-point  class =“ com.alphacsp.demo.MyModule &quot;  / >  </ module >  Contact.gwt.xml
Agenda Introduction Demo Features Discussion Summary
Base HTML Template < html >  < head >  <!-- Properties can be specified to influence deferred binding -->  < meta   name ='gwt:property'  content ='locale=en_UK'> < link   rel =&quot;stylesheet&quot;  href =&quot;Calendar.css&quot;>  < title >Demo Contacts Application</ title >  </ head >  < body > < script   language =&quot;javascript&quot;  src =&quot; com.alphacsp.demo.MyModule.nocache.js “/> <!-- Include a history iframe to enable full GWT history support -->  < iframe   src =&quot;javascript:''&quot;  id =&quot;__gwt_historyFrame&quot;  style =&quot;width:0;height:0;border:0“/> < div   id =“ niceWidgetThingHere ”/> </ body >  </ html >  Contact.html Standard GWT injection Access and manipulate however you like
View Technology  (1 of 2) FormPanel  loginPanel  =  new   FormPanel (); loginPanel . setFrame ( true ); loginPanel . setBorders ( true ); loginPanel . setButtonAlign ( HorizontalAlignment. CENTER); loginPanel . setHeading (constants. login ()); loginPanel . setFieldWidth (210); loginPanel . setLabelWidth (100); loginPanel . setWidth (400); TextField  usernameField  =  new   TextField < String >(); usernameField . setFieldLabel( constants. userNameField ()); loginPanel . add ( usernameField ); TextField  passwordField  =  new   TextField < String >(); passwordField . setFieldLabel( constants. passwordField ()); passwordField . setPassword( true ); loginPanel . add ( passwordField ); LoginView.java
View Technology  (2 of 2) Button   loginButton  =  new   Button (constants. loginButton ()); loginButton . setType (&quot;submit&quot;); loginButton . addSelectionListener( new   SelectionListener < ButtonEvent >() { @Override  public void  componentSelected ( ButtonEvent  be) { login ( usernameField . getValue (),  passwordField . getValue ()); } }); loginPanel . addButton ( loginButton ); LoginView.java Client-side event handling  
Page Flow private void  switchToView ( View   view) { viewport . removeAll (); viewport . add (view. getContent ()); viewport . layout (); } Controller.java What’s a page?
Form Binding List < TableColumn >  columns  =  new   ArrayList < TableColumn >(); columns . add ( new   TableColumn ( “name” ,  constants . nameColumn (), 150)); columns . add ( new  TableColumn ( “email” ,  constants . emailColumn (), 150)); columns . add ( new  TableColumn ( “department” ,  constants . departmentColumn (), 100); Table   table  =  new  Table ( new   TableColumnModel ( columns )); LookupView.java
Pagination // table TableColumnModel  columnModel  = new  TableColumnModel ( columns ); Table   table  =  new   Table ( columnModel ); // pagingLoader PagingLoader < PagingLoadConfig >  pagingLoader  =  new  BasePagingLoader (proxy); // store ListStore < Employee >  store  =  new   ListStore < Employee >( pagingLoader ); // binder new   TableBinder < Employee >( table ,  store ); PagingToolBar   toolBar  =  new   PagingToolBar (50); toolBar . bind ( pagingLoader ); LookupView.java
Table Sorting pagingLoader. setRemoteSort ( false ); LookupView.java
Validation emailField . setAllowBlank (false); emailField . setRegex (&quot; [a-zA-Z0-9]@+ &quot;); emailField . getMessages (). setRegexText (“Please use alphabet only); emailField . setValidator ( new  Validator () { public String  validate ( Field   field,  String  value) { // … } }); LookupView.java
AJAX  (1 of 2) Registering the service under this  name Mandatory stuff… It’s great to be a servlet @RemoteServiceRelativePath (&quot;l ookup &quot;)  public interface  LoginService  extends  RemoteService   { Employee   login ( String  userName,  String  password)  throws  UnsuccessfulLoginException ; } LoginService.java public interface  LoginServiceAsync   { void   login ( String  userName,  String  password,  AsyncCallback<Employee>  callback); } LoginServiceAsync.java public class  LoginServiceImpl  extends  RemoteServiceServlet   { String   login ( String  userName,  String  password) { // …. } } LoginServiceImpl.java
AJAX  (2 of 2) LoginServiceAsync   loginService  =  GWT . create ( LoginService . class ); loginService . login (username, password,  new   AsyncCallback<Employee>  { public void  onSucces s( Employee  result) { passwordField . setValue (&quot;&quot;); controller . setUsername (username); controller . loggedIn (); } public void  onFailure ( Throwable  caught) { try  { throw  caught; }  catch  ( UnsuccessfulLoginException  e) { loginPanel . setHeading (caught. getMessage ()); }  catch  ( Throwable  throwable) { // do whatever } } }); Yeepee! Deal with it… LoginView.java
I18N Support  (1 of 2) public interface  LoginMessages   extends  Messages  { String   fieldBlank ( String  fieldName); // … } LoginMessages.java fieldBlank = {0} cannot be empty. … . LoginMessages.properties LoginConstants  messages  = GWT . create ( LoginMessages .class ); String  message =  messages . fieldBlank (“Username”); anywhere
I18N Support  (2 of 2) < head > < meta   name =&quot; gwt:property &quot;  content =&quot; locale=ja_JP &quot;> < head > myPage.html http://www.example.org/myapp.html? locale=fr_CA Locale resolution: By metadata: By request parameter:
Error Handling GWT . setUncaughtExceptionHandler ( new  GWT . UncaughtExceptionHandler ()  { public void  onUncaughtException ( Throwable  e) { GWT . log (e. getMessage (), e); // … } }); Contacts.java
Agenda Introduction Demo Features Discussion Summary
Documentation GWT reference Decent Javadoc Active Forum onGWT.com, GWT Site Books
Did You Know? Can be very minimal Doesn’t require a Java backend Doesn’t mess with your Javascript Conversational state is saved in the client
Design Programmatic layouting Everything is CSS Go ahead, tweak your DOM Out of the box themes
Roadmap Simplified RPC Support for very large modules Drag and drop support Animation/effects support Vector graphics library (canvas, SVG, VML)
Tools IntelliJ IDEA Cypal Studio (for Eclipse) GWT4NB (for NetBeans) Instantiations Maven
Integrations HTML Seam, Grails, Spring MVC Google APIs, Google Gears
3 rd  party Ext-GWT Gwittir GWT Rocket GWT Log
Agenda Introduction Demo Features Discussion Summary
Cons It runs as Javascript No real concurrency Very limited reflection Limited POJO binding so far Verbatim design takes work Think outside the box
Pros Fast, fast, fast (and dynamic) Easy to mix OO, nice tooling Conversational state No more markup/Javascript soup Think outside the box
Resources http://code.google.com/webtoolkit/ http:// www.onGWT.com http://del.icio.us/liqweed/GWT
Thank  You !

GWT

  • 1.
  • 2.
    GWT It’s Javaall the way Ophir Radnitz Consultant, AlphaCSP
  • 3.
    Mission Statement “GWT's mission is to radically improve the web experience for users by enabling developers to use existing Java tools to build no-compromise AJAX for any modern browser. ”
  • 4.
    Overview Introduction DemoFeatures Discussion Summary
  • 5.
    Overview Introduction DemoFeatures Discussion Summary
  • 6.
    Overview Java Javascript compiler (!) Dynamic, reusable UI components Fast, responsive rich interface Easy on the developer Apache v2.0 license
  • 7.
    Features (1of 2) Cross browser compatibility Highly optimized output A good handle on The Web Browser history management Safe and powerful DOM access Bookmarkable stuff Secure remoting
  • 8.
    Features (2of 2) Lots of ready rich components JUnit integration Built-in benchmarking Easy I18N Debugging Your IDE
  • 9.
    … Powered ByGWT Google Code Google Health Google Checkout Google Base Lombardi Blueprint Contact Office Compiere Queplix Awdio DimDim Scenechronize QueWeb CRM Applications built at SAP, SAS, Library of Congress
  • 10.
    History May AugustNovember February August May Formerly known as “ Project Red Pill ” Announced on JavaOne 2006
  • 11.
    Status Version 1.5Release Candidate Support for Java 5 features Even more compiler optimizations UI library additions (animations, themes) I18N (Bi-di, pluralizations), accessibility Better DOM API Emerging libraries and integrations
  • 12.
    What’s in it?JRE Emulation (java.lang, java.util) GWT Compiler Hosted Browser Class Library
  • 13.
    Where does SpeedCome From? Fewer Requests (by far) Compiler optimization Javascript Deferred binding Versioned cache Efficient RPC Reduced load on the server
  • 14.
    Deferred Binding TheGWT Mantra: Why do at runtime what you can do at compile time? MyService service = GWT . create ( MyService . class );
  • 15.
  • 16.
    Entry Point AnatomyMyPage.html < script language =&quot;javascript&quot; src =&quot; com.alphacsp.demo.MyModule.nocache.js “/> com.alphacsp.demo.MyModule. <MD5>.cache.js “
  • 17.
    Compiled Javascript functioncom_alphacsp_contacts_Contacts(){var l='',B='&quot; for &quot;gwt:onLoadErrorFn&quot;',z='&quot; for &quot;gwt:onPropertyErrorFn&quot;',wb='&quot;><\/script>',n='/',kb='226AF0230B73371F6FD432899942EF89.cache.html',ib='6C5371FFFFB5323F9D8058C234E97823.cache.html',jb='86331CB96F6F13236040789304D78367.cache.html',lb='96AB31FA627C259590E8CA143E53C3E0.cache.html',vb='<script id=&quot;',sb=&quot;<script>com_alphacsp_contacts_Contacts.onInjectionDone('com.alphacsp.contacts.Contacts')<\/script>&quot;,v='=',y='Bad handler &quot;',ob='DOMContentLoaded',mb='E6FAB8BEE24B098AC223BA54C66FD81B.cache.html',xb='SCRIPT',ub='__gwt_marker_com.alphacsp.contacts.Contacts',o='base',q='clear.cache.gif',m='com.alphacsp.contacts.Contacts',u='content',db='gecko',eb='gecko1_8',nb='gwt.hybrid',A='gwt:onLoadErrorFn',w='gwt:onPropertyErrorFn',t='gwt:property',hb='hosted.html?com_alphacsp_contacts_Contacts',bb='ie6',pb='iframe',p='img',qb=&quot;javascript:''&quot;,r='meta',gb='moduleRequested',ab='msie',s='name',D='opera',rb='position:absolute;width:0;height:0;border:none',F='safari',tb='selectionDone',cb='selectionStart',x='startup',fb='unknown',C='user.agent',E='webkit';var zb=window,k=document,bc=zb.external,yb=zb.__gwtstatsEvent?function(a,b,c,d){zb.__gwtstatsEvent(a,b,c,d)}:null,oc,ec,Eb,Db=l,hc={},rc=[],nc=[],Cb=[],kc,mc;yb&&yb(m,x,cb,{millis:(new Date()).getTime()});if(!zb.__gwt_stylesLoaded){zb.__gwt_stylesLoaded={}}if(!zb.__gwt_scriptsLoaded){zb.__gwt_scriptsLoaded={}}function dc(){try{return bc&&(bc.gwtOnLoad&&zb.location.search.indexOf(nb)==-1)}catch(a){return false}}function gc(){if(oc&&ec){var c=k.getElementById(m);var b=c.contentWindow;b.__gwt_initHandlers=com_alphacsp_contacts_Contacts.__gwt_initHandlers;if(dc()){b.__gwt_getProperty=function(a){return Fb(a)}}com_alphacsp_contacts_Contacts=null;b.gwtOnLoad(kc,m,Db);yb&&yb(m,x,tb,{millis:(new Date()).getTime()})}}function ac(){var j,h=ub,i;k.write(vb+h+wb);i=k.getElementById(h);j=i&&i.previousSibling;while(j&&j.tagName!=xb){j=j.previousSibling}function d(b){var a=b.lastIndexOf(n);return a>=0?b.substring(0,a+1):l};if(j&&j.src){Db=d(j.src)}if(Db==l){var c=k.getElementsByTagName(o);if(c.length>0){Db=c[c.length-1].href}else{var g=k.location;var e=g.href;Db=d(e.substr(0,e.length-g.hash.length))}}else if(Db.match(/^\w+:\/\//)){}else{var f=k.createElement(p);f.src=Db+q;Db=d(f.src)}if(i){i.parentNode.removeChild(i)}}function lc(){var f=document.getElementsByTagName(r);for(var d=0,g=f.length;d<g;++d){var e=f[d],h=e.getAttribute(s),b;if(h){if(h==t){b=e.getAttribute(u);if(b){var i,c=b.indexOf(v);if(c>=0){h=b.substring(0,c);i=b.substring(c+1)}else{h=b;i=l}hc[h]=i}}else if(h==w){b=e.getAttribute(u);if(b){try{mc=eval(b)}catch(a){alert(y+b+z)}}}else if(h==A){b=e.getAttribute(u);if(b){try{kc=eval(b)}catch(a){alert(y+b+B)}}}}}}function qc(d,e){var a=Cb;for(var b=0,c=d.length-1;b<c;++b){a=a[d[b]]||(a[d[b]]=[])}a[d[c]]=e}function Fb(d){var e=nc[d](),b=rc[d];if(e in b){return e}var a=[];for(var c in b){a[b[c]]=c}if(mc){mc(d,a,e)}throw null}nc[C]=function(){var d=navigator.userAgent.toLowerCase();var b=function(a){return parseInt(a[1])*1000+parseInt(a[2])};if(d.indexOf(D)!=-1){return D}else if(d.indexOf(E)!=-1){return F}else if(d.indexOf(ab)!=-1){var c=/msie ([0-9]+)\.([0-9]+)/.exec(d);if(c&&c.length==3){if(b(c)>=6000){return bb}}}else if(d.indexOf(db)!=-1){var c=/rv:([0-9]+)\.([0-9]+)/.exec(d);if(c&&c.length==3){if(b(c)>=1008)return eb}return db}return fb};rc[C]={gecko:0,gecko1_8:1,ie6:2,opera:3,safari:4};com_alphacsp_contacts_Contacts.onInjectionDone=function(){oc=true;yb&&yb(m,x,gb,{millis:(new Date()).getTime()});gc()};com_alphacsp_contacts_Contacts.onScriptLoad=function(){ec=true;gc()};ac();lc();var pc;if(dc()){pc=hb}else{try{qc([D],ib);qc([F],jb);qc([bb],kb);qc([eb],lb);qc([db],mb);pc=Cb[Fb(C)]}catch(a){return}}var jc;function ic(){if(!Eb){Eb=true;gc();if(k.removeEventListener){k.removeEventListener(ob,ic,false)}if(jc){clearInterval(jc)}}}var cc;function fc(){if(!cc){cc=true;var a=k.createElement(pb);a.src=qb;a.id=m;a.style.cssText=rb;a.tabIndex=-1;k.body.appendChild(a);a.src=Db+pc}}if(k.addEventListener){k.addEventListener(ob,function(){fc();ic()},false)}var jc=setInterval(function(){if(/loaded|complete/.test(k.readyState)){fc();ic()}},50);k.write(sb)}com_alphacsp_contacts_Contacts.__gwt_initHandlers=function(i,e,j){var d=window,g=d.onresize,f=d.onbeforeunload,h=d.onunload;d.onresize=function(a){try{i()}finally{g&&g(a)}};d.onbeforeunload=function(a){var c,b;try{c=e()}finally{b=f&&f(a)}if(c!=null){return c}if(b!=null){return b}};d.onunload=function(a){try{j()}finally{h&&h(a)}}};com_alphacsp_contacts_Contacts();
  • 18.
    Project structure ResourceDescription /client Your client-side stuff /server Your server-side stuff /public Your resources (css, images, js) MyModule.gwt.xml Your module configuration
  • 19.
    Configuration A modulefile: < module > < inherits name =“ com.google.gwt.user.User “ / > < entry-point class =“ com.alphacsp.demo.MyModule &quot; / > </ module > Contact.gwt.xml
  • 20.
    Agenda Introduction DemoFeatures Discussion Summary
  • 21.
    Base HTML Template< html > < head > <!-- Properties can be specified to influence deferred binding --> < meta name ='gwt:property' content ='locale=en_UK'> < link rel =&quot;stylesheet&quot; href =&quot;Calendar.css&quot;> < title >Demo Contacts Application</ title > </ head > < body > < script language =&quot;javascript&quot; src =&quot; com.alphacsp.demo.MyModule.nocache.js “/> <!-- Include a history iframe to enable full GWT history support --> < iframe src =&quot;javascript:''&quot; id =&quot;__gwt_historyFrame&quot; style =&quot;width:0;height:0;border:0“/> < div id =“ niceWidgetThingHere ”/> </ body > </ html > Contact.html Standard GWT injection Access and manipulate however you like
  • 22.
    View Technology (1 of 2) FormPanel loginPanel = new FormPanel (); loginPanel . setFrame ( true ); loginPanel . setBorders ( true ); loginPanel . setButtonAlign ( HorizontalAlignment. CENTER); loginPanel . setHeading (constants. login ()); loginPanel . setFieldWidth (210); loginPanel . setLabelWidth (100); loginPanel . setWidth (400); TextField usernameField = new TextField < String >(); usernameField . setFieldLabel( constants. userNameField ()); loginPanel . add ( usernameField ); TextField passwordField = new TextField < String >(); passwordField . setFieldLabel( constants. passwordField ()); passwordField . setPassword( true ); loginPanel . add ( passwordField ); LoginView.java
  • 23.
    View Technology (2 of 2) Button loginButton = new Button (constants. loginButton ()); loginButton . setType (&quot;submit&quot;); loginButton . addSelectionListener( new SelectionListener < ButtonEvent >() { @Override public void componentSelected ( ButtonEvent be) { login ( usernameField . getValue (), passwordField . getValue ()); } }); loginPanel . addButton ( loginButton ); LoginView.java Client-side event handling 
  • 24.
    Page Flow privatevoid switchToView ( View view) { viewport . removeAll (); viewport . add (view. getContent ()); viewport . layout (); } Controller.java What’s a page?
  • 25.
    Form Binding List< TableColumn > columns = new ArrayList < TableColumn >(); columns . add ( new TableColumn ( “name” , constants . nameColumn (), 150)); columns . add ( new TableColumn ( “email” , constants . emailColumn (), 150)); columns . add ( new TableColumn ( “department” , constants . departmentColumn (), 100); Table table = new Table ( new TableColumnModel ( columns )); LookupView.java
  • 26.
    Pagination // tableTableColumnModel columnModel = new TableColumnModel ( columns ); Table table = new Table ( columnModel ); // pagingLoader PagingLoader < PagingLoadConfig > pagingLoader = new BasePagingLoader (proxy); // store ListStore < Employee > store = new ListStore < Employee >( pagingLoader ); // binder new TableBinder < Employee >( table , store ); PagingToolBar toolBar = new PagingToolBar (50); toolBar . bind ( pagingLoader ); LookupView.java
  • 27.
    Table Sorting pagingLoader.setRemoteSort ( false ); LookupView.java
  • 28.
    Validation emailField .setAllowBlank (false); emailField . setRegex (&quot; [a-zA-Z0-9]@+ &quot;); emailField . getMessages (). setRegexText (“Please use alphabet only); emailField . setValidator ( new Validator () { public String validate ( Field field, String value) { // … } }); LookupView.java
  • 29.
    AJAX (1of 2) Registering the service under this name Mandatory stuff… It’s great to be a servlet @RemoteServiceRelativePath (&quot;l ookup &quot;) public interface LoginService extends RemoteService { Employee login ( String userName, String password) throws UnsuccessfulLoginException ; } LoginService.java public interface LoginServiceAsync { void login ( String userName, String password, AsyncCallback<Employee> callback); } LoginServiceAsync.java public class LoginServiceImpl extends RemoteServiceServlet { String login ( String userName, String password) { // …. } } LoginServiceImpl.java
  • 30.
    AJAX (2of 2) LoginServiceAsync loginService = GWT . create ( LoginService . class ); loginService . login (username, password, new AsyncCallback<Employee> { public void onSucces s( Employee result) { passwordField . setValue (&quot;&quot;); controller . setUsername (username); controller . loggedIn (); } public void onFailure ( Throwable caught) { try { throw caught; } catch ( UnsuccessfulLoginException e) { loginPanel . setHeading (caught. getMessage ()); } catch ( Throwable throwable) { // do whatever } } }); Yeepee! Deal with it… LoginView.java
  • 31.
    I18N Support (1 of 2) public interface LoginMessages extends Messages { String fieldBlank ( String fieldName); // … } LoginMessages.java fieldBlank = {0} cannot be empty. … . LoginMessages.properties LoginConstants messages = GWT . create ( LoginMessages .class ); String message = messages . fieldBlank (“Username”); anywhere
  • 32.
    I18N Support (2 of 2) < head > < meta name =&quot; gwt:property &quot; content =&quot; locale=ja_JP &quot;> < head > myPage.html http://www.example.org/myapp.html? locale=fr_CA Locale resolution: By metadata: By request parameter:
  • 33.
    Error Handling GWT. setUncaughtExceptionHandler ( new GWT . UncaughtExceptionHandler () { public void onUncaughtException ( Throwable e) { GWT . log (e. getMessage (), e); // … } }); Contacts.java
  • 34.
    Agenda Introduction DemoFeatures Discussion Summary
  • 35.
    Documentation GWT referenceDecent Javadoc Active Forum onGWT.com, GWT Site Books
  • 36.
    Did You Know?Can be very minimal Doesn’t require a Java backend Doesn’t mess with your Javascript Conversational state is saved in the client
  • 37.
    Design Programmatic layoutingEverything is CSS Go ahead, tweak your DOM Out of the box themes
  • 38.
    Roadmap Simplified RPCSupport for very large modules Drag and drop support Animation/effects support Vector graphics library (canvas, SVG, VML)
  • 39.
    Tools IntelliJ IDEACypal Studio (for Eclipse) GWT4NB (for NetBeans) Instantiations Maven
  • 40.
    Integrations HTML Seam,Grails, Spring MVC Google APIs, Google Gears
  • 41.
    3 rd party Ext-GWT Gwittir GWT Rocket GWT Log
  • 42.
    Agenda Introduction DemoFeatures Discussion Summary
  • 43.
    Cons It runsas Javascript No real concurrency Very limited reflection Limited POJO binding so far Verbatim design takes work Think outside the box
  • 44.
    Pros Fast, fast,fast (and dynamic) Easy to mix OO, nice tooling Conversational state No more markup/Javascript soup Think outside the box
  • 45.
    Resources http://code.google.com/webtoolkit/ http://www.onGWT.com http://del.icio.us/liqweed/GWT
  • 46.