google gin

31
GIN A basic tutorial by anhquan.de

Upload: anh-quan

Post on 03-Jul-2015

7.178 views

Category:

Technology


8 download

DESCRIPTION

A basic tutorial shows you how to use Google GIN.GIN (GWT INjection) is Guice for Google Web Toolkit client-side code

TRANSCRIPT

Page 1: Google GIN

GIN A basic tutorial

by

anhquan.de

Page 2: Google GIN

What the heck is Google GIN?

• GIN = GWT INjection

• Guice brings automatic dependency injection to server side code, while GIN is for client-side code.

• GIN is built on top of Guice and uses (a subset of) Guice's binding language

Page 3: Google GIN

What the heck is Google GIN?

• GIN = GWT INjection

• Guice brings automatic dependency injection to server side code, while GIN is for client-side code.

• GIN is built on top of Guice and uses (a subset of) Guice's binding language

GWT client-side code

GIN

Page 4: Google GIN

What the heck is Google GIN?

• GIN = GWT INjection

• Guice brings automatic dependency injection to server side code, while GIN is for client-side code.

• GIN is built on top of Guice and uses (a subset of) Guice's binding language

GWT client-side code

GWT server-side code

GIN Guice

Page 5: Google GIN

How to use GIN ?

This tutorial shows you

Page 6: Google GIN

5 Steps to remember

1. Design the application with Interfaces IA,IB,…

Page 7: Google GIN

5 Steps to remember

1. Design the application with Interfaces IA,IB,…

2. Create concrete classes AImpl, BImpl,… to implement interfaces IA,IB,… Remember: use @Inject to mark the non-default constructor.

Page 8: Google GIN

5 Steps to remember

1. Design the application with Interfaces IA,IB,…

2. Create concrete classes AImpl, BImpl,… to implement interfaces IA,IB,… Remember: use @Inject to mark the non-default constructor.

3. Create AppClientModule to configure which implementation is bound to which interface

Page 9: Google GIN

5 Steps to remember

1. Design the application with Interfaces IA,IB,…

2. Create concrete classes AImpl, BImpl,… to implement interfaces IA,IB,… Remember: use @Inject to mark the non-default constructor.

3. Create AppClientModule to configure which implementation is bound to which interface

4. Create interface AppGinjector with the AppClientModule in the annotation @GinModules.

@GinModules({AppClientModule.class, other modules …})

Page 10: Google GIN

5 Steps to remember

1. Design the application with Interfaces IA,IB,…

2. Create concrete classes AImpl, BImpl,… to implement interfaces IA,IB,… Remember: use @Inject to mark the non-default constructor.

3. Create AppClientModule to configure which implementation is bound to which interface

4. Create interface AppGinjector with the AppClientModule in the annotation @GinModules.

5. Generate code for AppGinjector and use it

AppPresenter aPres = injector.getAppPresenter();

aPres.bind();

RootPanel.get().add(aPres.getDisplay().asWidget());

private final AppGinjector injector = GWT.create(AppGinjector.class);

@GinModules({AppClientModule.class, other modules …})

Page 11: Google GIN

Step 1: Design an Interface

public class ConfigPresenter extends WidgetPresenter<ConfigPresenter.Display>{

public interface Display extends NameAwareWidgetDisplay, WidgetDisplay {

public HasClickHandlers getSaveClick();

public void updateConfig(Config config);

}

}

Page 12: Google GIN

Step 1: Design an Interface

public class ConfigPresenter extends WidgetPresenter<ConfigPresenter.Display>{

public interface Display extends NameAwareWidgetDisplay, WidgetDisplay {

public HasClickHandlers getSaveClick();

public void updateConfig(Config config);

}

}

For gwt-dispatch developers: Normally, we create a Display interface as an inner interface of a Presenter class

Page 13: Google GIN

Step 2: Implement the interface

public class ConfigView extends Composite implements ConfigPresenter.Display {

private VerticalPanel panel = new VerticalPanel();

private AppConstants constants;

@Inject

public ConfigView(AppConstants constants, AppMessages messages) {

this.constants = constants;

panel.addStyleName(AppCSS.C_config_container);

panel.add(new HTML("<h1>Config view: comming soon<h1>"));

initWidget(panel);

}

}

Page 14: Google GIN

Step 2: Implement the interface

