GWTP

27
GWTP GOO-TEEPEE By: Ben Bracha

Transcript of GWTP

Page 1: GWTP

GWTP

GOO-TEEPEE

By: Ben Bracha

Page 2: GWTP

Agenda

• Background: Main concepts of GWT• GWTP key concepts and features

Page 3: GWTP

GWT – Main concepts

• Java -> JS• Deferred binding• Code splitting• (Gin/ Guice)

Page 4: GWTP

Java -> JS

• Build complex browser-based apps in Java– Java javascript cross compiler– All the goodies of Java• Rock-solid IDEs and tools• Refactoring• Unit testing

Page 5: GWTP

Deferred Binding

• Generating many version of the code in compile time• Only one is being loaded by particular client in run time• Each version is generated per browser along with other

axis defined by the application (browser, locale…)• In essence, this is the GWT answer for java reflection• GWT.Create(SomeType.class)• Code generation / replacement (for example –

RavelloGrey.gwt.xml)

Page 6: GWTP

Code Splitting

• As application grows – JS code downloading may take some time

• GWT let us split our code – download what you need, when you need it

• GWT.runAsync defines our split point• GWTP makes this clear for us using presenter-proxy

(TBD)

http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html

Page 7: GWTP

Gin & Guice

• Guice is a dependency injection (DI) framework written by Google

• Inversion of control (IOC) – dependencies for a component are set to it externally

• Less usage of the “new” keyword • Can replace actual dependencies easily (for testing..)• The Injector, injector configuration• Gin – Guice written for GWT (lack of reflection )

http://code.google.com/p/google-guice/http://code.google.com/p/google-gin/

Page 8: GWTP

Gin & Guice*.gwt.xml:<module> ... <inherits name="com.google.gwt.inject.Inject"/> ...</module>

Gin module:public class MyWidgetClientModule extends AbstractGinModule { protected void configure() { bind(SomeInterface.class).in(SomeImplementation.class); bind(MyWidgetMainPanel.class).in(Singleton.class); bind(MyRemoteService.class).toProvider(MyRemoteServiceProvider.class); }}

Ginjector: [usually for top level components only]@GinModules(MyWidgetClientModule.class)public interface MyWidgetGinjector extends Ginjector { MyWidgetMainPanel getMainPanel();}

Page 9: GWTP

Gin & Guice• @Inject

On members and on Constructor (note that members are injected only after construction!)

• @ImplementedBy annotation@ImplementedBy(PayPalCreditCardProcessor.class)public interface CreditCardProcessor { …}

Equivalent to:bind(CreditCardProcessor.class).to(PayPalCreditCardProcessor.class);

• Singleton scope– bind(TransactionLog.class).to(InMemoryTransactionLog.class).in(Singlet

on.class);– (default is not singleton!)

Page 10: GWTP

GWTP

• MVP framework for building GWT applications– MVP support (presenters, presenter-widgets,

nested presenters…)– Places (history and bookmark support)– Command pattern (The dispatcher)– The event bus

http://code.google.com/p/gwt-platform/

Page 11: GWTP

MVP

• Model (entity graph)

• View (dumb, no logic)

• Presenter (logic, no UI code)

• Advantages– Testability– Low coupling

Page 12: GWTP

Presenter - Proxy- View

• View – responsible for the widgets layout on screen• Presenter – Contains the business logic for a view

(loading data from server, handling events..)• Proxy – help getting the benefits of “code-splitting”. If

requested – presenter and view will be behind a “split point”

• Binding all together (they are all singletons!!)in AbstractPresenterModule:bindPresenter(LoginPresenter.class, LoginPresenter.MyView.class, LoginView.class, LoginPresenter.MyProxy.class);

Page 13: GWTP

Presenter – View interactions

• Interactions should be made only through interfaces

• The presenter defines an inner view interface (extends HasUiHandlers) implemented by the view

• An external interface extends UiHandlers defines operations required by the view. This is implemented by the presenter

• On presenter construction:getView().setUiHandlers(this);

Page 14: GWTP

Presenter – View interactions (supervising controller pattern)

public interface UserProfileUiHandlers extends UiHandlers{ void onSave();}

public class UserProfilePresenter extends Presenter<UserProfilePresenter.MyView, UserProfilePresenter.MyProxy> implements UserProfileUiHandlers{

public interface MyView extends View, HasUiHandlers<UserProfileUiHandlers>{ }

@Inject ExamplePresenter(final EventBus eventBus, final MyView view, final MyProxy proxy) { super(eventBus, view, proxy); getView().setUiHandlers(this); } ...}

