GWT

advertisement
Cute and Cuddly UIs
with GWT
What is the Google Web Toolkit?
• Official Definition:
o
“Google Web Toolkit (GWT) is a development toolkit
for building and optimizing complex browser-based
applications."
o
boring definition!
• Real Definition:
o
GWT is a compiler, plus a few frameworks
 It compiles java into optimized javascript
 does quite a bit more too
The Basic GWT app
• Consists of:
o An entry HTML page
 This is what the browser loads when it first hits
the website
o A gwt.xml file, named <Module Name>.gwt.xml
 Contains:
 what browsers to compile for
 java class containing the entry point
 what other modules are inherited (e.g. thirdparty toolkits like Gin, or gwttime)
o Some java source files written using the GWT toolkit
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='library'>
<inherits name='com.google.gwt.user.User'/>
<inherits
name='com.google.gwt.user.theme.standard.Standard'/>
<inherits name="org.gwttime.Time"/>
<!-- Specify the app entry point class. -->
<entry-point class='org.me.library.client.Library'/>
<set-property name="user.agent" value="ie6,ie8,gecko1_8,safari,
opera"/>
</module>
Sample Module.gwt.xml
Major parts of GWT
• UI Framework
• Remote Procedure Call(RPC) structure
• the GWT compiler
UI Frameworks
• GWT's UI toolkit includes:
o
o
o
Widgets
Event system
Resource management
GWT Widgets
• Includes widgets for pretty much all the common
HTML/Javascript widgets
o Button/PushButton
o TextBox, TextArea
o Password box
o etc.
Layout Widgets
• Also includes widgets for doing layouts
o Lay out vertically/horizontally in a row
 FlowPanel, HorizonalPanel
o Lay out in the center, with Borders
 DockLayoutPanel, DockPanel
o With a splitter between two widgets
 SplitLayoutPanel, SplitPanel
o With HTML
 HTMLPanel
