GWT IoC – Dependency Injection Practicum

Using GWT with GIN you can have automatic dependency injection on the client side of the application.  This is one of my favorite things about using GWT, because you write in java and cross-compile to JS it makes it much easier to support concepts like Dependency Injection (DI).

GIN is built on top of Guice and while it only supports a subset of what Guice can do its still quite a bit.   Gin conforms to JSR-330 so it uses the standard @Inject annotations just like its platform counterparts (Spring3, Guice, atInject, etc..)   The interesting thing to know about GIN is that it does all of its work at compile time, so you can’t do dynamic runtime rebinding.  However, it does mean that compared to manual DI there is practially zero overhead to using the library.

Setting Up GIN

Inheriting the GIN module

You have to inherit the GIN Module in your xml file

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

Define a Ginjector

A Ginjector is an interface that extends Ginjector, it defines any root level objects that you want to get from the injector. This is a primary difference where GIN differs from traditional DI frameworks, in that because it is done during compilation you must define up front the object graph you are going to use.

public interface MyWidgetGinjector extends Ginjector {
  MyWidgetMainPanel getMainPanel();
}

Define Bindings

Bindings are defined in a class that extends AbstractGinModule. The bindings syntax matches the general Guice syntax.

public class MyWidgetClientModule extends AbstractGinModule {
  protected void configure() {
    bind(MyWidgetMainPanel.class).in(Singleton.class);
    bind(MyRemoteService.class).toProvider(MyRemoteServiceProvider.class);
  }
}

Associate Bindings to Ginjector

On the interface that extends Ginjector add an @GinModules interface

@GinModules(MyWidgetClientModule.class)
public interface MyWidgetGinjector extends Ginjector {
  MyWidgetMainPanel getMainPanel();
}

Instantiate the Ginjector

Use GWT.create to make an instance of the Ginjector interface. Once you have this reference you are ready to kickstart the injection process.

public class MyWidget implements EntryPoint {
  private final MyWidgetGinjector injector = GWT.create(MyWidgetGinjector.class);
  public void onModuleLoad() {
    MyWidgetMainPanel mainPanel = injector.getMainPanel();
    RootPanel.get().add(mainPanel);
  }
}

Once the application calls getMainPanel() the injector can then start traversing the dependency graph and start to build up any dependent classes required to build the main panel.
That is all there is to it, then you are free to @Inject to your hearts content.