What is current state/fix of/for deprecated PlaceController constructor

471 views
Skip to first unread message

tanteanni

unread,
Nov 8, 2011, 4:13:31 AM11/8/11
to google-we...@googlegroups.com
I just updated to gwt 2.4  - to get the data grid (very nice). but no my PlaceController construction is deprecated. I read around here but can't find a good solution for this issue. (is it even an issue?):
if i update my PlaceController construction (in GinModule), all Activity's start()-methods start to cry (they wan't the old EventBus). They get their EventBus via ActivityManager, but the ActivityManagers are also constructed with "new" EventBus. So it seems it's a Problem of "AbstractActivity" isn't it?

For he Moment i have decided to keep the deprecated constructor (good idea?). But what would be the long term solution for this? Will there be a fix? Or is there already a fix?

thx in advance

Thomas Broyer

unread,
Nov 8, 2011, 4:29:48 AM11/8/11
to google-we...@googlegroups.com
How is your GIN configuration impacting your Activities start() methods?

As you said, the EventBus passed there comes from the ActivityManagers, so there's no reason GIN would mess things up.

(and BTW, Activity is still using the "old" EventBus because switching to the new one would be a breaking change)

tanteanni

unread,
Nov 8, 2011, 5:55:48 AM11/8/11
to google-we...@googlegroups.com
my problem is (the same problem as the others have/has?) if i change the event bus in GinModule all other instance get the "new" event bus. But now nobody (for example the activity manager) could call start(..., OldEventBus) because AbstractActivity's (com.google.gwt.activity.shared.AbstractActivity) start-method needs the eventbus from the "old" package. (to make it short if i switch to new event bus in ginModule the compile fails - i'don't want this :-))

