GWT Enterprise Patterns
●
Spencer Gibb
●
Sr. Software Engineer for LDS Church
●
12 Years Experience
–
E-commerce
–
Defense
–
Contractor
●
http://spencer.gibb.us
●
Heavy Google User
–
Google Apps for your Domain, App Engine, GWT
●
General Open Source Software User
If you remember nothing else...
●
Get browser history right, and get it right early
●
Use an Event Bus to fight spaghetti
●
DI + MVP
●
Dependency Injection
●
Model / View / Presenter
Three major themes
●
Embrace asynchrony
●
Always be decoupling
●
Strive to achieve statelessness
Event Bus
●
Everything is on the Event Bus
●
RPC
●
Results
●
Failures
●
Locations (Browser History)
●
View Presenter communication
●
Simpler Event code than GWT Events
EventBus GWT Event Style
public class MyEvent extends GwtEvent<MyEventHandler> {
public interface MyEventHandler extends EventHandler {
void onAddNewIssue(MyEvent event);
}
private static Type<MyEventHandler> TYPE =
new Type<MyEventHandler>();
public MyEvent() { }
public final Type<MyEventHandler> getAssociatedType() {
return TYPE;
}
protected void dispatch(MyEventHandler handler) {
handler.onAddNewIssue(this);
}
}
EventBus Simplified Events
●
Type Safe
●
getTypeObject is the key used by EventBus to
get handlers for particular event types rather
than the static TYPE.
public class MyEvent extends Event<String, MyEvent.Handler> {
public static abstract class Handler
extends EventHandler<MyEvent> {
public Object getTypeObject() {
return MyEvent.class;
}
}
public MyEvent(String data) {
super(data);
}
}
Command Pattern
●
GWT RPC Service implementation
DefaultDispatch
●
Commands
●
class SayHelloCommand implements
Command<HelloResults>
●
Results
●
class HelloResult implements Result
●
Reusable Result Objects
–
StringResult, LongResult etc...
Command Pattern Cont.
●
Command Handler
●
SayHelloCommandHandler implements
CommandHandler<SayHelloCommand, SayHelloResult>
●
One to one with a command/result pair
–
SayHelloResult execute(SayHelloCommand cmd)
●
Multi-Command Handler
●
Multiple commands in One class
●
Lose some type safety, gain flexibility
Class Handler extends MultiCommandHandler {
SayHelloResult hello(SayHelloCommand cmd) {}
GetHelloResult getHello(GetHelloCommand cmd) {}
}
Model, View, Presenter - MVP
●
Presenter defines View interface via GWT Has*
interfaces
●
Communication between View and Presenter is
via GWT Has* interfaces or Events
●
RPC done in Presenter
●
NO
GUI in Presenter
MVC
MVP
Presenter
●
Coordinates Events
●
Adds external behavior to view
●
RPC
●
Intra-app events
HelloPresenter extends
AbstractPresenter <HelloPresenter.View, CommandEventBus> {
class View extends WidgetView {
HasText getName();
//...
}
//...
}
View
●
All GUI work done here
●
UI Binder or widgets directly
●
Respond to Events on the EventBus
HelloViewImpl extends
AbstractWidgetView <CommandEventBus>
implements HelloPresenter.View {
HasText name;
//...
}
//...
}
Locations (GWT History)
●
Bookmarkability and browser back button
●
http://localhost/app#hello/joe
●
Gmail style positional parameters
●
All done via the event bus
●
Must be bootstrapped in EntryPoint
●
eventBus.changeLocation(“hello”, “fred”)
●
eventBus.add(new Location.Handler(“hello”) {
public void handle(Location location) {
location.getParam(0); }}
Dependency Injection in GWT
●
Gin on Guice (Compile time injection)
●
@Inject constructor injection
●
Event Bus in to Views and Presenters
●
Views in to Presenters
●
Default Presenter for Entry Point
●
View view = injector.getHelloPresenter().getView();
RootLayoutPanel.get().add(view.getImpl());
Integration
●
Appengine / JDO
●
JPA
●
Spring
●
Future GWT integration!
●
Guice
●
GIN (Gwt INjection)
●
Gilead (Generic Light Entity Adapter)
●
Maven
●
Eclipse (GWT/Appengine Plugin)
Wrap Up
●
Demo
●
Questions & Answers
●
http://gwt-enterprise-patterns.googlecode.com
1
GWT Enterprise Patterns
●
Spencer Gibb
●
Sr. Software Engineer for LDS Church
●
12 Years Experience
–
E-commerce
–
Defense
–
Contractor
●
http://spencer.gibb.us
●
Heavy Google User
–
Google Apps for your Domain, App Engine, GWT
●
General Open Source Software User
Looking to buy an older t-mobile android phone
2
If you remember nothing else...
●
Get browser history right, and get it right early
●
Use an Event Bus to fight spaghetti
●
DI + MVP
●
Dependency Injection
●
Model / View / Presenter
Borrowed From Google I/O Presentation
Who reviewed GWT Best Practices session from
Google IO?
My work is based off of that work
I took the event bus concept a little further
3
Three major themes
●
Embrace asynchrony
●
Always be decoupling
●
Strive to achieve statelessness
Borrowed From Google I/O Presentation
I broke some of these rules in the presentation
4
Event Bus
●
Everything is on the Event Bus
●
RPC
●
Results
●
Failures
●
Locations (Browser History)
●
View Presenter communication
●
Simpler Event code than GWT Events
It was very comfortable to put command, results,
locations, errors and general messages on the event
bus
The gwt HandlerManager that is viewed as the default
event bus can be unweildy
Custom events are more complex using
HandlerManager
5
EventBus GWT Event Style
public class MyEvent extends GwtEvent<MyEventHandler> {
public interface MyEventHandler extends EventHandler {
void onAddNewIssue(MyEvent event);
}
private static Type<MyEventHandler> TYPE =
new Type<MyEventHandler>();
public MyEvent() { }
public final Type<MyEventHandler> getAssociatedType() {
return TYPE;
}
protected void dispatch(MyEventHandler handler) {
handler.onAddNewIssue(this);
}
}
I didn't like having to implement the TYPE variable,
though I know why they did because of GWT's lack
of reflection
6
EventBus Simplified Events
●
Type Safe
●
getTypeObject is the key used by EventBus to
get handlers for particular event types rather
than the static TYPE.
public class MyEvent extends Event<String, MyEvent.Handler> {
public static abstract class Handler
extends EventHandler<MyEvent> {
public Object getTypeObject() {
return MyEvent.class;
}
}
public MyEvent(String data) {
super(data);
}
}
All the handlers followed the same pattern so I made a
generic one that simplified things
I use handlers by creating anonymous inner classes.
My custom events allowed for reusing results that we
will see later
7
Borrowed From Google I/O Presentation
The event bus allows for a high degree of decoupling
It made some possibly difficult things rather easy to do
8
Command Pattern
●
GWT RPC Service implementation
DefaultDispatch
●
Commands
●
class SayHelloCommand implements
Command<HelloResults>
●
Results
●
class HelloResult implements Result
●
Reusable Result Objects
–
StringResult, LongResult etc...
One object in, one object out
A dispatch gwt rpc service handles all server side
events
My custom events allow for resuable results, so you
can listen for the results of a particular command
rather than just results (though that may be desired)
http://en.wikipedia.org/wiki/Command_pattern
9
Command Pattern Cont.
●
Command Handler
●
SayHelloCommandHandler implements
CommandHandler<SayHelloCommand, SayHelloResult>
●
One to one with a command/result pair
–
SayHelloResult execute(SayHelloCommand cmd)
●
Multi-Command Handler
●
Multiple commands in One class
●
Lose some type safety, gain flexibility
Class Handler extends MultiCommandHandler {
SayHelloResult hello(SayHelloCommand cmd) {}
GetHelloResult getHello(GetHelloCommand cmd) {}
}
Seemed kind of like struts 1 to me
Use spring or guice to wire all your command handlers
to the dispatch
More work could be done here
More complex workflows via annotations
10
Model, View, Presenter - MVP
●
Presenter defines View interface via GWT Has*
interfaces
●
Communication between View and Presenter is
via GWT Has* interfaces or Events
●
RPC done in Presenter
●
NO
GUI in Presenter
I am a newbee here
Model-view-presenter (MVP) is a user interface design pattern engineered to
facilitate automated unit testing and improve the separation of concerns in
presentation logic.
* The model is an interface defining the data to be displayed or otherwise
acted upon in the user interface.
* The view is an interface that displays data (the model) and routes user
commands (events) to the presenter to act upon that data.
* The presenter acts upon the model and the view. It retrieves data from
repositories (the model), persists it, and formats it for display in the view.
11
MVC
Borrowed From Google I/O Presentation
12
MVP
Borrowed From Google I/O Presentation
13
Presenter
●
Coordinates Events
●
Adds external behavior to view
●
RPC
●
Intra-app events
HelloPresenter extends
AbstractPresenter <HelloPresenter.View, CommandEventBus> {
class View extends WidgetView {
HasText getName();
//...
}
//...
}
Similar to controller
Lots of event bus listeners and firings
14
View
●
All GUI work done here
●
UI Binder or widgets directly
●
Respond to Events on the EventBus
HelloViewImpl extends
AbstractWidgetView <CommandEventBus>
implements HelloPresenter.View {
HasText name;
//...
}
//...
}
Anything from the client.ui package
UI Binder is cool, simplifies views to behavior and not
layout
15
Locations (GWT History)
●
Bookmarkability and browser back button
●
http://localhost/app#hello/joe
●
Gmail style positional parameters
●
All done via the event bus
●
Must be bootstrapped in EntryPoint
●
eventBus.changeLocation(“hello”, “fred”)
●
eventBus.add(new Location.Handler(“hello”) {
public void handle(Location location) {
location.getParam(0); }}
Difficult to understand at first
Master location manager that delegates to children
Gwt-presenter project uses and interface that children
notify parents
16
Dependency Injection in GWT
●
Gin on Guice (Compile time injection)
●
@Inject constructor injection
●
Event Bus in to Views and Presenters
●
Views in to Presenters
●
Default Presenter for Entry Point
●
View view = injector.getHelloPresenter().getView();
RootLayoutPanel.get().add(view.getImpl());
17
Integration
●
Appengine / JDO
●
JPA
●
Spring
●
Future GWT integration!
●
Guice
●
GIN (Gwt INjection)
●
Gilead (Generic Light Entity Adapter)
●
Maven
●
Eclipse (GWT/Appengine Plugin)
The maven repositories were difficult.
Some things hosted in a local repo
GWT maven plugin works well
GWT 2.0
Some quirks when maven creates eclipse files
18
Wrap Up
●
Demo
●
Questions & Answers
●
http://gwt-enterprise-patterns.googlecode.com
Enter the password to open this PDF file:
File name:
-
File size:
-
Title:
-
Author:
-
Subject:
-
Keywords:
-
Creation Date:
-
Modification Date:
-
Creator:
-
PDF Producer:
-
PDF Version:
-
Page Count:
-
Preparing document for printing…
0%
Σχόλια 0
Συνδεθείτε για να κοινοποιήσετε σχόλιο