How to improve your productivity using GWTP

  • Published on
    16-Jul-2015

  • View
    621

  • Download
    6

Transcript

  • HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTPCHRISTIAN GOUDREAU

    GWT.create 2015

  • Motivations

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    Scalability Maintainability Extensibility

  • Architecture

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    SOLID - Uncle Bob MVP - Martin Fowler Iterative and incremental

    development - Craig Larman

  • THERES JUST TOO MANY GOOD PRACTICES

  • Frontend

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    GWTP REST-Dispatch GSS

  • MODEL

    PRESENTER

    VIEW

    MVP PATTERN

  • Presenter

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • public class ApplicationPresenter extends Presenter {

    interface MyView extends View { }

    @ProxyStandard interface MyProxy extends Proxy { }

    @ContentSlot public static final Type>();

    @Inject ApplicationPresenter(EventBus eventBus, MyView view, MyProxy proxy) { super(eventBus, view, proxy, RevealType.RootLayout); }

    @Override protected void onReveal() { }

    @Override protected void onBind() { }}

  • View

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • public class ApplicationView extends ViewImpl implements ApplicationPresenter.MyView { interface Binder extends UiBinder { }

    @UiField SimplePanel main;

    @Inject ApplicationView(Binder uiBinder) { initWidget(uiBinder.createAndBindUi(this)); }

    @Override public void setInSlot(Object slot, IsWidget content) { if (slot == ApplicationPresenter.SLOT_MAIN) { main.setWidget(content); } }}

  • Model

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • public class Dashboard { private int id;

    public int getId() { return id; }

    public void setId(int id) { this.id = id; }}

  • GWTP Lifecycle

  • Tips

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    Use UiHandlers Use the EventBus Use collaborators

  • UiHandlers and Presenter

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • public interface FeedbackUiHandlers extends UiHandlers { void performMail(Feedback currentFeedback);}

    public class FeedbackPresenter extends Presenter

    implements FeedbackUiHandlers {

    ...

    @Inject FeedbackPresenter(...) { super(...);

    getView().setUiHandlers(this); }

    @Override public void performMail(Feedback currentFeedback) { ... }}

  • View

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • public class FeedbackView extends ViewWithUiHandlers implements FeedbackPresenter.MyView {

    ...

    @UiHandler("submit") void onClick(ClickEvent e) { getUiHandlers().performMail(feedback); }}

  • EventBus

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • @Overrideprotected void onReveal() { themeService.withCallback(new AbstractAsyncCallback() { @Override public void onSuccess(Theme result) { super.onSuccess(result);

    getView().edit(result); } }).getByOrganizationId(currentUser.getOrganizationId());

    UpdateBreadcrumbEvent.fire(this, breadcrumbBuilder.theme());}

  • Collaborators

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • public interface LocationFacade { /** * Adds a new browser history entry. Calling this method will cause * {@link com.google.gwt.event.logical.shared.ValueChangeHandler * #onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)} * to be called as well if and only if issueEvent is true. * * @param historyToken the token to associate with the new history item * @param issueEvent true if a * {@link com.google.gwt.event.logical.shared.ValueChangeHandler * #onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)} * event should be issued */ void newItem(String historyToken, boolean issueEvent);

    /** * Reloads the current browser window. All GWT state will be lost. */ void reload();

    String getCurrentHash();}

  • public class LocationFacadeImpl implements LocationFacade { @Override public void newItem(String newUrl, boolean fireEvent) { History.newItem(newUrl, fireEvent); }

    @Override public native void reload() /*-{ $wnd.location.reload(true); }-*/;

    @Override public String getCurrentHash() { return Location.getHash(); }}

  • RESTDispatch

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    JAX-RS Command pattern Simplest implementation

  • RESTDispatch

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    JAX-RS Command pattern Simplest implementation

    Bonus Response - RestCallback GWTP-Extensions - Rest-

    delegatesDownside - not type safe

  • REST Dispatch setup

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • public class ServiceModule extends AbstractGinModule { @Override protected void configure() { install(new RestDispatchAsyncModule.Builder().build()); }

    @Provides @RestApplicationPath String getApplicationPath() { String baseUrl = GWT.getHostPageBaseURL(); if (baseUrl.endsWith("/")) { baseUrl = baseUrl.substring(0, baseUrl.length() - 1); }

    return baseUrl + API; }}

  • REST Dispatch usage

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • @Path(DASHBOARDS)public interface DashboardService { @GET @Path(DASHBOARD) Dashboard getByOrganizationId(@PathParam(ORGANIZATION_ID) int organizationId);

    @PUT @Path(DASHBOARD) void update(@PathParam(ORGANIZATION_ID) int organizationId, Dashboard dashboard);}

    private void loadTemplate() { dashboardService.withCallback(new AbstractAsyncCallback() { @Override public void onSuccess(Dashboard result) { setInSlot(SLOT_TEMPLATE, templateSelector.createTemplate(result)); } }).getByOrganizationId(currentUser.getOrganizationId());}

  • UIDesign

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    GSS + GSSS UiBinder CSS expert

  • GSS + GSSS

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

  • @Source({"com/arcbees/gsss/mixin/client/mixins.gss", "css/colors.gss", "fonts/geometria/geometria.gss", "css/style.gss"})Style style();

    @Source({"com/arcbees/website/client/resources/css/gridSettings.gss", "com/arcbees/gsss/grid/client/grid.gss"})GridResources.Grid grid();

    http://dev.arcbees.com/gsss/mixins/

  • @require "colors";@require "geometria";@require "gsss-mixins";

    * { box-sizing: border-box;}

    html { font-size: 62.5%;}

    @media (max-width: 979px) { html { font-size: 59%; }}

    .selectedFile { background-color: C_PRIMARY; color: #fff;

    display: inline-block; padding: .5rem .5rem .5rem 1rem;

    @mixin rounded(4px);}

  • Whats next?

    HOW TO IMPROVE YOUR PRODUCTIVITY USING GWTP

    Full JAX-RS coverage XML and custom

    serializers/deserializers New way of writing Presenters Generator rewrite for extensibility Pushstate

    https://docs.google.com/a/arcbees.com/document/d/1N9dMDxTFmZzF3xNTpnP3HIuwZC9OGtPPm_QVEikMP4g/

  • @Presenter(token = HOME, for = MyView.class, slot = ApplicationPresenter.SLOT_MAIN)@UseCodeSplit@UseGatekeeper(AclGatekeeper.class)@GatekeeperParams(ORGANIZATION_SETTINGS_DASHBOARD_READ)public class DashboardPresenter { interface MyView extends View { }

    @Inject DashboardPresenter() { }

    @OnReveal void onReveal() { }

    @OnBind void onBind() { }

    ...}

  • THANK YOU

  • Christian GoudreauCo-Founder and Bee-EO

    at Arcbees

    +ChristianGoudreau@imchrisgoudreau

  • QUESTIONS ?