public class ExampleView extends ViewWithUiHandlers<UserProfileUiHandlers> implements MyView { ...

@UiHandler("saveButton") void onSaveButtonClicked(ClickEvent event) { if (getUiHandlers() != null) { getUiHandlers().onSave(); } }

Page 15: GWTP

Presenter Vs. PresenterWidget

• Regular presenter-proxy-view tuple is singleton as defined by the framework

• What if we have some complex UI component that required presenter-view but not necessarily singleton?

• Use PresenterWidget-View pair– PresenterWidget has no proxy– It is up to its hosting parent to instantiate it

(inject!) and reveal it (add-to-slot)

Page 16: GWTP

Presenters Lifecycle

• Never call lifecycle methods explicitly• Always call super() when overriding

What to do When Called Phase

Add handlers to view After presenter construction onBind()

Undo everything from bind() Not called automatically onUnbind()

Any initialization or action should be done before reveal

Just before presenter revealed

onReveal()

Clean any initialization you did in onReveal()

Just before presenter becomes hidden

onHide()

The most commonly used.This is a good place to refresh presenter’s data

when navigation occurs and the presenter is still visible after

onReset()

Page 17: GWTP

Places• A place is usually a page in the application which the user

can navigate to• A place attached to some presenter• The PlaceManager is responsible for all place operations• A place can contain state parameters (URL) – for

bookmarking, history…

• We can add navigation confirmation• We can set up a default page for the application• We can set up a default error-page for the application• …

Page 18: GWTP

Placeshttp://phone.com#!search;q=iphone

public class SearchPresenter … {@ProxyStandard@NameToken("!Search")public interface MyProxy extends ProxyPlace<SearchPresenter>{…}…@Overridepublic void prepareFromRequest(PlaceRequest request) { … }String type = request.getParameter(…);}

* When preparing from request, If your presenter needs to fetch data from server that is required for it to become visible, you can block the reveal-phase and use manual-reveal

Page 19: GWTP

Nested Presenters

• You can build a composite-presenter made up from several child-presenters– Imply some common layout– Better design (break complex structures)– Reuse (presenters widgets)

• Composition is done with “slots”– Presenter defines named slots– View handles slot layout– The presenter may or may not know his children

http://code.google.com/p/gwt-platform/wiki/SimpleNestedSample

Page 20: GWTP

Nested Presenterspublic class MainPagePresenter extends Presenter<MainPagePresenter.MyView, MainPagePresenter.MyProxy> { @ContentSlot public static final Type<RevealContentHandler<?>> TYPE_SetMainContent = new Type<RevealContentHandler<?>>();

public interface MyView extends View {}… @Override protected void revealInParent() { RevealRootContentEvent.fire(this, this); }}

Page 21: GWTP

Nested Presenterpublic class MainPageView extends ViewImpl implements MyView { @UiField FlowPanel mainContentPanel; …

@Override public void setInSlot(Object slot, Widget content) { if (slot == MainPagePresenter.TYPE_SetMainContent) { setMainContent(content); } else { super.setInSlot(slot, content); } }

private void setMainContent(Widget content) { mainContentPanel.clear(); if (content != null) { mainContentPanel.add(content); } }}

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"><ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder“ …> <g:HTMLPanel> <npui:MainMenu /> <g:FlowPanel ui:field="mainContentPanel" /> <npui:MainMenu /> </g:HTMLPanel></ui:UiBinder>

Page 22: GWTP

Nested Presenterspublic class HomePresenter extends Presenter<HomePresenter.MyView, HomePresenter.MyProxy> { public interface MyView extends View {} @ProxyCodeSplit @NameToken(NameTokens.homePage) public interface MyProxy extends ProxyPlace<HomePresenter> {} @Inject public HomePresenter( final EventBus eventBus, final MyView view, final MyProxy proxy) { super(eventBus, view, proxy); }

@Override protected void revealInParent() { RevealContentEvent.fire(this, MainPagePresenter.TYPE_SetMainContent, this); }}

Page 23: GWTP

The Dispatcher

• Centralized component handling all client-server communication

• Command pattern– Action: shared with the server and client. Presents some

logic action that can be done by the client– Result: shared with the server and client. Each action

bounded to exactly one result, presenting the return value of the action.

– Handler: known only to the server. Handles an action-result pair.

http://code.google.com/p/gwt-platform/wiki/GettingStartedDispatch

Page 24: GWTP

The DispatcherAction:public class CreateNewDesignAction extends UnsecuredActionImpl<CreateNewDesignResult> {

private String designName;...

{

Result:public class CreateNewDesignResult implements Result {private DesignDto designDto;…}

Bind server handler:public class ServerModule extends HandlerModule {…@Overrideprotected void configureHandlers() {

…bindHandler(CreateNewDesignAction.class, CreateNewDesignServerActionHandler.class);

}

Invoke action from client:dispatcher.execute(new CreateNewDesignAction(text), new BaseCallback<CreateNewDesignResult>() {

@Overridepublic void onSuccess(CreateNewDesignResult result) { setCurrentDesign(result.getDesignDto());{});

Page 25: GWTP

The Event Bus

• Central unit for communication between loosely related objects (vs. direct method invocation)

• Use it for notifying the “world” (the application) about interesting events (for example: entity updated)

• Not over-use it – avoid chatty application (performance)• Can used private event-bus \ named-event-bus (for

separation)

http://arcbees.wordpress.com/2010/08/24/gwt-platform-event-best-practice/

Page 26: GWTP

The Event Bus

Page 27: GWTP

The Event Bus