"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
Google Web Toolkit for the Enterprise Developer - JBoss World 2009
1. Google Web Toolkit (GWT) for
the Enterprise Developer
Fred Sauer
Developer Advocate, Google
September 2009
fredsa@google.com
1 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
2. Agenda
30 second survey
What to do about questions?
Mission & Introduction
Know your toolkit
Tips
Q&A
2 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
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."
3 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
4. GWT is all about
Productivity for developers
Language, IDEs, tools, libraries
People, ecosystem
Performance for your users
'Perfect' caching
Whole program optimization
Better than practical hand written code
4 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
5. GWT Browser-Proofs Your JavaScript Code...
IE
Firefo
x
i
Safar e
m
Chro
Opera
Wednesday, September 2, 2009
6. Deferred Binding
Firefox Webkit (Safari) Opera IE
Typical portable 2876 ms 1276 ms 2053 ms 4078 ms
setInnerText()
textContent=... - 908 ms 1386 ms -
innerText=... 2477 ms 918 ms 1520 ms 2469 ms
DOM manipulation 7148 ms 1997 ms 4836 ms 14800 ms
Improvement 14% 29% 32% 39%
6 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
7. Deferred Binding at Runtime
7 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
8. Deferred Binding at Runtime
8 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
9. More than just a compiler
9 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
10. History just works
10 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
11. Rich Text Area
11 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
13. GUI Editing
13 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
14. Simple, Powerful RPCs
interface SpellService extends RemoteService {
/**
* Checks spelling and suggests
* alternatives.
* @param the word to check
* @return the list of alternatives
*/
String[] suggest(String word);
}
14 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
15. GWT 2.0 operating modes
Development Mode (Hosted Mode)
All about productivity
Java + JavaScript
JVM Debugging
Now in any supported browser
Production Mode (Web Mode)
All about performance
Compiled, Pure JavaScript
15 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
16. 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!)
U E
T R
O T
N
16 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
17. Development Mode
In any supported browser
FF, Safari, IE6/7/8, …
On your machine
On remote machines
In another VM
Using a callback address:port
http://mymachine:8080/Foo.html?gwt.codesvr=…
17 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
18. Development Mode
Web Code
Server Server
Java Virtual Machine
18 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
19. Google Plugin for Eclipse
19 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
20. 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
20 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
21. RTL, I18N, L10N, A11Y
21 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
22. Locale support
<!-- Always use utf-8 -->
<meta http-equiv="content-type" content="text/
html;charset=utf-8" />
<!-- Compile time locales -->
<extend-property name="locale"
values="fr_CA,de"/>
<set-property-fallback name="locale"
value="fr_CA"/>
// Runtime locales
LocaleInfo.getAvailableLocaleNames();
22 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
24. Developer guided code splitting
GWT.runAsync()
Time
HTML JS Running
Without splitting
With splitting
Speedup
HTML JS Running! Running!! Running!!!
JS JS
24 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
25. Developer guided code splitting
GWT.runAsync()
Time
HTML JS Running
Without splitting
With splitting
Speedup
HTML JS Running! Running!! Running!!!
JS JS
25 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
26. Manual code splitting - Don't try this at home
26 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
27. Developer guided code splitting
GWT.runAsync()
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() {
Window.alert("Hello, AJAX");
doMoreStuff();
}
public void onFailure(Throwable caught) {
Window.alert("Code download failed");
}
});
27 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
28. RunAsync package pattern - Gateway class
package 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
}
…
28 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
29. RunAsync package pattern - Gateway class
…
// Async interface to obtain an
// instance of AddressBook
public interface Callback {
void onCreated(AddressBook addressBook);
void onCreateFailure(Throwable e);
}
…
29 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
30. 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);
}
});
}
}
30 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
31. Story of Your Compile (SOYC)
-C
31 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
32. SOYC
The Story of Your Compile:
Reading the Tea Leaves of the GWT
Compiler for an Optimized Future
Lex Spoon and Bruce Johnson
May 28, 2009 @ Google I/O
http://code.google.com/events/io/sessions/
StoryCompilerGwtCompiler.html
32 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
34. Using JSON
// 1. Server responds
{"firstName": "Fred", "lastName": "Sauer", … }
// 2. Client parses
p = safeJsonParse(responseText);
// or Client evaluates (Danger, Will Robinson!)
p = eval(responseText);
…
34 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
35. Using JSON
// Brittle
var greeting = 'Hello, ' + p.firstName + ' ' +
p.lastName;
// Additional payload for user to download
function getName(p) {
return p.firstName + ' ' + p.lastName;
}
// Additional method invocation overhead
var greeting = 'Hello, ' + getName(p);
35 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
36. The amazing disappearing code trick
Using 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; }-*/;
…
36 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
37. The amazing disappearing code trick
public class Person extends JavaScriptObject {
…
// This method is about to disappear as well!
public String getDisplayName() {
return getFirstName() + " " + getLastName();
}
}
37 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
38. The amazing disappearing code trick
…
// Go ahead, use your type-safe abstractions
// You get to keep your wrapper classes
Person person;
// Also keep your convenience methods
String name = person.getDisplayName();
// GWT performs disappearing trick
var name = p.firstName + ' ' + p.lastName;
38 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
39. Overlay Types++
Client/server agnostic code using Person
(e.g. unit tests, business logic)
JavaScriptObject Person
(Class) (Interface)
Person_ClientImpl Person_ServerImpl
(JSO + Interface) (POJO or whatever)
39 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
40. Responsiveness matters
0.1 seconds perceived as instantaneous
1 second maintains the feeling that a single task
is being carried out
10 seconds limit for keeping user’s attention
40 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
41. Roundtrips are deadly
1 round trip for TCP connection setup
(1 round trip for HTTP redirect?)
1 round trip for each HTTP request
$ ping ohare.com
PING ohare.com (70.142.247.22): 56 data bytes
64 bytes from 70.142.247.22: icmp_seq=0 ttl=113 time=54.689 ms
64 bytes from 70.142.247.22: icmp_seq=1 ttl=113 time=55.500 ms
64 bytes from 70.142.247.22: icmp_seq=2 ttl=113 time=54.728 ms
41 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
42. Reducing round trip time
Use HTTP Expires and Cache-Control headers
Use GWT 'Perfect Caching'
Cache 'forever' - your entire app and all its resources
Bundle, bundle, bundle
Enable HTTP Pipelining
Use multiple hostnames
Defeat browser's two connection limit
Watch out for DNS lookup overhead though
42 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
43. Know your HTTP Headers
<!-- See RFC 2616. Here's an example:
Expires: Thu, 02 Sep 2010 03:21:55 GMT
Cache-Control: public, max-age=31536000
-->
<Files *.cache.*>
ExpiresDefault "now plus 1 year"
</Files>
<Files *.nocache.*>
ExpiresDefault "access"
</Files>
43 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
44. Sprites for free (ImageBundle)
20,558 bytes
11 separate images
6,824 bytes
1 bundled image
∑ Separate Bundled
44 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
45. 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();
}
45 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
46. Injecting / inspecting resources at compile-time
interface MyBundle extends ClientBundle {
public static final MyBundle INSTANCE =
GWT.create(MyBundle.class);
@Source("app_config.xml")
TextResource appConfig1();
@Source("wordlist.txt")
ExternalTextResource wordlist();
…
46 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
47. Injecting / inspecting resources at compile-time
interface MyBundle extends ClientBundle {
@Source("myCursor.cur")
DataResource myCursor();
}
MyBundle.INSTANCE.myCursor().getUrl();
http://localhost:8080/foo/
B349934EA27D6EFFD949B88E6A116ED7.cache.cur
data:content/unknown;base64,c2FkIGprZ2xkZdqZGZrb
CBnamtkZmxnIGRma2xnaiBrZGxmZ2prbGRmamcga2xkaiBna
2w7ZGZqZy…IGRmamtsw7ZGZqZyBrbGRmZ2ogZGtsO
47 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
48. Injecting / inspecting resources at compile-time
interface 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();
…
48 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
49. Injecting / inspecting resources at compile-time
interface MyBundle extends ClientBundle {
…
@Strict // or @NotStrict
@Source("address_book.css")
CssResource addressBookCSS();
}
49 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
50. Compile time CSS awesomeness
http://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
50 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
52. Linkers - orchestrating compiler output
xs
sso
Out of the box std
3rd party
Ω µ
∆ ¶
52 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
53. Single Script (sso) Linker
SingleScriptLinker
yourpage.html
<module>.nocache.js
53 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
54. Cross site (xs) Linker
XSLinker
yourpage.html
<module>.nocache.js
<md5>.cache.js
54 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
55. Standard (std) Linker
IFrameLinker
yourpage.html
<module>.nocache.js
<iframe ...
<md5>.cache.html
55 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
56. Generators
GWT.create(…)
What code will
your code write?
56 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
57. Corporate Gadgets
57 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
58. Making gadgets
@ModulePrefs(
title = "Hello World!",
directory_title = "My first gadget",
screenshot = "gadget.png",
thumbnail = "thumb.png",
…
height = 210)
public class HelloGadget
extends
Gadget<HelloPreferences>
{
…
58 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
59. Making gadgets
@ModulePrefs(…)
public class HelloGadget extends
Gadget<HelloPreferences> {
public void onModuleLoad() { /* ... */}
protected void init(
final HelloPreferences prefs) {
…
}
}
59 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
60. Making gadget preferences
public interface MealPreferences extends
UserPreferences {
@PreferenceAttributes(
display_name = "Vegetarian",
default_value = "false")
BooleanPreference noMeat();
}
60 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
61. Expecting the unexpected in Development
public void onModuleLoad() {
Log.setUncaughtExceptionHandler();
// This isn't going to help us now
DeferredCommand.addCommand(new Command() {
GWT.setUncaughtExceptionHandler(…);
public void execute() {
onModuleLoad2();
//}Your initialization code goes wrong here :(
});
} // Cross your fingers
}
private void onModuleLoad2() {
// Your module initialization code goes here
}
61 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
62. Expecting the unexpected in Development Mode
// Hyperlink your stack traces
Throwable#printStrackTrace()
62 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
63. 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");
63 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
64. Make the compiler output human readable
// Production Mode (-style OBF)
Ee='area=';function nc(){$wnd.alert(Ee+(u(new
q),Hb($doc))*Gb($doc))}
// -draftCompile -style PRETTY
function $onModuleLoad() {
$showArea(getClientWidth(),getClientHeight());
}
function $showArea(width, height){
alert_0('area=' + width * height);
}
64 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
65. 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" />
65 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
66. Expecting the unexpected in Production Mode
Even with -style OBF
Server side symbol maps, e.g.
xQ() -> MyClass.myOriginalJavaMethod()
66 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
67. Expecting the unexpected in Production Mode
You still get stack traces in JavaScript!
Throwable#getStackTrace()
67 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
68. Projects you should know
http://code.google.com/p/google-web-toolkit-incubator/
Ideas: widgets, libraries, resources
http://code.google.com/p/gwt-google-apis/ (GALGWT)
Gears, Gadgets, AJAX Search, Maps,
Visualization, Language, AjaxLoader
http://code.google.com/p/gwt-exporter/
68 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
69. Shameless plugs (gwt-dnd, gwt-log, gwt-voices)
69 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
70. 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 QA
Button searchButton = new Button();
searchButton.ensureDebugId("srch");
70 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
71. Watch the compiler optimize away your code
-Dgwt.jjs.traceMethods=foo.Bar.onModuleLoad
public class ShapeExample implements EntryPoint {
public void onModuleLoad() {
Shape s = getShape();
Window.alert("Area is " + s.getArea());
}
public static abstract class Shape {
public abstract double getArea();
}
private Shape getShape() { return shape; }
private final Shape shape = new SmallSquare();
public static abstract class Square extends Shape {
public double getArea() { return getSideLength() * getSideLength(); }
public abstract double getSideLength();
}
public static class SmallSquare extends Square {
private static final double SIDE_LEN_SMALL = 2;
public double getSideLength() { return SIDE_LEN_SMALL; }
}
}
71 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
72. Watch the compiler optimize away your code
-Dgwt.jjs.traceMethods=foo.Bar.onModuleLoad
---------------------------
CleanupRefsVisitor:
DeadCodeVisitor:
InliningVisitor:
TightenTypesVisitor:
RewriteCallSites:
FinalizeVisitor:
JAVA INITIAL:
---------------------------
public void onModuleLoad(){
static final void $onModuleLoad(ShapeExample
final void onModuleLoad(){
this$static){
final ShapeExample$Shape s = this.getShape();
ShapeExample$Shape s = this.getShape();
this$static.shape;
final ShapeExample$Shape
Window.alert("Area is " +ss.getArea());
ShapeExample$SmallSquare s = ShapeExample.
4.0"); this$static.getShape();
= ShapeExample.
this$static.shape;
((this
$static.shape));
$getShape(this$static); 4.0");
} Window.alert("Area is " + s.getArea());
((2.0)) * ((2.0)));
ShapeExample$SmallSquare.
((ShapeExample$SmallSquare.
ShapeExample$Square.
$getSideLength(s) * is " + s.getArea());
$getArea(s));
} Window.alert("AreaShapeExample$SmallSquare.
$getSideLength(s));
$getSideLength(s))));
}
}
72 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
73. System properties you should know
(GWT 1.7 and prior)
// Hosted mode just closes
// when you tell it to (e.g. ALT-F4)
-Dgwt.shell.endquick=
73 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
74. 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
74 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
75. Compiler arguments you should know
// Story of your compile
-soyc
// Symbols maps, SOYC reports, RPC info
-exta stuff
-logLevel
// GWT Compiler argument!
-ea
75 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
77. RPC log <module>.rpc.log
====================================
Types potentially sent from browser:
====================================
Reachable types computed on: Thu Jul 23 14:38:43
PDT 2009
com.google.gwt.user.client.rpc.IncompatibleRemot
eServiceException
Path '…' is reachable as a subtype of type '…'
Started from '…'
77 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
78. Hacks you should know
class Safe {
private static int secret() {
return 42;
}
}
class Thief {
public native int breakIn() /*-{
return @Safe::secret()();
}-*/;
}
78 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
79. Be prepared
Removing everything @deprecated for GWT 2.0
79 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009
80. 80 JBoss World 2009 | Fred Sauer
Wednesday, September 2, 2009