sf jug - gwt can help you create amazing apps - 2009-10-13
DESCRIPTION
TRANSCRIPT
1
Google Web ToolkitCan help you create amazing apps
Fred SauerDeveloper [email protected]: @fredsa
San Francisco Java User GroupOct 13, 2009
2
Agenda
Introduction
Selecting a language
Feature tour
Developer productivity
Compiler magic
Need for speed
Q&A
3
Google Web Toolkit
Write
Core Java APIs
Widgets
Libraries
Java IDEs
Debug
JVM Debugging
Development Mode
A real browser
Developer Productivity
Optimize
GWT Compiler
Image Bundle (Sprites)
CSS Magic
End User Performance
Run
Desktop
Mobile
Online/Offline
Gadgets
4
May 2006 GWT 1.0 Launch at JavaOne
Aug 2008 GWT 1.5 Java 5 language support
Apr 2009 GWT 1.7 Dedicated IE8 support
Fall 2009 GWT 2.0 LOTS of interesting stuff
3+ years in review
5
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."
6
Focus
Productivity for developers
Language, IDEs, tools, libraries
People, ecosystem
Performance for your users
'Perfect' caching
Whole program optimization
Better than practical hand written code
7
No plugins required
VML Flash
Silverlight
8
What we don't want
9
GWT Browser-Proofs Your JavaScript Code...
IE
Firefox
Safari
Chrome
Opera
10
Deferred Binding
14800 ms4836 ms1997 ms7148 msDOM manipulation
2469 ms1520 ms918 ms2477 msinnerText=...
-1386 ms908 ms-textContent=...
4078 ms2053 ms1276 ms2876 msTypical portable setInnerText()
IEOperaWebkit (Safari)
Firefox
Improvement 39%32%29%14%
11
A More Powerful Web, Made Easier
12
Eating our own dogfood
12
15
Selecting a language
16
Rich ecosystem of tools and libraries
+ + =
17
Code completion and javadoc
18
Can you find the bug?
Hint: JavaScript is a dynamic language
19
Java is a static language
Catch errors at compile time
20
Feature tour
21
Pluggable Architecture
22
More than just a compiler
Development Mode
23
Sprites for free
20,558 bytes
6,824 bytes
11 separate images
1 bundled image
28
History just works
29
Rich Text Area
30
RTL, I18N, L10N, A11Y
31
Widget Libraries
• GWT (http://code.google.com/webtoolkit/)
• Incubator (http://code.google.com/p/google-web-toolkit-incubator/)
• Smart GWT (http://code.google.com/p/smartgwt/)
• GWT-Ext (http://code.google.com/p/gwt-ext/)
• Vaadin (IT Mill Toolkit) (http://vaadin.com/)
• GWT mosaic (http://code.google.com/p/gwt-mosaic/)
• Ext GWT (http://extjs.com/products/gxt/)
• Advanced GWT Components (http://advanced-gwt.sourceforge.net/)
34
Shameless plugs for:gwt-dnd, gwt-log, gwt-voices
35
Developer productivity
for you
36
GWT 2.0 operating modes
Development Mode (Hosted Mode)
All about productivity
Java + JavaScript
Now in any supported browser
Production Mode (Web Mode)
All about performance
Compiled, Pure JavaScript
37
Development Mode (Hosted Mode)
JVM debugging
Server & Client code in the same IDE
Step in / over / out
Introspect & modify variables
Hot swap code (ignore the IDE warning!)
NOT TRUE
38
Java Virtual Machine
Development Mode
Code Server
Web Server
Duke, the Java mascotCopyright © Sun Microsystems Inc., all rights reserved.
39
Google Plugin for Eclipse
40
Eclipse plugin highlights
Extensive JSNI support
RPC sync/async quick fixes
Launch configurations
GWT JUnit tests
Contributor SDKs (gwt-user, gwt-dev-<platform>)
Development Mode (GWT 2.0)
Hosted Mode (GWT 1.7)
Constantly improving; check back often
41
GWT Debugging in the browser
42
Complete Java development stack
43
Developer productivity
on larger projects
44
Do or do not. There is no try.
Test, test, test
JUnit, CI, TDD
Selenium, WebDriver, enableDedugId
http://mymachine:8080/Foo.html?gwt.codesvr=…
Code coverage
Logging
http://code.google.com/p/gwt-log/; incubator logging
45
Do or do not. There is no try.
gwt-api-checker
Design
EventBus, MVP, embrace asynchrony
Separation & specialization
CSS, HTML, Java/JavaScript; UiBinder; MVP
46
Testing & TDD tools your should know
GWTTestCase extends UnitTest
GWTMockUtilities - neutralizing GWT.create()
FakeMessagesMaker
Lightweight metrics
http://code.google.com/p/google-web-toolkit/wiki/LightweightMetricsDesign
47
Modules you should know
<!-- Selenium, WebDriver, etc. --><inherits name="com.google.gwt.user.Debug" /><set-property
name="gwt.enableDebugId" value="true" />
// Setup my ids for QAButton searchButton = new Button();searchButton.ensureDebugId("srch");
48
Compiler arguments you should know
// Story of your compile-soyc
// Symbols maps, SOYC reports, RPC info-extra stuff
-logLevel
// Note: use as a GWT Compiler argument!-ea
49
-extra files you should know
stuff/…/…GreetingService.rpc.logstuff/…/rpcPolicyManifest/manifest.txtstuff/…/soycReport/splitPoints0.xml.gz
stuff/…/symbolMaps/04065D…5D6433CF.symbolMapstuff/…/symbolMaps/24B10B…3859D5C9.symbolMapstuff/…/symbolMaps/2814EF…CF2746BA.symbolMapstuff/…/symbolMaps/32793E…8754FAC1.symbolMapstuff/…/symbolMaps/C23998…9827C30B.symbolMap
50
Collaboration hints you should know
Source control, use svn:ignore
war/WEB-INF/lib/<sdk-jars>
war/WEB-INF/classes
war/<module-name>
OS/platform browser issues / setup, code formatting
trunk/gwt/eclipse/README.txt
Eclipse, Checkstyle
Prefs: Java Editor -> Save Actions
51
Project Organization
war/ layout
Multiple modules, single compile, single script
Java package naming conventions
client
server
rebind
model
52
Configuration parameters you should know<extend-configuration-property
name="rpc.blacklist"value="com.foo.myapp.client.WidgetList" />
<extend-configuration-propertyname="rpc.blacklist"value="com.foo.myapp.client.TimerList" />
…
53
System properties you should know
// Specify benchmark output directory-Dcom.google.gwt.junit.reportPath=…
// watch the compiler optimize a method-Dgwt.jjs.traceMethods=foo.Bar.onModuleLoad
54
Compiler arguments you should know
// Human readable code-style PRETTY
// fast (for development)-draftCompile
// Compile N permutations in parallel// (N = number of cores)-localWorkers=N
55
RunAsync package pattern - Gateway classpackage com.foo.client.addressbookasync;
public class AddressBook { // Can't construct directly private AddressBook() { }
// Only callable once you have an instance public show() { // use package restricted code here }
…
56
RunAsync package pattern - Gateway class …
// Async interface to obtain an // instance of AddressBook public interface Callback { void onCreated(AddressBook addressBook); void onCreateFailure(Throwable e); }
…
57
RunAsync package pattern - Gateway class … public static void get(final Callback cb) { GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { cb.onCreated(new AddressBook()); } public void onFailure(Throwable e) { cb.onCreateFailure(e); } }); }}
58
Compiler magic
59
GWT quote to remember
“The fastest code is thatwhich does not run.”
Joel WebberGWT co-creator
60
Conventional and non-conventional
Java transformations
Dead-code elimination
Method inlining
Constant folding & propagation
JavaScript transformations (gzip motivated)
Method reordering
Argument renaming
61
EXPERIMENTAL arguments you should know// Don't care what Class#getName() returns?-XdisableClassMetadata
5% - 10% script reduction
Showcase metadata before
Showcase metadata after
62
EXPERIMENTAL arguments you should know// In a real-world (very large) Google app...// 1% script size reduction// 10% faster in performance-sensitive code-XdisableCastChecking
try { ((Quacker) animal).quack();} catch (ClassCastException c) { Window.alert("Found a non-quacker");}
63
Need for speed
64
Speed matters
perceived as instantaneous.
maintains the feeling that a single task is being carried out.
limit for keeping user’s attention.
0.1 seconds
1 second
10 seconds
65
Another reason speed matters
2. UIChanges
3. UserLearns
1. UserAction
Performance for your users
66
GWT Helps Apps Startup More Quickly
26-Nov 29-Apr 18-Jun 28-Jul 12-Sep 27-Oct 24-Dec 16-Mar
Siz
e of
Initi
al J
avaS
crip
t Dow
nloa
d (K
B)
375
750
1125
1500
0
7x Decrease InInitial Download Sizewith runAsync()
1400 KB
200 KB
67
Developer guided code splitting
68
Developer guided code splitting
69
Manual code splitting - Don't try this at home
69
70
Developer guided code splitting
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() { … }
public void onFailure(Throwable caught) { … }
});
71
Story of Your Compile (SOYC)
-C
72
Disappearing code
that just works
73
JSON - JavaScript Object Notation
{ "firstName": "Fred", "lastName": "Sauer", "contactInfo": { "email": "[email protected]", … } "likes": [ "Open Source", "GWT", "Chocolate" ]}
74
Using JSON
// 1. Server responds{"firstName": "Fred", "lastName": "Sauer", … }
// 2. Client parsesp = safeJsonParse(responseText);
// or Client evaluates (Danger, Will Robinson!)p = eval(responseText);
…
75
Using JSON
// Brittlevar greeting = 'Hello, ' + p.firstName + ' ' + p.lastName;
// Additional payload for user to downloadfunction getName(p) { return p.firstName + ' ' + p.lastName;}
// Additional method invocation overheadvar greeting = 'Hello, ' + getName(p);
76
The amazing disappearing code trickUsing JSO Types
// This class is about to disappear!
public class Person extends JavaScriptObject {
// assume 'this' has 'firstName' property public native String getFirstName() /*-{ return this.firstName; }-*/;
public native String getLastName() /*-{ return this.lastName; }-*/;
…
77
The amazing disappearing code trick
public class Person extends JavaScriptObject {
…
// This method is about to disappear as well! public String getDisplayName() { return getFirstName() + " " + getLastName(); }
}
78
The amazing disappearing code trick
…// Go ahead, use your type-safe abstractions
// You get to keep your wrapper classesPerson person;
// Also keep your convenience methodsString name = person.getDisplayName();
// GWT performs disappearing trickvar name = p.firstName + ' ' + p.lastName;
79
ClientBundle
80
Sprites for free (ImageBundle)
public interface MyDialogImages extends ImageBundle {
// Look for 'saveButton.{png|jpg|gif|bmp}' AbstractImagePrototype saveButton();
AbstractImagePrototype okButton();
@Resource("com/foo/myapp/btn_cancel.png") AbstractImagePrototype cancelButton();}
81
Injecting / inspecting resources at compile-timeinterface MyBundle extends ClientBundle {
public static final MyBundle INSTANCE = GWT.create(MyBundle.class);
@Source("app_config.xml") TextResource appConfig1();
@Source("wordlist.txt") ExternalTextResource wordlist();
…
82
Injecting / inspecting resources at compile-timeinterface MyBundle extends ClientBundle { @Source("myCursor.cur") DataResource myCursor();}MyBundle.INSTANCE.myCursor().getUrl();
http://localhost:8080/foo/B349934EA27D6EFFD949B88E6A116ED7.cache.cur
data:content/unknown;base64,c2FkIGprZ2xkZdqZGZrbCBnamtkZmxnIGRma2xnaiBrZGxmZ2prbGRmamcga2xkaiBna2w7ZGZqZy…IGRmamtsw7ZGZqZyBrbGRmZ2ogZGtsO
83
Injecting / inspecting resources at compile-timeinterface MyBundle extends ClientBundle { …
@Source("arrow.png") // locale sensitive! @ImageOptions(flipRtl = true) ImageResource pointer();}
MyBundle.INSTANCE.pointer().getUrl();MyBundle.INSTANCE.pointer().getWidth();MyBundle.INSTANCE.pointer().getHeight();…
84
Injecting / inspecting resources at compile-timeinterface MyBundle extends ClientBundle {
…
@Strict // or @NotStrict @Source("address_book.css") CssResource addressBookCSS();
}
85
Compile time CSS awesomenesshttp://code.google.com/p/google-web-toolkit/wiki/CssResource
@def small 1px; /* Constants */
@if user.agent safari gecko1_8 { … }@if locale en { … }
@noflip { … } /* no automatic left/right swap */
@external
91
Expecting the
unexpected
92
Expecting the unexpected in Developmentpublic void onModuleLoad() {
// This isn't going to help us now GWT.setUncaughtExceptionHandler(…);
// Your initialization code goes wrong here :(
// Cross your fingers
}
public void onModuleLoad() { Log.setUncaughtExceptionHandler(); DeferredCommand.addCommand(new Command() { public void execute() { onModuleLoad2(); } });
}private void onModuleLoad2() { // Your module initialization code goes here}
93
Expecting the unexpected in Development Mode// Hyperlink your stack tracesThrowable#printStrackTrace()
94
Expecting the unexpected in Development Mode// Logging with zero overhead in production mode<inherits
name="com.allen_sauer.gwt.log.gwt-log-DEBUG"/>
Log.debug("This is a 'DEBUG' test message");
96
Expecting the unexpected in Production Mode<inherits name="compiler.emulatedStack" />
<set-configuration-property name="compiler.emulatedStack.recordLineNumbers" value="true" />
<set-configuration-property name="compiler.emulatedStack.recordFileNames" value="true" />
98
Expecting the unexpected in Production ModeYou still get stack traces in JavaScript!
Throwable#getStackTrace()
99
- Development Mode
- Declarative UI (UiBinder)
- Developer Guided Code Splitting-ClientBundle
- SOYC
Roadmap
Fall 2009
100
Thank you
Read morehttp://code.google.com/webtoolkit/
Contact infoFred Sauer
Developer Advocate
Twitter @fredsa
Questions?