architecting your gwt applications with gwt-platform - lesson 02

43
Architecting your GWT application with GWT- Platform Juan Manuel Rojas R. http://rhemsolutions.com/ Lima, Perú 26/10/2012

Upload: rhemsolutions

Post on 29-Nov-2014

13.295 views

Category:

Documents


8 download

DESCRIPTION

Write GXT3 application using GWTP

TRANSCRIPT

Page 1: Architecting your GWT applications with GWT-Platform - Lesson 02

Architecting your GWT application with GWT-

Platform

Juan Manuel Rojas R.http://rhemsolutions.com/ Lima, Perú 26/10/2012

Page 2: Architecting your GWT applications with GWT-Platform - Lesson 02

Architecting your GWT application

Google found that a Model-view-presenter (MVP) architecture works best when developing GWT appshttps://developers.google.com/web-toolkit/articles/mvp-architecture

Model View Presenter FrameworksMvp4ggwt-dispatchgwt-platform

Page 3: Architecting your GWT applications with GWT-Platform - Lesson 02

GWT-Platform

It's an open source MVP framework, that supports many nice features of GWT, including code splitting and history management, with a simple annotation-based API.

Page 4: Architecting your GWT applications with GWT-Platform - Lesson 02

A highly productive app stack

http://www.youtube.com/watch?feature=player_detailpage&v=imiquTOLl64#t=200s

gwt-platform (GWTP)

GWT RequestFactory

JPA 2.0 - PostgreSQL

UI (MVP)

RPC

PostgreSQL

Page 5: Architecting your GWT applications with GWT-Platform - Lesson 02

Google Plugin for Eclipse

Update sites

Eclipse 4.2 (Juno)http://dl.google.com/eclipse/plugin/4.2

Page 6: Architecting your GWT applications with GWT-Platform - Lesson 02

GWTP Eclipse Plugin

To install the GWTP Eclipse Plugin, from Eclipse go to Help > Install New Software

Click on Add...Name: GWTPLocation: http://plugin.gwt-platform.googlecode.com/hg/update

Page 7: Architecting your GWT applications with GWT-Platform - Lesson 02

Clean example code1. Delete theme lines from Module.gwt.xml2. Delete files from client package GreetingService GreetingServiceAsync server package, GreetingServiceImpl shared packaged FieldVerifier src/test/java GwtTestFirstProject src/test/resources FirstProjectJUnit.gwt.xml3. Clean Css file and html table code src/main/webapp4. Delete servlet definition from web.xml src/main/webapp/WEB-INF

Entry point

package com.example.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.user.client.Window;

public class FirstProject implements EntryPoint { public void onModuleLoad() { Window.alert("empty project"); }}

Page 8: Architecting your GWT applications with GWT-Platform - Lesson 02

Dependency injection (DI)

Separate behavior from dependency resolution.

Injects the dependent element (object or value etc) to the destination automatically.

Reduction of boilerplate code in the application objects since all work to initialize or set up dependencies is handled by a provider component.http://en.wikipedia.org/wiki/Dependency_injection

Page 9: Architecting your GWT applications with GWT-Platform - Lesson 02

Dependency injection for GWT

google-ginGIN is built on top of Guice and uses (a subset of) Guice's binding language.

<!-- google-gin --><dependency>

<groupId>com.google.gwt.inject</groupId> <artifactId>gin</artifactId> <version>2.0.0</version> <exclusions> <exclusion> <groupId>com.google.gwt</groupId> <artifactId>gwt-servlet</artifactId> </exclusion> </exclusions>

</dependency>

Page 10: Architecting your GWT applications with GWT-Platform - Lesson 02

Dependency injection for Java 5

google-guiceThink of Guice's @Inject as the new new.Guice embraces Java's type safe nature using generics and annotations. <!-- google guice --> <dependency> <groupId>com.google.inject</groupId> <artifactId>guice</artifactId> <version>3.0</version> </dependency>

Page 11: Architecting your GWT applications with GWT-Platform - Lesson 02

Dependency injection GIN

Constructor injection

public class ClientPlaceManager {

@Injectpublic ClientPlaceManager(final EventBus eventBus,

final TokenFormatter tokenFormatter) { //eventBus and tokenFormatter are not null

}}

