Hot questions for Using EventBus in gwt platform

Question:

I have a child presenter (added to the parent in a slot) that fires an event through the eventBus (on a condition) when onBind() is called :

class ChildPresenter extends PresenterWidget<?> {

        void onBind() {

               instance = initMyInstance();

               if (instance == null) {
                        eventBus.fireEvent(new MyEvent());
               }
        }

       //...
}

On the parent, i handle the event in the onBind() method like this :

class ParentPresenter extends Presenter<..>{

     void onBind() {

           eventBus.addHandler(MyEvent.TYPE, new MyEventHandler() {...} );
     }
}

I tried also this in the parent: addRegisteredHandler(LoggedOutEvent.TYPE, this) and addVisibleHandler(...) too, where i implement the MyEventHandler interface in the parent presenter but it does not handle the fired event.

Am i doing it wrong? I noticed also when i move the handling process to the onReveal() method of my parent presenter, it worked but twice!!


Answer:

Most likely you have a timing issue. Make sure that addHandler() in the parent is called before fire in the child, and also I think it should happened in a separate browser event. Try this to see if it helps:

class ChildPresenter extends PresenterWidget<?> {

        void onBind() {

               instance = initMyInstance();

               if (instance == null) {
                   Scheduler.get().scheduleDeferred(new ScheduledCommand() {

                       @Override
                       public void execute() {
                            eventBus.fireEvent(new MyEvent());
                       }
                   });

               }
        }

       //...
}

Question:

Ok, here is my problem. I have 2 presenters: FirstPresenter (ex: abc.com#first) & SecondPresenter (ex: abc.com#second). There is a button on SecondPresenter & when user clicks on that button then the FirstPresenter will popup a message.

So, here is what I did, I used eClipse to create an event name MyEvent, the eclipse generated a class MyEvent.java

On the SecondPresenter, I got:

    private EventBus eventBus;

    @Inject
    public SecondPresenter(final EventBus eventBus, final MyView view,
            final MyProxy proxy) {
        super(eventBus, view, proxy);
        this.eventBus=eventBus;
    }
    @Override
    protected void onBind() {
        super.onBind();
        passMsgButton.addClickHandler(new ClickHandler(){

            @Override
            public void onClick(ClickEvent event) {
                MyEvent myEvent =new MyEvent();
                myEvent.setMsg("hello");
                SecondPresenter.this.eventBus.fireEvent(myEvent);    
            }               
        });
    }

On the FirstPresenter, I got:

    private final MyHandler myHandler=new MyHandler(){

        @Override
        public void onMy(
                MyEvent event) {
            // TODO Auto-generated method stub
            Window.alert(event.getMsg());



        }}; 

    @Override
    protected void onBind() {
        super.onBind();
        registerHandler(getEventBus().addHandler(MyEvent.getType(), myHandler));
    }       

If the FirstPresenter is the nested presenter that is embedded inside the SecondPresenter then that above code works fine. But if they are 2 separated Presenters then the above code didn't work.

Why? I checked Google doc & they just say that EventBus can call a Presenter, they didn't say it must be the nested presenter so I assumed that EventBus can call any separated presenter.

I changed private EventBus to public EventBus, but it didn't help.

What am I missing?

EDIT:

I changed my code a bit, it works partially. I am not sure i'm doing right thing since it still has some issues.

Ok, on the FirstPresenter I implements MyHandler & Override onMy method

   public class FirstPresenter extends
    Presenter<FirstPresenter.MyView, FirstPresenter.MyProxy> implements MyHandler{

  private final MyHandler myHandler=new MyHandler(){

    @Override
    public void onMy(
            MyEvent event) {
        // TODO Auto-generated method stub
        Window.alert(event.getMsg());
    }}; 

     @ProxyEvent

     @Override
      public void onMy(MyEvent event) {
        Window.alert(event.getMsg());
          getView().getHtmlPanel().add(new Label("test"));
      }
      @Override
      protected void onBind() {
        super.onBind();
        registerHandler(getEventBus().addHandler(MyEvent.getType(), myHandler));
      }
    }

When I click the button on SecondPresenter (a page on a 2nd tab of Webbrowser) then I saw the message popup on the 2nd tab (i.e. the browser didn't make the 1st tab on focus), but when I click on the FirstPresenter (a page on 1st tab) I didn't see the Label("test")?

Why it can call the Window.alert but didn't add the Label onto the FirstPresenter?

Also, how can I get the Browser to set focus on the FirstPresenter (i.e. show the the first tab)?

Am I missing something?


Answer:

The problem is that if you have two top level presenters only one is active at any time. I guess that the onBind() method of the FirstPresenter hasn't been called and thus the handler hasn't been attached to the Event on the EventBus.

It works with nested presenters because there both Presenters are "active" at the same time.

You have to rely on ProxyEvent to "wake up the FirstPresenter