Search code examples
gwtuibindergwt-gin

Use gwt ui-binding in conjunction with google-gin


is there a way to use dependency injection in a widget, that is created via ui binding?

Suppose I have a simple widget (in package com.example.client.ui.widget):

public class Foo extends Composite {

    private final EventBus eventBus;

    @Inject
    public Foo(final EventBus eventBus) {
        this.eventBus = eventBus;
        // create ui
    }
}

and then I have a view that is defined via ui binding which uses this widget. eg:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'
    xmlns:app='urn:import:com.example.client.ui.widget'>

    <g:HorizontalPanel>
        <app:Foo/>
    </g:HorizontalPanel>
</ui:UiBinder>

Doing it like this does not work, because of the no-arg constructor constraint for widgets that are used in ui binding. But wouldn't it be nice if the GWT compiler just uses GIN if there is an @Inject annotation? Or can this be done in any other way? Maybe I totally miss the concept of GIN and GWT, if so, any hints are much appreciated.

Thanks in advance, Markus


Solution

  • if you need dependency injection for widgets you are doing something wrong.

    BUT

    It is possible to use GIN to for injection of some stuff into your widgets.

    Think about the following: GIN is a standalone dependency injection framework, you just ask what you need, GIN will create a bean with dependencies resolved. Injection will be performed only if object was obtained from Ginjector instance. UI binder is a framework for declarative UI, it creates widgets based on your XML (and does a bunch of other stuff, but we can ignore it for now).

    So if we want to use GIN to inject dependecies into Widget, it means widget should be created by GIN, not UiBinder. UiBinder will have to use an instace supplied by GIN. Is it possible? Yes, it UiBinder allows it by:

    using annotation @UiField(provided=true) on widget field

    or

    using @UiFactory

    So what you need to do is to create binding for widget in your GinModule, obtain it's instance via Ginjector or inject provider for widget, than you can give instance of widget to UiBinder via @UiField(provided=true) or @UiFactory.