4

I've implemented a GWT application following the recommendations of this tutorial. I also downloaded the sample code, and I noticed that every Presenter of the demo needed to be injected in the main presenter constructor to be instantiated. The author included this in the source:

public class GreetingPresenter extends WidgetPresenter<GreetingPresenter.Display> {

    // FUDGE FACTOR!  Although this is not used, having GIN pass the object
    // to this class will force its instantiation and therefore will make the
    // response presenter listen for events (via bind()).  This is not a very good way to
    // achieve this, but I wanted to put something together quickly - sorry!
    private final GreetingResponsePresenter greetingResponsePresenter;

    @Inject
    public GreetingPresenter(final Display display, final EventBus eventBus, final DispatchAsync dispatcher, final GreetingResponsePresenter greetingResponsePresenter) {
            super(display, eventBus);       
            this.dispatcher = dispatcher;       
            this.greetingResponsePresenter = greetingResponsePresenter;     
            bind();
}

I verified that if any Presenter doesn't get injected in GreetingPresenter, it won't be instantiated. For demonstration purposes this is cool because the whole app only has two Presenters, but in a Real-World application this can be a serious inconvenient.

What's the proper way of accomplish Presenter instantiation?

EDIT: Including GIN related classes for reference:

Presenter module:

public class GreetingClientModule extends AbstractPresenterModule {

    @Override
    protected void configure() {        
        bind(EventBus.class).to(DefaultEventBus.class).in(Singleton.class);
        bind(PlaceManager.class).in(Singleton.class);       
        bindPresenter(GreetingPresenter.class, GreetingPresenter.Display.class, GreetingView.class);
        bindPresenter(GreetingResponsePresenter.class, GreetingResponsePresenter.Display.class, GreetingResponseView.class);        
        bind(AppPresenter.class).in(Singleton.class);
        bind(CachingDispatchAsync.class);
    }
}

Ginjector:

@GinModules({ ClientDispatchModule.class, GreetingClientModule.class })
public interface GreetingGinjector extends Ginjector {

    AppPresenter getAppPresenter();
    PlaceManager getPlaceManager();

}
Carlos Gavidia-Calderon
  • 7,145
  • 9
  • 34
  • 59

2 Answers2

3

You can solve this by using Providers. In my Gin Modules I declare my Presenter/Activity along with it's view like this

    // Content Area
    bind(ContentActivityMapper.class).in(Singleton.class);

    // Intro Page
    bind(IntroPageActivity.class);
    bind(IntroPageView.class).to(IntroPageViewImpl.class).in(Singleton.class);

Then in the Activity Mapper I use the provider like this

public class ContentActivityMapper implements ActivityMapper {

    @Inject Provider<IntroPageActivity> introPageProvider;

    public Activity getActivity(Place place) {

        if (place instanceof DefaultPlace) {
        return introPageProvider.get().withPlace(new IntroPagePlace());
        }...

I have the withPlace method set up on the ActivityPresenter to allow for it to be injected without an argument. That code looks like this.

public class IntroPageActivity extends AbstractActivity {

    private IntroPageView view;

    @Inject
    public IntroPageActivity(IntroPageView view) {
        super();
        this.view = view;
    }

    public IntroPageActivity withPlace(IntroPagePlace place) {
        return this;
    }

    @Override
    public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
        containerWidget.setWidget(view.asWidget());
    }...
Deanna
  • 696
  • 1
  • 5
  • 15
  • The MVP framework used already has facilities for Presenter/Display injection (see the another answer). But still, we need every presenter as an argument of the main Presenter for the app to work :S – Carlos Gavidia-Calderon Apr 13 '12 at 16:03
  • I didn't show them in the example but I have around 20 different activities/presenters in this application. I don't have to embed them in the maim presenter. This is all I need and they all get created as needed and even works with the AsyncProvider class for code splitting. – Deanna Apr 13 '12 at 16:12
  • I am trying to do this with GWTP but my Provider is always undefined.. the parent Presenter declares `@Injected Provider myAbc` but something appears to be missing. Any idea what the problem might be? – Stefan Falk Mar 12 '16 at 15:58
  • I don't really have enough info on your problem to help you. My only guess is something isn't bound in the Gin modules file. – Deanna Mar 28 '16 at 21:53
2

I think you are missing your Ginjector and AbstractGinModule definition where you define the GIN bindings from that sample.
I recommend to download the code from the mentioned tutorial and also check out the GIN getting started wiki.

GreetingGinjector:

@GinModules({ ClientDispatchModule.class, GreetingClientModule.class })
public interface GreetingGinjector extends Ginjector {

    AppPresenter getAppPresenter();

    PlaceManager getPlaceManager();

}

GreetingClientModule:

public class GreetingClientModule extends AbstractPresenterModule {

    @Override
    protected void configure() {        
        bind(EventBus.class).to(DefaultEventBus.class).in(Singleton.class);
        bind(PlaceManager.class).in(Singleton.class);

        bindPresenter(GreetingPresenter.class, GreetingPresenter.Display.class, GreetingView.class);
        bindPresenter(GreetingResponsePresenter.class, GreetingResponsePresenter.Display.class, GreetingResponseView.class);

        bind(AppPresenter.class).in(Singleton.class);
        bind(CachingDispatchAsync.class);
    }
}

Entrypoint:

public class GreetMvp implements EntryPoint {
    private final GreetingGinjector injector = GWT.create(GreetingGinjector.class);

    public void onModuleLoad() {
        final AppPresenter appPresenter = injector.getAppPresenter();
        appPresenter.go(RootPanel.get());

        injector.getPlaceManager().fireCurrentPlace();
    }
}
Ümit
  • 17,379
  • 7
  • 55
  • 74
  • I download the source code and tested it, and it included the classes that you mention. Still, the "FUDGE FACTOR" was needed for the GreetingResponsePresenter to work :S – Carlos Gavidia-Calderon Apr 12 '12 at 21:10