public class ConfigView extends Composite implements ConfigPresenter.Display {

private VerticalPanel panel = new VerticalPanel();

private AppConstants constants;

@Inject

public ConfigView(AppConstants constants, AppMessages messages) {

this.constants = constants;

panel.addStyleName(AppCSS.C_config_container);

panel.add(new HTML("<h1>Config view: comming soon<h1>"));

initWidget(panel);

}

}

If the class has no default constructor, then a @Inject annotation is required. Otherwise, you will get a RuntimeException (“No @Inject or default constructor found for class …. ”)

Page 15: Google GIN

Step 3: Create class AppClientModule

public class AppClientModule extends AbstractPresenterModule {

@Override

protected void configure() {

bind(EventBus.class).to(DefaultEventBus.class).in(Singleton.class);

bind(PlaceManager.class).to(AppPlaceManager.class);

bindPresenter(LoginPresenter.class, LoginPresenter.Display.class, LoginView.class);

bindPresenter(MainPresenter.class, MainPresenter.Display.class, MainView.class);

bindPresenter(AppPresenter.class, AppPresenter.Display.class, AppView.class);

bind(LoginPresenterPlace.class).in(Singleton.class);

bind(ContactsPresenterPlace.class).in(Singleton.class);

bind(LoginPresenter.class).in(Singleton.class);

bind(LoginPresenter.Display.class).to(LoginView.class);

}

}

Page 16: Google GIN

Step 3: Create class AppClientModule

public class AppClientModule extends AbstractPresenterModule {

@Override

protected void configure() {

bind(EventBus.class).to(DefaultEventBus.class).in(Singleton.class);

bind(PlaceManager.class).to(AppPlaceManager.class);

bindPresenter(LoginPresenter.class, LoginPresenter.Display.class, LoginView.class);

bindPresenter(MainPresenter.class, MainPresenter.Display.class, MainView.class);

bindPresenter(AppPresenter.class, AppPresenter.Display.class, AppView.class);

bind(LoginPresenterPlace.class).in(Singleton.class);

bind(ContactsPresenterPlace.class).in(Singleton.class);

bind(LoginPresenter.class).in(Singleton.class);

bind(LoginPresenter.Display.class).to(LoginView.class);

}

} Don’t need to bind LoginPresenter and LoginPresenter.Display Because they are already “bind” above in the bindPresenter(…)

See the implementation of the bindPresenter() in the next slide …

Page 17: Google GIN

Note: Implementation of bindPresenter()

public abstract class AbstractPresenterModule extends AbstractGinModule {

protected <D extends Display> void bindPresenter( Class<? extends Presenter> presenter,

Class<D> display, Class<? extends D> displayImpl )

{

bind( presenter ).in( Singleton.class );

bindDisplay( display, displayImpl );

}

protected <D extends Display> void bindDisplay( Class<D> display, Class<? extends D>

displayImpl )

{

bind( display ).to( displayImpl );

}

}

Page 18: Google GIN

Note: Implementation of bindPresenter()

public abstract class AbstractPresenterModule extends AbstractGinModule {

protected <D extends Display> void bindPresenter( Class<? extends Presenter> presenter,

Class<D> display, Class<? extends D> displayImpl )

{

bind( presenter ).in( Singleton.class );

bindDisplay( display, displayImpl );

}

protected <D extends Display> void bindDisplay( Class<D> display, Class<? extends D>

displayImpl )

{

bind( display ).to( displayImpl );

}

}

DisplayImpl class is bound to Display interface

Page 19: Google GIN

Note: Implementation of bindPresenter()

public abstract class AbstractPresenterModule extends AbstractGinModule {

protected <D extends Display> void bindPresenter( Class<? extends Presenter> presenter,

Class<D> display, Class<? extends D> displayImpl )

{

bind( presenter ).in( Singleton.class );

bindDisplay( display, displayImpl );

}

protected <D extends Display> void bindDisplay( Class<D> display, Class<? extends D>

displayImpl )

{

bind( display ).to( displayImpl );

}

}

Presenter is bound as Singleton. It means there is no new instance created when you invoke AppGinjector.getPresenter()

DisplayImpl class is bound to Display interface

Page 20: Google GIN

Step 4: Define AppGinjector interface

@GinModules({ClientDispatchModule.class,AppClientModule.class})

public interface AppGinjector extends Ginjector {

public AppPresenter getAppPresenter();

public PlaceManager getPlaceManager();

public EventBus getEventBus();

}

Page 21: Google GIN

Step 4: Define AppGinjector interface

@GinModules({ClientDispatchModule.class,AppClientModule.class})