the question is what to do (in http://code.google.com/p/google-web-toolkit/issues/detail?id=6653) they talked about editing activity source code or providing an own activity. but i guess thats not the "official" solution to lift an gwt app (2.3 using activities) to 2.4?!
so how to implement an Activity in gwt 2.4 (i guess com.google.gwt.activity.shared.AbstractActivity should not be used?)?

Thomas Broyer

unread,
Nov 8, 2011, 6:51:54 AM11/8/11
to google-we...@googlegroups.com
The question is: if only Activity uses the "old" event bus, and that one happens to be provided by ActivityManager (which has a dependency on the "new" event bus), and why couldn't you use the "new" event bus everywhere else than the Activity#start method?

bind(com.google.web.bindery.event.shared.EventBus.class).to(com.google.web.bindery.event.shared.SimpleEventBus.class).in(Singleton.class);

@Provides PlaceController providePlaceController(com.google.web.bindery.event.shared.EventBus bus) {
   return new PlaceController(bus);
}
@Provides PlaceHistoryHandler providePlaceHistoryHandler(PlaceHistoryMapper mapper) {
   return new  PlaceHistoryHandler(mapper);
}
...
ActivityManager manager = new ActivityManager(injector.activityMapper() // simplification: assumes a single ActivityManager/ActivityMapper
                            injector.eventBus());
manager.setDisplay(display);

PlaceHistoryHandler phh = injector.placeHistoryHandler();
phh.register(injector.placeController(), injector.eventBus(), defaultPlace);
phh.handleCurrentHistory();

Everything above compiles OK, right?

Now, why that class would make it fail to compile then:
class MyActivity extends AbstractActivity {
   public void start(AcceptsOneWidget panel, com.google.gwt.event.shared.EventBus bus) {
      panel.setWidget(new Label("Hello World!");
   }
}

The activity has no dependency on the singleton/global event bus, and the one passed to its start() method doesn't come from GIN; so what's the problem?

And if you need to get injected the global event bus, for whatever reason, then just do it:

import com.google.web.bindery.event.shared.EventBus;
class MyActivity extends AbstractActivity {
   @Inject EventBus globalBus;

   public void start(AcceptsOneWidget panel, com.google.gwt.event.shared.EventBus bus) {
      panel.setWidget(new Label("Hello World!");
      globalBus.fireEvent(new StartedEvent("hello world"));
   }
}

tanteanni

unread,
Nov 8, 2011, 7:40:25 AM11/8/11
to google-we...@googlegroups.com
Thx Thomas,

"The activity has no dependency on the singleton/global event bus, and the one passed to its start() method doesn't come from GIN; so what's the problem?" 

I think that's wrong in my case. ActivityManagers are provides this way in my code:
    @Provides
    @Singleton
    @Named("ContentArea")
    public final ActivityManager getContentActivityManager(final ContentMapper activityMapper, final EventBus eventBus) {
        return new ActivityManager(activityMapper, eventBus);
    }
The eventBus is provided via bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class); At the Moment i change the package the compilation fails for my activities (another question is why new ActivityManager is accepting eventBus from both packages).

Correct me if i am wrong: you suggest to give activity's start method the old eventbus (but this one shouldn't be used). but because the activity managers are calling the start method with their eventbus i have to provide activitymanagers constructed with the old eventBus? (i don't really understand the code you provided, is "injector.eventBus()" the old or the new EventBus)

Thomas Broyer

unread,
Nov 8, 2011, 9:00:59 AM11/8/11
to google-we...@googlegroups.com


On Tuesday, November 8, 2011 1:40:25 PM UTC+1, tanteanni wrote:
Thx Thomas,

"The activity has no dependency on the singleton/global event bus, and the one passed to its start() method doesn't come from GIN; so what's the problem?" 

I think that's wrong in my case. ActivityManagers are provides this way in my code:
    @Provides
    @Singleton
    @Named("ContentArea")
    public final ActivityManager getContentActivityManager(final ContentMapper activityMapper, final EventBus eventBus) {
        return new ActivityManager(activityMapper, eventBus);
    }
The eventBus is provided via bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class); At the Moment i change the package the compilation fails for my activities

OK, let's start from the beginning: what do you mean exactly by "the compilation fails" ? Java compilation ? GWT compilation ? where exactly and with which error ?

 
(another question is why new ActivityManager is accepting eventBus from both packages).

In that particular case, because it has both constructors, with gwt EventBus (deprecated) and with web.bindery EventBus; but if it hadn't (to maintain binary compatibility), as gwt EventBus extends web.bindery EventBus, polymorphism would do the rest (and thus it would maintain source compatibility).
 
Correct me if i am wrong: you suggest to give activity's start method the old eventbus

You have no choice but use the deprecated EventBus as the formal argument to your activities' start() method.
The GWT team cannot change the definition of Activity to use the web.bindery EventBus, because that would be a breaking change (you'd have to go through all your activities to change the EventBus type to the web.bindery one).
And you cannot declare it as a web.bindery EventBus (even though it's a superclass of the gwt EventBus) because Java doesn't support contravariance of argument types (that'd declare an overload, not an override; see http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Java )
 
(but this one shouldn't be used).

Why wouldn't you use it? The eventbus passed as argument to your start() method is *not* your global eventbus (as given to the ActivityManager), it's a ResettableEventBus built around it, so that you don't have to bother unregistering your handlers.
It's there to help you, so use it!

but because the activity managers are calling the start method with their eventbus i have to provide activitymanagers constructed with the old eventBus?

No (see above); it doesn't matter which kind of EventBus you give to the ActivityManager, it will wrap it in a ResettableEventBus and give that one to your activity.
 
(i don't really understand the code you provided, is "injector.eventBus()" the old or the new EventBus)

Everything in the first part uses the web.bindery EventBus.

tanteanni

unread,
Nov 8, 2011, 9:32:05 AM11/8/11
to google-we...@googlegroups.com
" OK, let's start from the beginning: what do you mean exactly by "the compilation fails" ? Java compilation ? GWT compilation ? where exactly and with which error ?"

Good Idea (an Thx for your patience - again):

If i change the binding of EventBus (bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);) from "old" to "new" package in my clientModule (Gin) the deprecated warning in
"    @Provides
    @Singleton
    public final PlaceController getPlaceController(final EventBus eventBus) {
        return new PlaceController(eventBus);
    }
" will disappear but on gwt-compilation i'll get following error (maven build):
[INFO] Compiling module de.stalabw.zensus2011.adb.AuswertungsDB
[INFO]    [ERROR] Errors in 'C:\WorkspaceADB\AuswertungsDB\target\.generated\de\stalabw\zensus2011\adb\client\gin\ClientInjectorImpl.java'
[INFO]       [ERROR] Line 895:  Rebind result 'com.google.gwt.event.shared.EventBus' cannot be abstract
[INFO]    [ERROR] Cannot proceed due to previous errors

tanteanni

unread,
Nov 8, 2011, 9:57:00 AM11/8/11
to google-we...@googlegroups.com
i guess i got it and saved my day -again.

i just eliminated all "old"(and changed where necessary) imports and put "com.google.gwt.event.shared.EventBus" in each startMethod. 
but i have some bad feelings about that
- some tests call the start methods. at the moment start(panel, new com.google.gwt.event.shared.SimpleEventBus()) works (because i know that the methods don't use the event bus - all are using the eventBus injected on construction-time) - but this could fail. so either i use only the "old" eventBus in Tests (where possible) or wrap it like the managers do in a resttableEventBus?

- this solution feels like a workaround?! i think in future there must be an new AbstractActivity with "correct" start-Method (probably a 1.4AndUpActivity ;-?)


Jens

unread,
Nov 8, 2011, 2:03:10 PM11/8/11
to google-we...@googlegroups.com
i just eliminated all "old"(and changed where necessary) imports and put "com.google.gwt.event.shared.EventBus" in each startMethod. 
but i have some bad feelings about that

Why? Isn't this the normal situation? Every Activity/Places related class can take the new web.bindery EventBus, *except* Activity.start(AcceptsOneWidget view, EventBus eventBus). But this method is only called by the ActivityManager and this class will provide an old EventBus (an old ResettableEventBus that takes your global new web.bindery EventBus as a constructor parameter) to make things work.
 
- some tests call the start methods. at the moment start(panel, new com.google.gwt.event.shared.SimpleEventBus()) works (because i know that the methods don't use the event bus - all are using the eventBus injected on construction-time) - but this could fail. so either i use only the "old" eventBus in Tests (where possible) or wrap it like the managers do in a resttableEventBus?

I would always use the new web.bindery EventBus and if needed wrap it in an old Resettable/CountingEventBus. Why do you inject an EventBus in your Activity's constructor although you get one via the Activity.start() method? You should use the one provided by the start() method, as all handlers are automatically removed once the activity stops. But maybe I misunderstood  you.

-- J.

tanteanni

unread,
Nov 9, 2011, 10:59:12 AM11/9/11
to google-we...@googlegroups.com
thx for clarification jens.

my problem is that i use the event bus within some activities outside of start(..) and there i always should use the bindary-One. So in such activities i have two different EventBuses. the bindary-One is imported the other one is explicitly set in start method. 
And to be sure that an activity never uses /imports the wrong EventBus i did it in all activities. (someone could add some code to an activity that uses/needs an eventbus and if at this point in time the wrong import is present (because the start -method needs it) it won't work - some injector error will occur)


Thomas Broyer

unread,
Nov 9, 2011, 11:35:24 AM11/9/11
to google-we...@googlegroups.com


On Wednesday, November 9, 2011 4:59:12 PM UTC+1, tanteanni wrote:
thx for clarification jens.

my problem is that i use the event bus within some activities outside of start(..) and there i always should use the bindary-One. So in such activities i have two different EventBuses. the bindary-One is imported the other one is explicitly set in start method.

Out of curiosity, why should you "always use the web.bindery one"?

Either you add handlers to it, and using the global bus directly could be a source of memory leaks (you forget to remove your handlers, and the bus then keeps holding references to your activity, even after it's stopped and supposedly disposed), adding your handlers to the bus passed to the start method would have the same effect re. your handlers, except that they're automatically removed when the activity is stopped (onStop or onCancel) so you're guaranteed to not leak.
Or you fire events, and then again, the bus passed to the start method will simply delegate to the global bus (the one passed to the ActivityManager), so it's not an issue either. Even after the activity is stop you can still fire events on that bus (if for instance you do it from AsyncCallbacks or Receivers; e.g. the user clicks "save" then navigates before the server responds, maybe you ask him to confirm –return a non-null value from maybeStop– but he chooses to go away nonetheless, so the activity is stopped; when the server responds, you can still fire an event on the bus, for instance to show a notification that the object has correctly be saved).


Oh, and the field in your activity holding the eventbus can still use the web.bindery type, as the gwt bus extends the web.bindery one:

import com.google.web.bindery.event.shared.EventBus;
class MyActivity extends AbstractActivity {
   EventBus bus;

   @Override
   public void start(AcceptsOneWidget panel, com.google.gwt.event.shared.EventBus bus) {
      this.bus = bus;
      // do your initialization stuff
   }

   private void fireFooEvent() {
      this.bus.fireEvent(new FooEvent());
   }
}

And to be sure that an activity never uses /imports the wrong EventBus i did it in all activities. (someone could add some code to an activity that uses/needs an eventbus and if at this point in time the wrong import is present (because the start -method needs it) it won't work - some injector error will occur)

To make sure you don't use/import the wrong event bus, simply watch for "import com.google.gwt.event.shared." in your files (except if you're importing GwtEvent); in most cases, I guess you'll have type mismatch errors (trying to assign a web.bindery bus to a gwt variable) or deprecation warnings (if you have a variable of type "gwt EventBus", then the compiler will resolve constructor/method overloads using that bus too, which are deprecated as you noted earlier: ActivityManager, PlaceController, etc.)
And of course, watch for these errors when compiling: "Rebind result 'com.google.gwt.event.shared.EventBus' cannot be abstract" ;-)
(I unfortunately don't have any real experience on this though, as we're stuck with an old version of GWT before things were moved to web.bindery; too many customizations –yes, you could say "abuses"– of RF that make it hard to update)

Jens

unread,
Nov 9, 2011, 11:38:13 AM11/9/11
to google-we...@googlegroups.com
my problem is that i use the event bus within some activities outside of start(..) and there i always should use the bindary-One. 

Why should you? Assuming you only have one global event bus, the one provided by the start() method and the injected one are basically the same. The one provided by start() is just a wrapper around your global event bus obtained via injection (the one you gave the ActivityManager). Every method of this wrapper is delegated to your global event bus.

Its totally fine to store the event bus and also use it in other activity methods.

Activity.start(...., EventBus eventBus) {
  this.eventBus = eventBus;
  this.eventBus.addHandler(....);

Sure if you store it the activity has an "old" import statement as the start() method provides an "old" event bus. But on the day GWT kicks the old event bus you can simply run a global search and replace on your java files to correct the imports (class name is the same)

-- J.

Jens

unread,
Nov 9, 2011, 11:40:08 AM11/9/11
to google-we...@googlegroups.com
Hehe I hate it when this yellow "1 new message" box appears just when clicking on "post" and both new posts are basically the same :)

tanteanni

unread,
Nov 11, 2011, 3:27:56 AM11/11/11
to google-we...@googlegroups.com
since the beginning of using activities i asked myself why some "dependency injection" examples injected an eventbus and don't use the one that start() delivers. i thought that the pattern - inject all stuff you need.

But thx to you-both this question is answered - don't inject the bus! use the one from start(). So not only that little Problem is solved but i also learned a lot more - again.


So the best documentaion for gwt is still this group - (i am not sure if this is good or bad) 

Thomas Broyer

unread,
Nov 11, 2011, 7:31:28 PM11/11/11
to google-we...@googlegroups.com


On Wednesday, November 9, 2011 5:35:24 PM UTC+1, Thomas Broyer wrote:
(I unfortunately don't have any real experience on this though, as we're stuck with an old version of GWT before things were moved to web.bindery; too many customizations –yes, you could say "abuses"– of RF that make it hard to update)

FWIW, I shouldn't work on that Armistice Day (holiday in France), but this has been haunting me for weeks, so I took some time to (again) try to update our app to the latest and greatest (a.k.a. latest trunk).

I blindly replaced all EventBus, AutoBean and RequestFactory imports from com.google.gwt to com.google.web.bindery, then fixed the compile errors by using the FQCN on activity's start() method, and in a few places I had to revert to com.google.gwt.event.shared.HandlerRegistration (when using widget events, or defining our own widget events; where we used com.google.gwt.event.shared.GwtEvent).
That was enough to fix both javac and GWT Compiler. Now I have many server-side RequestFactory tweaks to port to the "new" RequestFactory; and that won't be that easy unfortunately...
Reply all
Reply to author
Forward
0 new messages