public class ColaboradorPresenter {

@Inject Messages messages;

public ColaboradorPresenter() {//messages is null}

protected void onBind() {//messages is not null}

}

Field injection

Page 12: Architecting your GWT applications with GWT-Platform - Lesson 02

Dependency injection GIN (Continuation)@Provides MethodsWhen you need create and initialize an object.

public class ClientModule extends AbstractPresenterModule {

@Provides @Singleton public AppRequestFactory createRequestFactory(EventBus eventBus, MyDefaultRequestTransport requestTransport) {

AppRequestFactory factory = GWT.create(AppRequestFactory.class); factory.initialize(eventBus, requestTransport); return factory; }}

public class ColaboradorPresenter { private final AppRequestFactory factory; @Inject public ColaboradorPresenter(Provider<AppRequestFactory> provider){ factory = provider.get(); }}

How to inject

Page 13: Architecting your GWT applications with GWT-Platform - Lesson 02

Setting GWTP and GXT3

Add to your Module.gwt.xml

<!-- sencha gxt3 --><dependency> <groupId>com.sencha.gxt</groupId> <artifactId>gxt</artifactId> <version>3.0.1</version> </dependency>

<inherits name='com.sencha.gxt.ui.GXT'/> <inherits name='com.gwtplatform.mvp.Mvp'/>

Add to your POM.xml

<properties> ... <gwtp.version>0.7</gwtp.version> ... </properties>

<!-- MVP component --> <dependency> <groupId>com.gwtplatform</groupId> <artifactId>gwtp-mvp-client</artifactId> <version>${gwtp.version}</version> <scope>provided</scope> </dependency> <!-- Annotation component --> <dependency> <groupId>com.gwtplatform</groupId> <artifactId>gwtp-processors</artifactId> <version>${gwtp.version}</version> <scope>provided</scope> </dependency>

Page 14: Architecting your GWT applications with GWT-Platform - Lesson 02

Setting GWTP Create the directoriescom.example.client |--presenter |--view |--place

import com.google.web.bindery.event.shared.EventBus;

public class ClientPlaceManager extends PlaceManagerImpl {

private final PlaceRequest defaultPlaceRequest;

@Injectpublic ClientPlaceManager(final EventBus eventBus,

final TokenFormatter tokenFormatter,@DefaultPlace final String defaultPlaceNameToken) {

super(eventBus, tokenFormatter);this.defaultPlaceRequest = new PlaceRequest(defaultPlaceNameToken);

}

public void revealDefaultPlace() {revealPlace(defaultPlaceRequest, false);

}}

import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.PARAMETER;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.RetentionPolicy.RUNTIME;

@BindingAnnotation@Target({ FIELD, PARAMETER, METHOD })@Retention(RUNTIME)public @interface DefaultPlace {}

public class NameTokens {

}

Page 15: Architecting your GWT applications with GWT-Platform - Lesson 02

Setting GIN for GWTP

Create a gin package in the client side

public class ClientModule extends AbstractPresenterModule {

@Overrideprotected void configure() { install(new DefaultModule(ClientPlaceManager.class));}

}

import com.google.web.bindery.event.shared.EventBus;@GinModules(ClientModule.class)public interface ClientGinjector extends Ginjector { EventBus getEventBus(); PlaceManager getPlaceManager();}

Getters methods for get objects

Define objects available for injection

If GIN can't find a binding for a class, it falls back to calling GWT.create() on that class.

Inheriting the GIN module

<inherits name="com.google.gwt.inject.Inject"/>

Page 16: Architecting your GWT applications with GWT-Platform - Lesson 02

Setting GIN for GWTP(Continuation)Configure your EntryPoint

public class FirstProject implements EntryPoint { private final ClientGinjector ginjector = GWT.create(ClientGinjector.class);

public void onModuleLoad() { // This is required for Gwt-Platform proxy's generatorDelayedBindRegistry.bind(ginjector);

ginjector.getPlaceManager().revealCurrentPlace(); }}

Add the next properties to your Module.gwt.xml<module> ... <define-configuration-property name='gin.ginjector' is-multi-valued='false' /> <set-configuration-property name='gin.ginjector' value='com.example.client.gin.ClientGinjector' />

</module>

Page 17: Architecting your GWT applications with GWT-Platform - Lesson 02

GWT-Platform and GXT3

Structure your views

A place represent a url of a program

Page 18: Architecting your GWT applications with GWT-Platform - Lesson 02

GWT-Platform and GXT3(Continuation)

TokensMost presenters have a token so the user can navigate.

When there is not token the default presenter is shown.You can navigate from one presenter to another by:● Typing another url● Using a Hyperlink Widget● Using a PlaceRequest

PlaceRequest request = new PlaceRequest("inicio");

placeManager.revealPlace(request);

Page 19: Architecting your GWT applications with GWT-Platform - Lesson 02

GWT-Platform and GXT3(Continuation)

Nested PresentersYour header, footer and menu are in one presenter the "parent presenter".

Page 20: Architecting your GWT applications with GWT-Platform - Lesson 02

GWT-Platform and GXT3(Continuation)

Presenter Widget Is for reusable graphical and logical code.

Page 22: Architecting your GWT applications with GWT-Platform - Lesson 02

GWT-Platform and GXT3(Continuation)

All presenters are composed of three files if you will use UIBinder

All presenters have a inner interface that view implements.

Page 23: Architecting your GWT applications with GWT-Platform - Lesson 02

Presenter lifecycle

GWT-Platform and GXT3(Continuation)

Page 24: Architecting your GWT applications with GWT-Platform - Lesson 02

GWT-Platform and GXT3(Continuation)

Presenter lifecycle

1. Presenters are Singleton so it is instantiated once.2. prepareFromRequest(): Is where you can get url

parameters.3. onBind(): Is called when the presenter is instantiated.4. onReveal(): Is called whenever the Presenter was not

visible on screen and becomes visible.5. onHide(): Is called whenever the Presenter was visible

on screen and is being hidden.6. onReset(): Is called whenever the user navigates to a

page that shows the presenter, whether it was visible or not.

Page 25: Architecting your GWT applications with GWT-Platform - Lesson 02

Create Presenterusing GWTP Eclipse Plugin

Page 26: Architecting your GWT applications with GWT-Platform - Lesson 02

First PresenterLayoutPresenterOptions

● Use UiBinder● RevealRootContentEvent● Is Not a Place

OrderingMove to view packageLayoutView.javaLayoutView.ui.xml

Page 27: Architecting your GWT applications with GWT-Platform - Lesson 02

First Presenter LayoutPresenter(Continuation)

Deprecated shared.EventBus

GWTP Eclipse Plugin use EventBus from event.shared next this package was deprecated and change to web.bindery.event.shared.

* Is important to do the next in every presenter you create with GWTP Eclipse Plugin

Delete import com.google.gwt.event.shared.EventBusReplace byimport com.google.web.bindery.event.shared.EventBus;

Page 28: Architecting your GWT applications with GWT-Platform - Lesson 02

First Presenter LayoutPresenter(Continuation)Add the next field to LayoutPresenter

import com.google.gwt.event.shared.GwtEvent.Type;//for nested presenters@ContentSlot public static final Type<RevealContentHandler<?>> SLOT_content = new Type<RevealContentHandler<?>>();

Modify LayoutView.ui.xml<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'xmlns:g='urn:import:com.google.gwt.user.client.ui'xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"xmlns:container="urn:import:com.sencha.gxt.widget.core.client.

container" ><container:Viewport> <!--for nested presenter --> <gxt:ContentPanel ui:field="contentPanel" borders="false"

headerVisible="false" bodyBorder="false" /> </container:Viewport>

</ui:UiBinder>

Page 29: Architecting your GWT applications with GWT-Platform - Lesson 02

First Presenter LayoutPresenter(Continuation)

Setting Vertical Layout (LayoutView.ui.xml)<ui:UiBinder> ... <ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="minVerticalLayoutData" > <ui:attributes width="1" height="-1" /> </ui:with> <ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="maxVerticalLayoutData" > <ui:attributes width="1" height="1" /> </ui:with>

<container:Viewport> ...</container:Viewport>

</ui:UiBinder>

Page 30: Architecting your GWT applications with GWT-Platform - Lesson 02

<ui:UiBinder> ...

<container:Viewport> <container:VerticalLayoutContainer> <container:child layoutData="{minVerticalLayoutData}"> <g:HTMLPanel> <div> <div>First Project</div> </div> </g:HTMLPanel> </container:child> <container:child layoutData="{maxVerticalLayoutData}"> <!--for nested presenter --> <gxt:ContentPanel ui:field="contentPanel" borders="false" headerVisible="false"

bodyBorder="false" /> </container:child> </container:VerticalLayoutContainer></container:Viewport>

</ui:UiBinder>

First Presenter LayoutPresenter(Continuation)

Using Vertical Layout (LayoutView.ui.xml)

Page 31: Architecting your GWT applications with GWT-Platform - Lesson 02

First Presenter LayoutPresenter(Continuation)

@UiField ContentPanel contentPanel;//for nested presenter

Add the next field to LayoutView

@Overridepublic void setInSlot(Object slot, Widget content) {

if(slot == LayoutPresenter.SLOT_content){contentPanel.clear();if(content != null){

contentPanel.add(content);contentPanel.forceLayout();

}return;

}super.setInSlot(slot, content);

}

Add the next method to LayoutView

Page 32: Architecting your GWT applications with GWT-Platform - Lesson 02

Default PresenterWelcomePresenterOptions

● Use UiBinder● RevealContentEvent● Content Slot

(from parent presenter)● Is a Place● CodeSplit (recommended)● Token: #welcome● DefaultPlace

Page 33: Architecting your GWT applications with GWT-Platform - Lesson 02

Default Presenter WelcomePresenter(Continuation)

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'xmlns:g='urn:import:com.google.gwt.user.client.ui'xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container"

>

<gxt:ContentPanel headingText="Welcome" > <container:CenterLayoutContainer> <g:HTMLPanel><h2> Welcome User</h2></g:HTMLPanel> </container:CenterLayoutContainer></gxt:ContentPanel>

</ui:UiBinder>

Modify WelcomeView.ui.xml

Page 34: Architecting your GWT applications with GWT-Platform - Lesson 02

reset.css

Download reset.cssput this css in your HTML header<head>...<link type="text/css" rel="stylesheet" href="reset.css">...</head>

In your Module.css file* { font-family: arial, helvetica, tahoma, sans-serif;}

Page 35: Architecting your GWT applications with GWT-Platform - Lesson 02

mvn gwt:run

Page 37: Architecting your GWT applications with GWT-Platform - Lesson 02

Styling our application(Continuation)public interface Resources extends ClientBundle {

@Source("add.png") ImageResource add();

@Source("delete.png") ImageResource delete();

@Source("cancel.png") ImageResource cancel();

@Source("edit.png") ImageResource edit();

@Source("save.png") ImageResource save();

@Source("exit.png") ImageResource exit();

}

client.resources |- Resources.java

Page 38: Architecting your GWT applications with GWT-Platform - Lesson 02

Styling our application(Continuation)public interface CommonsCss extends CssResource {

@ClassName("layout-header")String layout_header();

@ClassName("layout-title")String layout_title();

String logout();

@ClassName("underline")String underline();

@ClassName("button")String button();

String exit();}

client.resources |- CommonsCss.java |- Commons.css

Page 39: Architecting your GWT applications with GWT-Platform - Lesson 02

Styling our application(Continuation)

Add to your ClientBundle

public interface Resources extends ClientBundle {

...

@Source("bg.gif") ImageResource bg();

@Source("Commons.css") CommonsCss commonsCss();

}

Page 40: Architecting your GWT applications with GWT-Platform - Lesson 02

Styling our application(Continuation)

Modify LayoutView.ui.xml<ui:UiBinder> <ui:with type="com.example.client.resources.Resources" field="resources" />

...

<container:child layoutData="{minVerticalLayoutData}"> <g:HTMLPanel styleName="{resources.commonsCss.layout_header}"> <div class="{resources.commonsCss.layout_title}"> First Project </div> <div class="{resources.commonsCss.logout}"> <span class="{resources.commonsCss.underline}"> <a class="{resources.commonsCss.button}" href="/logout" > <span class="{resources.commonsCss.exit}">Logout</span> </a> </span> </div> </g:HTMLPanel> </container:child> ...

</ui:UiBinder>

Page 41: Architecting your GWT applications with GWT-Platform - Lesson 02

Styling our application(Continuation)

Modify LayoutView.javapublic class LayoutView extends ViewImpl implements LayoutPresenter.MyView {

...

@Injectpublic LayoutView(final Binder binder, final Resources resources ) {

resources.commonsCss().ensureInjected();//load css

widget = binder.createAndBindUi(this);}

}

Page 42: Architecting your GWT applications with GWT-Platform - Lesson 02

mvn gwt:run

Thanks