public interface AppGinjector extends Ginjector {

public AppPresenter getAppPresenter();

public PlaceManager getPlaceManager();

public EventBus getEventBus();

}

List of modules. Each module class contains only one configure() method to specify which implementation is bound to which interface.

Page 22: Google GIN

Step 4: Define AppGinjector interface

@GinModules({ClientDispatchModule.class,AppClientModule.class})

public interface AppGinjector extends Ginjector {

public AppPresenter getAppPresenter();

public PlaceManager getPlaceManager();

public EventBus getEventBus();

}

List of modules. Each module class contains only one configure() method to specify which implementation is bound to which interface.

A helper module provided by gwt-dispatch (just ignore it for now)

Page 23: Google GIN

Step 4: Define AppGinjector interface

@GinModules({ClientDispatchModule.class,AppClientModule.class})

public interface AppGinjector extends Ginjector {

public AppPresenter getAppPresenter();

public PlaceManager getPlaceManager();

public EventBus getEventBus();

}

List of modules. Each module class contains only one configure() method to specify which implementation is bound to which interface.

A helper module provided by gwt-dispatch (just ignore it for now)

You create it in step 3!

Page 24: Google GIN

Step 4: Define AppGinjector interface

@GinModules({ClientDispatchModule.class,AppClientModule.class})

public interface AppGinjector extends Ginjector {

public AppPresenter getAppPresenter();

public PlaceManager getPlaceManager();

public EventBus getEventBus();

}

Use whatever name you want!

List of modules. Each module class contains only one configure() method to specify which implementation is bound to which interface.

A helper module provided by gwt-dispatch (just ignore it for now)

You create it in step 3!

Page 25: Google GIN

Step 4: Define AppGinjector interface

@GinModules({ClientDispatchModule.class,AppClientModule.class})

public interface AppGinjector extends Ginjector {

public AppPresenter getAppPresenter();

public PlaceManager getPlaceManager();

public EventBus getEventBus();

}

Return type is important. Injector will return the instance basing on type.

Use whatever name you want!

List of modules. Each module class contains only one configure() method to specify which implementation is bound to which interface.

A helper module provided by gwt-dispatch (just ignore it for now)

You create it in step 3!

Page 26: Google GIN

Step 5: Using Injector in the EntryPoint

public class App implements EntryPoint{

private final AppGinjector injector = GWT.create(AppGinjector.class);

public void onModuleLoad() {

AppPresenter aPres = injector.getAppPresenter();

aPres.bind();

RootPanel.get().add(aPres.getDisplay().asWidget());

PlaceManager placeManager = injector.getPlaceManager();

placeManager.fireCurrentPlace();

}

}

Page 27: Google GIN

Step 5: Using Injector in the EntryPoint

public class App implements EntryPoint{

private final AppGinjector injector = GWT.create(AppGinjector.class);

public void onModuleLoad() {

AppPresenter aPres = injector.getAppPresenter();

aPres.bind();

RootPanel.get().add(aPres.getDisplay().asWidget());

PlaceManager placeManager = injector.getPlaceManager();

placeManager.fireCurrentPlace();

}

}

GWT generates the implementation of AppGinjector at compile time

Page 28: Google GIN

Step 5: Using Injector in the EntryPoint

public class App implements EntryPoint{

private final AppGinjector injector = GWT.create(AppGinjector.class);

public void onModuleLoad() {

AppPresenter aPres = injector.getAppPresenter();

aPres.bind();

RootPanel.get().add(aPres.getDisplay().asWidget());

PlaceManager placeManager = injector.getPlaceManager();

placeManager.fireCurrentPlace();

}

}

GWT generates the implementation of AppGinjector at compile time

Here are all Interfaces. Their implementations are injected by GIN. But which implementation is bound to which Interface? => See AppClientModule .configure()

Page 29: Google GIN

That’s it!

Page 30: Google GIN

Learn more

Articles: • Google's MVP tutorial

• Best Practices For Architecting Your GWT App session

Projects: • Project google-gin

• Project google-guice

• Project gwt-dispatch

• Project gwt-presenter

• Project gwt-platform

• A project implement MVP patterns based on gwt-dispatch, gin, guice

• Apache Hupa – a GWT based webmail (using maven+junit+eclipse, gwt-dispatch, gwt-presenter, gin, guin). Highly recommended!

• TeampScape – Another tutorial projects about gwt+gae, gwt-dispatch, gwt-presenter, datastore/jdo

Page 31: Google GIN

Thank you!

anhquan.de