javagwtgwtpgwt-platformgwt-gin

Assisted injection error while trying to create presenter


I already used Gin assisted injection a few times but I'm new to gwtp and I'm facing an error message I don't understand while trying to instantiate a PresenterWidget using my factory, even after reading several posts on the subject...

[ERROR] Error injecting @com.google.inject.assistedinject.Assisted(value=) java.lang.Integer: 
Unable to create or inherit binding: 
Binding requested for constant key '@com.google.inject.assistedinject.Assisted(value=) java.lang.Integer' but no explicit binding was found; 
Path to required node:
org.moshika.dtp.client.application.book.page.PagePresenter [com.gwtplatform.mvp.client.gin.AbstractPresenterModule.bindPresenterWidget(AbstractPresenterModule.java:260)]

Context : I have to display the content of a book on the screen. For the moment I use a BookPresenter with proxy and place and I will try to bind / unbind pages on the fly as PresenterWidget. I don't think my pages could be implemented as CellWidget because I will implement lots of DTP / WYSIWYG functionalities.

My Module :

public class CommonModule extends AbstractGinModule {

@Override
protected void configure() {
    // DefaultPlaceManager Places
    install(new DefaultModule.Builder().defaultPlace(NameTokens.SEARCH).errorPlace(NameTokens.ERROR).unauthorizedPlace(NameTokens.ERROR).build());

    install(new GinFactoryModuleBuilder().build(PagePresenter.Factory.class));

    RestDispatchAsyncModule.Builder dispatchBuilder = new RestDispatchAsyncModule.Builder();
    install(dispatchBuilder.build());

    bindConstant().annotatedWith(RestApplicationPath.class).to("rest");

    bind(ResourceLoader.class).asEagerSingleton();

    bindPresenter(BookPresenter.class, BookPresenter.MyView.class, BookViewTablet.class, BookPresenter.MyProxy.class);

    bindPresenterWidget(PagePresenter.class, PagePresenter.MyView.class, PageViewTablet.class);

}

BookPresenter :

public class BookPresenter extends Presenter<BookPresenter.MyView, BookPresenter.MyProxy>
    implements BookUiHandlers {

    public interface MyView extends View, HasUiHandlers<BookUiHandlers> {
    }

    @ProxyStandard
    @NameToken(NameTokens.BOOK)
    public interface MyProxy extends ProxyPlace<BookPresenter> {
    }

    static final Slot<PagePresenter> SLOT_BOOK = new Slot<PagePresenter>();

    private ResourceDelegate<PageResources> pageDelegate;

    private PagePresenter.Factory factory;

    @Inject
    BookPresenter(EventBus eventBus,
        MyView view, MyProxy proxy,
        ResourceDelegate<PageResources> pageDelegate,
        PagePresenter.Factory factory) {
        super(eventBus, view, proxy, ApplicationPresenter.SLOT_MAIN);

        view.setUiHandlers(this);
        this.pageDelegate= pageDelegate;
        this.factory= factory;
    }

    @Override
    protected void onReveal() {
        super.onReveal();
        NavigationVisibilityEvent.fire(this, true);
        fetchPages(0, 5);
    }

    @Override
    public void fetchPages(final int offset, int limit) {
        pageDelegate.withCallback(new AsyncCallback<List<PageDto>>() {

            @Override
            public void onFailure(Throwable caught) {
                // TODO Auto-generated method stub
            }

            @Override
            public void onSuccess(List<PageDto> dtos) {
                clearSlot(SLOT_BOOK);
                for (PageDto dto : dtos) {
                    PagePresenter pagePresenter = factory.create(dto.getFolioPage());
                    addToSlot(SLOT_DEROULE, pagePresenter);
                    pagePresenter.refreshModel();
                }
            }
        }).list(offset, limit);
    }
}

PagePresenter and Factory :

public class PagePresenter extends PresenterWidget<PagePresenter .MyView>
    implements PageUiHandlers {

    public interface MyView extends View {
        void setFolio(Integer folio);
    }

    public interface Factory {
        CahierPageJourPresenter create(Integer folio);
    }

    private ResourceDelegate<PageResources> pageDelegate;

    private Integer folioPage;

    @Inject
    PagePresenter(EventBus eventBus, MyView view,
        ResourceDelegate<PageResources> pageDelegate,
        @Assisted Integer folio) {
        super(eventBus, view);
        this.pageDelegate= pageDelegate;
        this.folio= folio;
}

    public void refreshModel() {
        pageDelegate.withCallback(new AsyncCallback<PageDto>() {

            @Override
            public void onFailure(Throwable caught) {
                // TODO Auto-generated method stub
            }

            @Override
            public void onSuccess(PageDtodto) {
                getView().setFolio(dto.getFolio());
            }
        }).get(folio);
    }
}

It might be a very stupid mistake since I don't see what I'm doing different from all the other posts on the same subject...


Solution

  • If you want to use assisted injection here, don't call bindPresenterWidget(PagePresenter.class, PagePresenter.MyView.class, PageViewTablet.class); directly. Instead, bind only the view: bind(PagePresenter.MyView.class).to(PageViewTablet.class);

    bindPresenterWidget actually calls bind(PagePresenter.class). Then bindings are resolved and since you don't have a constant for an Integer annotated with @Assisted, it throws.

    If you only ever have one page visible at a time, you can also use a URL parameter to store the page number. Then you can override onReset() and update the content based on the requested page. This technique would avoid instantiating multiple PagePresenter and you can get rid of assisted factories.