|
GinTutorial
Using GIN to create a GWT widget
This tutorial will show how a simple GWT widget can be constructed with GIN. You should be already familiar with Guice - if not, then please read the Guice User Guide for an introductory overview of Guice concepts. IntroductionIn regular Guice, you would use: // Does NOT work in GWT code! MyWidgetMainPanel mainPanel = injector.getInstance(MyWidgetMainPanel.class); However, as the comment points out that won't work in GWT:
Fortunately in GWT there is a different idiom for which accomplishes the same purpose. Step 1. Inheriting the GIN module<module> ... <inherits name="com.google.gwt.inject.Inject"/> ... </module> Step 2. Defining the GinjectorDeclare an interface with methods that return the desired types: public interface MyWidgetGinjector extends Ginjector {
MyWidgetMainPanel getMainPanel();
}Experienced GWT users will notice the similarity to the way GWT image bundles and messages are done: You simply create a method for each object type you want to create, and the an implementation of the interface gets generated for you at compile time. Note that you only need to create injector methods for classes that you would directly access in your top-level initialization code, such as the UI classes to install in your RootPanel. You don't need to create injector methods for lower-level classes that will be automatically injected. So for example, if Class A uses class B which uses class C, you only need to create an injector method for A, as the other classes B and C will automatically be injected into A. In other words, injector methods provide a bridge between the Guice and non-Guice world. Step 3. Declare bindingsThe next step is to bind the various classes and providers using a Guice module. The module class looks almost exactly like it would in regular Guice (We use the GinModule and AbstractGinModule instead of Module and AbstractModule.) Here's an example module: public class MyWidgetClientModule extends AbstractGinModule {
protected void configure() {
bind(MyWidgetMainPanel.class).in(Singleton.class);
bind(MyRemoteService.class).toProvider(MyRemoteServiceProvider.class);
}
}Note that if GIN can't find a binding for a class, it falls back to calling GWT.create() on that class. What this means that image bundles and translated messages will just magically work. We emulate most of Guice's types but not modules, because:
For compatibility with regular Guice we provide a GinModuleAdapter class, which makes your GinModule available as a Module. Step 4. Associating the module with the injectorAdd the GinModules annotation to your Ginjector, specifying the module(s) needed to configure the application. @GinModules(MyWidgetClientModule.class)
public interface MyWidgetGinjector extends Ginjector {
MyWidgetMainPanel getMainPanel();
}Current project layout: MyWidgetProject/
client/
MyWidget.java
MyWidgetGinjector.java
MyWidgetMainPanel.java
MyWidgetClientModule.java
public/
server/(TODO: Add build file example) Step 5. Creating the GinjectorTo create the injector instance, use the standard GWT.create() call. This can be done during static initialization: public class MyWidget implements EntryPoint {
private final MyWidgetGinjector injector = GWT.create(MyWidgetGinjector.class);
public void onModuleLoad() {
MyWidgetMainPanel mainPanel = injector.getMainPanel();
RootPanel.get().add(mainPanel);
}
}
|
Sign in to add a comment
Gin also performs some magic when dealing with async remote services (GWT-RPC) and actually calls GWT.create(MyRemoteSyncService.class) if the Ginjector defines a method returning MyRemoteSyncServiceAsync.