gwt architecture best practices and lessons learned
DESCRIPTION
This are the slides from my GWT architectures talk at the JAX 2013TRANSCRIPT
p.g.taboada | pgt technology scouting GmbH
Google Web Toolkit
Architecture
Best Practices
Donnerstag, 25. April 13
Donnerstag, 25. April 13
http://gwtreferencelist.appspot.com
Donnerstag, 25. April 13
‣GWT Development
‣Basics
‣Structuring the UI
‣Communication
‣Scaling
Donnerstag, 25. April 13
Shift happened
Java development, JS deployment,
Async,RPC,
RIA/ single page,...
Donnerstag, 25. April 13
TextBox t = new TextBox();
RootPanel.get().add(t);
Donnerstag, 25. April 13
Browser Server
user action
full html response
full html response
full html response
user action
user action
Donnerstag, 25. April 13
Browser Server
event
first request
full html response
data
data request
data
data request
event
event
event
Donnerstag, 25. April 13
low level, generic toolkitDonnerstag, 25. April 13
let‘s build big thingsDonnerstag, 25. April 13
TextBox t0 = new TextBox();TextBox t1 = new TextBox();TextBox t2 = new TextBox();TextBox t3 = new TextBox();TextBox t4 = new TextBox();
VerticalPanel...SplitPanel...ScrollPanel
RootPanel.get().add(mainPanel);
Donnerstag, 25. April 13
Run, Forrest. Run!Donnerstag, 25. April 13
HopplaDonnerstag, 25. April 13
framework wizardry needed
Donnerstag, 25. April 13
‣GWT Development
‣Basics
‣Structuring the UI
‣Communication
‣Scaling
Donnerstag, 25. April 13
BE CAREFUL. GWT DEVELOPMENTIS COMPLICATED HOT NEW STUFF.
Donnerstag, 25. April 13
WELL, IT‘S NOT NEW...
Donnerstag, 25. April 13
THERE IS NOT A MOMENT TO LOOSETHERE IS NOT A MOMENT TO LOOSEJan 2000 Jan 2005
XHTML 1.0Jan 2000
HTML 4.0.1Dez 1999
CSS 2Mai 1998
HTML 4.0 updateApril 1998
XHTML 1.1Mai 2001
HTML 2.0November 1995
HTML 4.0Dezember 1997
Java EE 1.2Dez 1999
JDK 1.1Feb 1997
Internet Explorer 6Aug 2001
JDK 1.0Jan 1996
CSS 2.1Feb 2004 – Jun 2011
CSS level 2 revision 1, often referred to as "CSS 2.1", fixes errors in CSS 2, removes poorly supported or not fully interoperable features and adds already-implemented browser extensions to the specification. In order to comply with the W3C Process for standardizing technical specifications, CSS 2.1 went back and forth between Working Draft status and Candidate Recommendation status for many years.
J2SE 1.2Dez 1998
J2SE 1.3Mai 2000
CSS 1Dez 1996
HTML 3.2Januar 1997
Donnerstag, 25. April 13
nothing new hereDonnerstag, 25. April 13
nothing new here too
Jan 2007
Donnerstag, 25. April 13
how can I avoid this?Donnerstag, 25. April 13
don‘t public instance the singletons
Donnerstag, 25. April 13
event bus pleasehttp://jarrettws.blogspot.de/2010/05/public-transport.html
Donnerstag, 25. April 13
eventbus.fireEvent(NotificationEvent.info("Daten wurden erfolgreich gespeichert"
));
Donnerstag, 25. April 13
USE MVP!You will get used to it
Donnerstag, 25. April 13
presenter model
clientFactory
eventBus
panel
view
Donnerstag, 25. April 13
presenter
view interface
presenter interface
model
desktop view
tablet view mock viewDonnerstag, 25. April 13
public interface LoginView extends View {
void setPresenter(LoginView.Presenter currentPresenter);
void presetEmailFieldWith(String email);
void doShowApplicationMetadata(AppData params);
public interface Presenter extends LemniscusPresenter {
void userLoginWith(String username, String password);
void userDidAskForRegistrationPlace();
void userWantsToChangePassword(
int verificationCode, String userEmail, String
newPasswordToUse);
void userRequestedVerificationCodeForPasswordChange(String email);
}
}
Donnerstag, 25. April 13
public interface LoginView extends View {
void setPresenter(LoginView.Presenter currentPresenter);
void presetEmailFieldWith(String email);
void doShowApplicationMetadata(AppData params);
public interface Presenter extends LemniscusPresenter {
void userLoginWith(String username, String password);
void userDidAskForRegistrationPlace();
void userWantsToChangePassword(
int verificationCode, String userEmail, String newPasswordToUse);
void userRequestedVerificationCodeForPasswordChange(String email);
}
}
MyDesktopViewImpl extends Composite implements LoginView
Donnerstag, 25. April 13
public interface LoginView extends View {
void setPresenter(LoginView.Presenter currentPresenter);
void presetEmailFieldWith(String email);
void doShowApplicationMetadata(AppData params);
public interface Presenter extends LemniscusPresenter {
void userLoginWith(String username, String password);
void userDidAskForRegistrationPlace();
void userWantsToChangePassword(
int verificationCode, String userEmail, String newPasswordToUse);
void userRequestedVerificationCodeForPasswordChange(String email);
}
}
MyLoginPresenter extends AA... implements LoginView.Presenter
Donnerstag, 25. April 13
BUT ON IE 6 IT IS SO SLOW!
Donnerstag, 25. April 13
BUT ON IE 7 IT IS SO SLOW!
Donnerstag, 25. April 13
BUT ON IE 8 IT IS SO SLOW!
Donnerstag, 25. April 13
BUT ON IE 9 IT IS SO SLOW!
Donnerstag, 25. April 13
too many widgets ain‘t goodDonnerstag, 25. April 13
CREATE CUSTOM WIDGETS
don‘t extend FlextTable
don‘t extend VerticalPaneldon‘t extend SimplePanel
CREATE CUSTOM EVENTS
Donnerstag, 25. April 13
if you can, do it in CSS
@-webkit-keyframes redPulse { from { box-shadow: 0px 0px 2px #ff0033; } 50% { box-shadow: 0px 0px 10px #ff0033; } to
{ box-shadow: 0px 0px 2px #ff0033; }}
Donnerstag, 25. April 13
use CSS layout
<g:LayoutPanel styleName="{B.style.mainContent}"> <g:layer left="0" right="340px" top="0" height="50%"> <g:SimpleLayoutPanel styleName="{B.style.mainWidget}" addStyleNames="{B.style.termineGlow}"> <ux:DashboardTermineDataGrid ui:field="terminetable" styleName="{B.style.mainWidgetContent}" /> </g:SimpleLayoutPanel> </g:layer> <g:layer right="0" width="340px" top="0" height="50%"> <g:SimpleLayoutPanel styleName="{B.style.mainWidget}" addStyleNames="{B.style.finanzenGlow}"> <ux:KWStatsDataGrid ui:field="statstable" styleName="{B.style.mainWidgetContent}" /> </g:SimpleLayoutPanel> </g:layer> <g:layer right="0" left="0" bottom="0" height="50%"> <g:SimpleLayoutPanel styleName="{B.style.mainWidget}" addStyleNames="{B.style.uebersichtGlow}"> <ux:WartelisteDataGrid ui:field="wartelistetable" styleName="{B.style.mainWidgetContent}" /> </g:SimpleLayoutPanel> </g:layer></g:LayoutPanel>
Donnerstag, 25. April 13
Ray Ryan - lessons learnedDonnerstag, 25. April 13
‣GWT Development
‣Basics
‣Structuring the UI
‣Communication
‣Scaling
Donnerstag, 25. April 13
„just do it“ pattern
„View A“
„View B“
mainPanel.setWiget( aWidget );
mainPanel.setWiget( bWidget );
some action
Donnerstag, 25. April 13
hard to maintainDonnerstag, 25. April 13
history management
from day one!
back button and refresh as a
feature (not a catastrophe)
Donnerstag, 25. April 13
keep it stupid simple• use PLACES framework
for main level navigation
• if you really need to, nest activities for a second level. try not to.
• use dialogs for user input, showing data. dialogs are easily reused.
Donnerstag, 25. April 13
Once upon a time, a good designer does
good a good looking design...
‣ he will be using photoshop or dreamweaver‣ he will not use the
software‣ he will not build the
software‣ he will not maintain the
software
Donnerstag, 25. April 13
Donnerstag, 25. April 13
top menue bound to places framework
Donnerstag, 25. April 13
switching between places with fade in and out
Donnerstag, 25. April 13
teach user to wait until application is ready again
Donnerstag, 25. April 13
gives us enough time to load the required content
300ms out 500ms in
Donnerstag, 25. April 13
Komponents inside an
„activity“ fire non public,
custom events
Donnerstag, 25. April 13
datepicker sends KW
selected event
Donnerstag, 25. April 13
presenter may goto itself, view may be cached
Donnerstag, 25. April 13
STATELESS VIEW
URL contains EVERYTHING needed to rebuild view
user hits reload
GWT apps starts, activity
gets fired
presenter loads data
from server
view is back again
Donnerstag, 25. April 13
some actions don‘t require PLACE navigation at all
Donnerstag, 25. April 13
use POPUPS to stay ABOVE navigation
Donnerstag, 25. April 13
let POPUPS/ DIALOGS move slowly into view
pin POPUPS to one side of the
window
Donnerstag, 25. April 13
let POPUPS/ DIALOGS move slowly into view
pin POPUPS to one side of the
window
Donnerstag, 25. April 13
Don‘t move your user away from his
„PLACE“ unless you have to.Search DIALOG
slides in from right side, stays on TOP
Donnerstag, 25. April 13
Navigation must not hurt
• The application shown uses only 3 levels of navigation, DOES NOT NEED MORE
• PLACES used for bookmarkable entry points/ back button navigation consistency
• Activities should be STATELESS, to survive page reloads
• Learn from OTHERS
Donnerstag, 25. April 13
BEFORE YOU ADD THE LOGO TO THE TOP
HOW MANY PIXELS DO YOUR USERS HAVE? the designer or
marketing guy using photoshop is probably sitting in
front of a 27“ apple cinema
displayDonnerstag, 25. April 13
‣GWT Development
‣Basics
‣Structuring the UI
‣Communication
‣Scaling
Donnerstag, 25. April 13
Honor the A in AJAX
‣ Javascript does not block Get over it
‣ Latency is not a myth
‣ Results must not arrive in the call order
Donnerstag, 25. April 13
MARSHALLING / UNMARSHALLING IN JAVASCRIPT IS SLOW
Donnerstag, 25. April 13
BUILDING A GENERIC FRAMEWORK FORMARSHALLING/ UNSMARSHALLING DATA SUCKS
Donnerstag, 25. April 13
DON‘T BIND YOU NEXT 3 YEARS OF WORK AGAINST SOME COMMUNICATION PROTOCOLL
Donnerstag, 25. April 13
LOADING TOO MUCH DATA WILL ALWAYS HURT
Donnerstag, 25. April 13
GWT-RPC is a good solution if handled with care
SomeResult someMethodName(SomeParameter spo)
GWT-RPC binds many
methods into one interface
Interface Versioning
is a monstrous
thing
Donnerstag, 25. April 13
SomeResult someMethodName(SomeParameter spo)
the method names bind the requests to the result
typesafety all the way
Donnerstag, 25. April 13
USING GENERICS FOR TYPESAFETY, GET RID OF METHODS AND INTERFACES
Donnerstag, 25. April 13
<A extends Action<R>, R extends Result> R execute(A action);
now we just one interface with one method
typesafety all the way
Donnerstag, 25. April 13
command pattern
GOF Pattern
commonly used in Rich Clients
Donnerstag, 25. April 13
someAction
someResult
someActionHandler
Donnerstag, 25. April 13
someAction
someResult
someActionHandlerPOJOS
Donnerstag, 25. April 13
someAction
someResult
someActionHandlermultipleversions
someActionV2
someActionHandlerV2
Donnerstag, 25. April 13
someAction
someResult
someActionHandlermultipleversions
someActionV2
someActionHandlerV2
someResultV2
Donnerstag, 25. April 13
someAction
someResult
someActionHandler
GWT-RPC
client server
batchingcachingsecurity
cachingexception translationsecurity
GWT client
Donnerstag, 25. April 13
someAction
someResult
someActionHandler
RMI / HTTPInvoker
client server
batchingcachingsecurity
cachingexception translationsecurity
Java client
Donnerstag, 25. April 13
someAction
someResult
someActionHandler
JSON-servlet
client server
batchingcachingsecurity
cachingexception translationsecurity
Mobile client
Donnerstag, 25. April 13
batchAction
someAction1
batchActionHandler
someAction2
someAction3
batchResult
someResult1
someResult2
someResult3
client server
batching can be manual or
automatic
server executesactions in given order
Donnerstag, 25. April 13
BATCH EXECUTION ALLOWS FOR FINE GRAINED COMMANDS AND REUSE
Donnerstag, 25. April 13
toggleTerminMetadata
reloadDashboardTermine
BooleanResult
DataListResult<Termin>
Donnerstag, 25. April 13
toggleTerminMetadata
reloadTermin
BooleanResult
DataResult<Termin>
Donnerstag, 25. April 13
toggleTerminMetadata
loadMonthStats
BooleanResult
DataResult<MonthStats>
loadMonthTermine DataListResult<Termin>
Donnerstag, 25. April 13
‣GWT Development
‣Basics
‣Structuring the UI
‣Communication
‣Scaling
Donnerstag, 25. April 13
• Every client brings his own CPU power
• The client does the page rendering
• GWT provides different ways to reduce number of requests even more
• The server must „only“ authenticate the user and provide the data, perform the actions requested by the client
GWT scaling is easy...
Donnerstag, 25. April 13
WHAT CAN POSSIBLY GO WRONG?
Donnerstag, 25. April 13
LETS TALK HIGH TRAFFIC...HIGH TRAFFIC IS WHEN ONE SERVER IS NOT ENOUGH
Donnerstag, 25. April 13
• Bandwith issues
• Connection pool bottlenecks
• Thread pool bottlenecks
• CPU bottlenecks caused by reflection API calls
• High JVM garbage collection CPU usage
HIGH TRAFFIC PROBLEMS
Donnerstag, 25. April 13
NOT REALLY GWT PROBLEMS,BUT WHAT CAN WE DO?
Donnerstag, 25. April 13
TX TX
TX TX
TX
TX
TX TX
TX
TXavoid „tx collisions“
Donnerstag, 25. April 13
TX TX TX TX
TX
TXTX
TX TX
TX
TX
TXTX
TX
TX
load small portions of data, do it often
Donnerstag, 25. April 13
Donnerstag, 25. April 13
IMPLEMENT REAL LOAD BALANCINGEACH REQUEST GOES TO THE NEXT AVAILABLE SERVER
Donnerstag, 25. April 13
• Don‘t stick a session to a server.
Why send a user over and over again to a possible overloaded server?
• Don‘t store anything on the HTTP session. Let the load balancer balance the load.
• Session replication is expensive and does not scale well
SCALING HOW-TO
Donnerstag, 25. April 13
Webserver
Webserver
LB Webserver
Webserver
Webserver
Session Cache
STATELESS WEB
Webserver
Donnerstag, 25. April 13
Session Cache
Session state should not change, just expire
Session state could contain user id, client id, session id, user roles
If session cache becomes bottleneck, use distributed cache, eg. memcached
Session Cache
Session Cache
Donnerstag, 25. April 13
Thanks!Donnerstag, 25. April 13