Upload
arcbees
View
627
Download
6
Embed Size (px)
Citation preview
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
THERE’S 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<ApplicationPresenter.MyView, ApplicationPresenter.MyProxy> {
interface MyView extends View { }
@ProxyStandard interface MyProxy extends Proxy<ApplicationPresenter> { }
@ContentSlot public static final Type<RevealContentHandler<?>> SLOT_MAIN = new Type<RevealContentHandler<?>>();
@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<Widget, ApplicationView> { }
@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<FeedbackPresenter.MyView, FeedbackPresenter.MyProxy>
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<FeedbackUiHandlers> 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<Theme>() { @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; }}
<inherits name="com.gwtplatform.dispatch.rest.delegates.ResourceDelegate"/><inherits name='com.gwtplatform.mvp.MvpWithEntryPoint'/>
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<Dashboard>() { @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);}
What’s 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 ?