DockLayoutPanel p = new DockLayoutPanel(Unit.EM);
p.addNorth(new HTML("north"), 2);
p.addSouth(new Button("Hello", 2);
p.addEast(new TextArea("Some text!"), 2);
p.addWest(new HTML("west"), 2);
p.add(buildMyBigWidgetList());
//add it to the HTML document
RootLayoutPanel rp = RootLayoutPanel.get(); rp.add(p);
Laying out content
Diversion about Standards Mode
• Standards Mode
o put <!Doctype html> on top
of your html page to be in
standards mode
• Some layout widgets in
GWT only work in Standards Mode
o FlowLayout
o DockLayoutPanel
o SplitLayoutPanel
GWT Events
• Events handle most all user-level interactions in GWT
o Mouse clicks
o Key presses
• Events also can be used to send information from one
widget to another
o much like PropertyChangeListener in Swing
o Instead of a PropertyChangeListener, use subclass of
ValueChangedEvent<T>
Button myButton = new Button("Do stuff");
myButton.addClickHandler(new ClickHandler(){
@Override
public void onClick(ClickEvent ce){
//react to button
}
});
ValueChangeEvent.fire(this, new MyValueChangeEvent());
Add an event listener
UiBinder
• In GWT, you can layout your pages programatically
o new FlowLayout().add(MyWidget), etc.
• Can also lay out pages using html, css, and xml
• The UiBinder is a way of doing layouts with xml, html,
and css, instead of java.
o This is actually doing layouts with html/css, instead of
javascript
<!DOCTYPE ui:UiBinder SYSTEM
"http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:u="urn:import:com.google.gwt.user.cellview.client">
<ui:style>
.important { font-weight: bold;}
</ui:style>
<g:HTMLPanel>
<div class="{style.important}">Here's an interesting
element!</div>
<div id="tableDiv"><u:CellTable ui:field="cellTable" /></div>
</g:HTMLPanel>
</ui:UiBinder>
Sample UiBinder
UiBinder(Continued)
• Why use UiBinder instead of programmatic layouts?
o Separates layout and aesthetic logic from functional
logic
 easier to change layout without affecting
functionality
 easier to apply CSS styles (especially with
ClientBundle)
o Faster
 programmatic logic is compiled to more javascript
than html
 UiBinder is compiled to more html than javascript
ClientBundle
• ClientBundle is a way of optimizing how the browser gets
static resources
o Images (ImageResource)
o CSS (CssResource)
o Text (TextResource)
• Groups together resources to make better use of the
browser cache
o moves resources from "never cache" category to the
"cache forever" category
Without a ClientBundle...
• Make a change to an image, or css
• do your users see it right away?
o maybe
o depends on their browser cache
With a Client Bundle...
• You add an ImageResource
• GWT compiler gives the image a unique hash
• you change the image later..
o GWT compiler assigns new image a new hash
o browsers now looking for a different image
o changes show up right away
More ClientBundle
• Not just for Images
o also for Css, static Text
• TextResource
o compiles in static text as a cached resource
o compiler can also easily internationalize the text from
properties files
o can be configured to download large text resources
from the server as needed
 allows rapid updates without a recompile/redeploy
of the website
Server Stuff
• Question: How do you make server calls in javascript
land?
Don't
• Don't ever, ever, ever use the internet. It's just a fad,
it'll pass.
Refresh the entire page
• It seems awfully lonely in here, without any users...
Use AJAX!
GWT RPC
• GWT defines an AJAX-based Remote Procedure Call
mechanism
o Define your Service interface
o Define your
Service's Asynchronous companion interface
o Implement your Service interface server side
o call your Asynchronous interface client side
GWT RPC(Continued)
• The GWT compiler will automatically generate
implementations of your Asynchronous interface that
uses AJAX to make the calls.
• No Such Thing as a synchronous server call
o GWT team decided that synchronous server calls are
A Bad Idea(TM), and so they aren't available
 They were right
public interface BeanServiceAsync{
void countBeans(String beanCounter,
AsyncCallback<Integer> beanCallback);
public interface BeanService{
int countBeans(String beanCounter);
public static class App {
private static final BeanServiceAsync ourInstance;
//some static initialization stuff here
}
}
public static BillingDataServiceAsync getInstance() {
return ourInstance;
}
void countMyBeans(){
AsyncCallback<Integer>callback = newAsyncCallback<Integer>(){
void onFailure(Throwable t){
handleFailure(t);
}
void onSuccess(Integer beanCount){
dealWithBeanCount(beanCount)
}
}
BeanService.App.getInstance().countBeans("myName",callback);
}
Using BeanServiceAsync
GWT RPC(continued)
• It is very easy to make an asynchronous server call in
GWT
o Good:
 your UIs are more responsive than with synchronous
calls
 less effort necessary
o Bad:
 It's easy to just make a server call whenever you
want
 Sometimes you may bring back more data than you
expect
Make too many RPC calls...
Browser limits how many
run concurrently
o the rest wait
o the page becomes
unresponsive
o Users hate you
o
Ask for too much data...
• Browser locks your page while
processing the javascript
• page becomes unresponsive
• Users hate you
GWT Compiler
• GWT is a compiler, plus frameworks(Already mentioned
this, right?)
o ......and??
o ....So what does the compiler do for me?
GWT Compiler(Continued)
• Does all kinds of things
o optimizes your java source code
o converts java source to javascript
o optimizes javascript
 including ClientBundles, UiBinder, embedded css,
etc.
 optimizes javascript for different browsers
Permutations
• Compiler compiles for each browser independently
o called Permutations of the compile
• If IE does a certain task in one way, and Chrome does it
another...
o IE permutation is compiled to use IE way, and never
use Chrome's way
o Chrome permutation 
always uses Chrome's way, and
never IE's
• Can even replace entire implementations specific to each
Browser
Steps in the GWT compile
• Steps in the GWT compile:
o optimize java source
o translate to javascript specific for each browser
o optimize resulting javascript
o perform code splitting(we'll get there)
Java optimization stage
• Optimizes Java source
o Dead code elimination
 removed unused code blocks
 replaces if(somethingTrue()&&anotherTrue()) with
if(true)
o staticifies non-overridden methods
 If method A is never overridden, then method A
becomes static
o inlines method calls
 not as aggressive here as the HotSpot compiler
 get too aggressive, it makes javascript bigger
Javascript stage
• Javascript optimizations
o Basically the same to the interpreted javascript as
what happens to the java
o static evaluation (same as Dead code elimination, but
cooler sounding)
o method inlining
 much more aggressive here since it only makes code
smaller
o global namespace mangling
 turns "Foo.bar()" into "f.b()"--if you're lucky
o global css namespace mangling
o code splitting
Codesplitting
• If you have a very big application...
o downloading app to webpage takes a long time
o javascript evaluation takes a long time
o your users get bored and leave before your site loads
• a solution..
o don't bring every piece of javascript down initially
o bring down only what you need, as you need it
Codesplitting(Continued)
• The compiler will separate out the javascript for you
o IF you tell it to
• Surround blocks of code which don't need to be
downloaded initially with GWT.runAsync()
• Compiler will recognize this
o moves everything which is connected to that point into
a different .js file which is downloaded later
• only stuff which is directly connected to the entry point
(no GWT.runAsync()) will be downloaded initially
o sometimes this can be surprising
public void runSomeCodeAsync(){
GWT.runAsync(new RunAsyncCallback(){
void onFailure(Throwable t){
//your javascript failed to load!
}
}
}
void onSuccess(){
runMyAppCode();
}
Codesplit
Story of your Compile
• It's often confusing to determine what pieces of code
are brought down in what split
o GWT compiler can generate a summary
 called the Story of Your Compile(SOYC)
 Tells you where code has been split
 what code is included in that split
 what code is in the initial download
 what code is "left over"
 code is left over if it fits in no split entirely
 this is downloaded initially.
Caveats about GWT Compiler
• GWT compiler is slooooow
o Each permutation takes time
 the compiler does a lot, and it does it repetitively
o permutations are easy to add
 add a new browser
 add a new language to compile for
o Codesplitting is nontrivial
 tends to add quite a bit of build time
• Not unusual to see full builds take 30 minutes, 1 hour, or
more
Caveats(Continued)
• You can speed up the compile
o Compile fewer permutations
o use the -draftCompile command line argument
o Distributed Compiler
 not really all the way there--you have to write some
glue code
Development mode
• Obviously can't develop very effectively like that
• GWT team introduced Development Mode to make up for
this
• Development Mode skips the compile stage and goes
straight to the browser
Development mode(Continued)
• Includes an embedded jetty server to run server code
• puts wrappers into javascript instead of actual code
o when you interact with the page...
 each action you take is sent to the embedded
server
 that server compiles enough javascript to perform
that action, and sends it back
• Can use debuggers with development mode for clientside javascript debugging
• to make a UI change take effect, only need to refresh,
not rebuild.
Development Mode(Continued)
• However...
o Development mode is not exactly the same as
production mode
 some bugs exist only in development
 some bugs exist only in production
 development mode is much slower than production
Best practices
• Use UiBinder
• Use ClientBundle
• Use codesplitting
o you would be amazed how much faster your app feels
• avoid excessive javascript
o javascript is usually slower than HTML
• Don't make too many server calls
• Remember your Java Best practices
• Be kind to your users
Third party tools
• Gin(http://code.google.com/p/google-gin/)
o like guice, but for GWT
 no interceptors though
• gwttime(http://code.google.com/p/gwt-time
o port of joda-time to GWT
 not perfect (kinda big)
 better than nothing
 needs to be revamped
• gwt-log(http://code.google.com/p/gwt-log/)
o log4j-style client side logging
o can be sent to the server!
Questions?
Contact
Twitter: @scottfines
Email: scottfines@gmail.com
LinkedIn
Download