Questions and concerns with HandlerManager

36 views
Skip to first unread message

Joel Webber

unread,
Aug 7, 2009, 12:11:18 PM8/7/09
to GWTcontrib, Ed Bras
All,

There has been a fair amount of discussion about the 1.6 HandlerManager and related code, along with a few issues submitted (primarily by Ed), and I'm starting this thread to try and reach some kind of consensus on what, if anything, needs to be changed about it. Please note that we need to find the simplest things we can do to enable everyone's use cases, without creating a new event system from whole cloth, or adding a lot of complexity to simple use cases. Please help me to reach convergence so that we can get this taken care of reasonably soon.

The following are the three issues I'm aware of. I'll work backwards, from simplest to most complex.

1. Switching the 'source' of an event object, primarily for composite events.
We actually did consider this in the original design. This is the normal pattern for re-firing an event from a composite (the composite has a field called 'button' that represents a wrapped widget):

    HandlerRegistration addClickHandler(ClickHandler h) {
      return button.addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
          fireEvent(event);
        }
      });
    }

This does require the instantiation of an extra inner class, but the design allows the HandlerManager to re-use event objects, even when they're fired through multiple layers of widgets and composites.

2. Making the source of a HandlerManager generic (issue 3636).
Mark Renouf's comment in this issue was spot on: Doing so would break the delegation described above. I don't see any way around this. Please let me know if I've missed something (but please no proposals that would involve redesigning the whole event system).

3. Adding an "interceptor" to the HandlerManager (issue 3628).
I'll be honest. I've spent all morning trying to figure out what's being requested here, and I just don't quite get it. I'm sure there's a real problem being described here, but I think I need a very concrete use-case that can't be easily implemented the way things are to fully understand it.

Thanks for your help,
joel.

Ed

unread,
Aug 7, 2009, 1:34:25 PM8/7/09
to Google Web Toolkit Contributors
It costs me a bit to go back in time as these issues are already from
some time back..
Let me try to give some input on these points.

2) I don't fully understand what the problem is here. Could you give
an example that shows that it breaks?
Anyway, let me explain a bit how my handlermanager works as I don't
seem to have this problem yet... but neither do I think it solves
it.... (I did this somewhere on the forum already... I think but but
can't find it 123)

In my implementation I can specify the source through generics as I
found it important due to experience in the past. It makes it more
clear and tight about what to expect in the listener event (the
element of least-suprise).
The steps for firing an event are almost the same, except:
- I bought myself some extra freedom by introducing an extra
eventbuilder object that contains the event (kind of intermediate
object). The event is a stupid value object without any extra logic
like the GWT event. This is takes away the need for the gwt package
protected event methods btw. I moved the logica that GWT put in the
gwt event in my eventbuilder, such that they al have their simple and
clear responsibility. I think the current gwt event contains/does too
much. I experience this when trying to extend/use it, this is
difficult/not possible...

The event builder will call the listener and pass in the contained
event. I use the builders as flyweight object and reuse them.
The event builder is passed to the fireEvent(..) method of the
HandlerManager.
This is an interface of which if have several sub interfaces to add
extra functionality like the interceptor construction.
The HandlerManager will ask the event builder to fire the event
passing in the register that holds all the listeners. The event
builder will then ask the register to fire the event, passing in
himself. The register will retrieve all interested listeners through
the type that is contained in the event builder, and will then ask the
event builder to dispatch the event to the listener, passing in the
listener (one by one)....
I might sound a bit cumberslume.. al these forward calls (visitor
pattern) (at least I think it is).. but I needed it to keep it tight
and use my generics correctly... If you want allll the dirty details I
really have to dig in to it again...

Anyway: the above construction I needed to win extra freedom to add
extra functionality like the interceptor, stop delegation, etc.. and
to work with different implementations againts common interfaces
(which currently isn't possible with the GWT implementation as the gwt
event contains too many things: logica and data. Ofcourse this is
desired looking from a rich object perspective, but you don't want to
expose all the delegation to the subscribers... I mean: they can stop
the delegation, but that's about it...
Maybe the above will give some idea's.

3) Ok, let me give an example and hope I have some luck here... ;) I
remember we had this same discussion about primitive-simple Widget
interfaces, you asked me the same thing (together with Bruce), I gave
some concrete interfaces.. and never heard anyting :(...

My app is very simple in layout: a menu on the left and the content on
the right. You can navigate to another piece of content by clicking on
the next/prev button in the content screen part or by clicking in the
menu.
If the user navigates away from the current content screen (by
clicking next/previous... or the menu), and the current shown content
isn't valid, he will be asked for a confirmation. If yes, the action
(=going to the new content and saving the current shown content) will
be performed, if no, the action is canceled and he stays on the same
content screen.
I implement this through an interceptor (aynchrone in this case) that
will take care of the confirmation and some other side-actions. It
makes it clean and transparent.
What I do roughly: I inject the interceptor in the presenter. When the
select value in the model changes it will first inform the interceptor
with a callback. The call back contains different methods that are
called by the HandlerManager implementation to indicate success/
cancelation. In case of success (the user clicks Ok), it will inform
the callback about this such that the property change can be made
permanent. The handlermanager will then inform the listeners and after
that call the callback to indicate that they are all informed....
If you need more details, let me know ?


After describing the above, you might understand that it's desirable
to open up the GWT Handlermanager to add these functionality directly
to it, instead of making a copy and changing it...... Probably this is
need in my case anyway... but still...

Hope this helps...

Joel Webber

unread,
Aug 7, 2009, 4:07:02 PM8/7/09
to Google-Web-Tool...@googlegroups.com
On Fri, Aug 7, 2009 at 1:34 PM, Ed <post2...@hotmail.com> wrote:

It costs me a bit to go back in time as these issues are already from
some time back..
Let me try to give some input on these points.

2) I don't fully understand what the problem is here. Could you give
an example that shows that it breaks?

It's actually worse than I thought. If I add a type parameter to HandlerManager, I get something like

  class HandlerManager<Source> { ... }

But I have no way to specify the source type when it's declared in Widget:

  class Widget {
    HandlerManager<???> handlerManager;
  }

The Source type parameter would force me to declare a separate HandlerManager field in each subclass of Widget. But then I can't subclass a widget and get the source type correct -- I'd need *another* handlerManager field.
To be honest, I'm having a really hard time understanding the structure you're describing. Maybe a bit of (heavily elided) code would help clarify it?

After describing the above, you might understand that it's desirable
to open up the GWT Handlermanager to add these functionality directly
to it, instead of making a copy and changing it...... Probably this is
need in my case anyway... but still...

If you could describe *precisely* what you think should be "opened up" in HandlerManager, it would help me to make a reasonable judgment. As it stands, it all seems very vague to me.

Thanks,
joel.

Ed

unread,
Aug 7, 2009, 4:43:52 PM8/7/09
to Google Web Toolkit Contributors
> class HandlerManager<Source> { ... }

Interesting how you put Generics in the HandlerManager ....
Of course this is a no go area as you explained.
Try my HandlerManager scenario like I described above; only the event
contains the actual source generics, and of course not he
HandlerManager...
Let me know if you want some code of this ? So I can grep something
together... I might need a bit of time for that... and let me know
where to send it to?

> To be honest, I'm having a really hard time understanding the structure
> you're describing. Maybe a bit of (heavily elided) code would help clarify
> it?

Hmmmm... I could give some code, but I think in words the need for the
interceptor is clear:
The user selects something and the interceptor will indicate if the
selection is allowed to be committed (like a 2-phase db transaction)
or not..
Can you give me more details about what you not understand here
please?
I am afraid that the code only make it less understandable as it's
complex.. due to the asynchrone behavior.


> If you could describe *precisely* what you think should be "opened up" in
> HandlerManager, it would help me to make a reasonable judgment. As it
> stands, it all seems very vague to me.


Hmmmm... can't remember the *precise* details anymore... it was
already some time ago... :(
One thing I remember was that I wanted to change the source in the
HandlerManager, which wasn't possible as it can only be set through
the constructor..




On Aug 7, 10:07 pm, Joel Webber <j...@google.com> wrote:

Bruce Johnson

unread,
Aug 7, 2009, 4:55:25 PM8/7/09
to Google-Web-Tool...@googlegroups.com
Are there lots of folks on the list that have the same sorts of feedback on HandlerManager? I ask because, as a fly on the wall here, this conversation doesn't sound like it's converging, and I'd like to declare this thread dead for now so that we can move onto other things. We have a lot of other things to be giving attention to so that we can get GWT 2.0 out. If we need to revisit these issues in the future, we certainly can.

-- Bruce

Ed

unread,
Aug 7, 2009, 5:10:13 PM8/7/09
to Google Web Toolkit Contributors
Then I would declare it dead Bruce!

With all do respect: I do very complex things with GWT and do walk on
his boundaries...
And to my experience.... -> I am a bit lonely out here... (yes I know
it sounds a bit arrogant...)
And yes, I agree that you guys have better things to do to make GWT
first more mature before they support these complex things...

Buttt... it would be nice if these things aren't forgotten and put on
the nice-to-have list... and not on the forget-list.

I think that adding (more) primitive (characteristic) widget/panel
interfaces, like we discussed before has an higher priority, so I hope
you guys add this to gwt 2.0. I am still suprised about the few people
complain about this. But I have pointed out concrete clear cases that
show the need for this...(like you asked before)

Just my thoughts...
BTW: Joe if you want some code about my HandlerManager to be able to
define the source through generics, let me know...


On Aug 7, 10:55 pm, Bruce Johnson <br...@google.com> wrote:
> Are there lots of folks on the list that have the same sorts of feedback on
> HandlerManager? I ask because, as a fly on the wall here, this conversation
> doesn't sound like it's converging, and I'd like to declare this thread dead
> for now so that we can move onto other things. We have a lot of other things
> to be giving attention to so that we can get GWT 2.0 out. If we need to
> revisit these issues in the future, we certainly can.
>
> -- Bruce
>

Bruce Johnson

unread,
Aug 7, 2009, 5:13:43 PM8/7/09
to Google-Web-Tool...@googlegroups.com
Dead! (for now)

Ed

unread,
Aug 8, 2009, 4:46:36 AM8/8/09
to Google Web Toolkit Contributors
Even do it's dead, let me give some pointers on the Source generic
issue that came in mind:
- My Source isn't part of my HandlerManager, as in the example of Joe
above.
- My Source is contained in the event builder and his type indicated
on the event builder through Generics.
- The source can be passed in every time an event is fired if you
wish.
- I don't think that event delegation is any problem. If I understand
you correctly, I certainly do this and have no problems with it.
Here example code of usage (The Form Generic is the Source):
this.formValidationListenerReg = input.addValidationChangeListener(new
OnValueSourceListener<Form, Boolean>() {
public void onValue(final OnValueSourceEvent<Form, Boolean>
event) {
handleFormValidationChange(event.getValue());
}
});

I am now using it since about 6 months a lot (I work with GWT 24 hours
the last few years) and it works very well...

Have a nice weekend

Chris

unread,
Aug 28, 2009, 1:52:17 PM8/28/09
to Google Web Toolkit Contributors
I realize this is a bit of an old thread; however, I ran across a use
case where I would like to be able to modify HandlerManager. In our
application we would like to be able to "stop" an event from being
fired further.

One example, we have three event handlers that can be added A, B, C
(validation, required check, and save rpc). We add the handlers to a
button in that order when needed (sub class determine which handlers
to add). We want to be able to specify in A or B handler that the
event should stop propagating to other handlers.

We tried a couple of different things (including starting to add our
own event handling logic) and we settled on two changes to GWT
itself. We added a method to GWTEvent:
- public void stop(); /* record that the event should not be passed
to more handlers */
- public void isStopped(); /* is the event stopped for further
processing */
- public void unStop(); /* reset the stop flag to be false - did in
case event is reused */

In our event handlers we can now call event.stop() to stop further
propagation.

In HandlerManager.HandlerRegister we modified

private <H extends EventHandler> void fireEvent(GwtEvent<H> event,
boolean isReverseOrder) {
Type<H> type = event.getAssociatedType();
int count = getHandlerCount(type);
if (isReverseOrder) {
for (int i = count - 1; i >= 0; i--) {
H handler = this.<H> getHandler(type, i);
event.dispatch(handler);
if(event.isStopped()) { // CUSTOM: event stop processing
event.unStop(); // did this in case events are reused
break;
}
}
} else {
for (int i = 0; i < count; i++) {
H handler = this.<H> getHandler(type, i);
event.dispatch(handler);
if(event.isStopped()) { // CUSTOM: event stop processing
event.unStop(); // did this in case events are reused
break;
}
}
}
}

Just thought I would send a quick note in case future changes are
being considered for HandlerManager (realizing 2.0 time frame is
probably off the table).

Chris....

Ray Cromwell

unread,
Aug 28, 2009, 2:16:57 PM8/28/09
to google-web-tool...@googlegroups.com

I had a discussion about this and other propagation issues for non-DOM events a long time ago when the 1.6 event system was being designed. At the time, I believe the consensus was that propagation for custom events was a complex subject and should be left for developers to subclass HandlerManager and GwtEvent. For example, I had a quite complex use case where I was implementing synthetic widgets drawn on a Canvas and I needed both capture and bubbling behavior with totally custom events. Thus, I would subclass GwtEvent as VirtualEvent and add stopPropagation/preventDefault/etc. I would also subclass HandlerManager so that it would perform the checks you outlined above, as well as propagating events between sources.

This was on the old incubator, and it looks like in 1.6, some decisions were made that makes this more difficult now, as HandlerRegistry is a private class which cannot be overriden (probably for efficiency), thus HandlerManager is kind of frozen in stone, so you either have to patch it (it seems too late for this), or just copy it wholesale. There's no real harm in creating a totally separate HandlerManager implementation, like a HandlerManagerWithPropagationModel.

-Ray

Chris

unread,
Aug 28, 2009, 3:00:28 PM8/28/09
to Google Web Toolkit Contributors
Ray thanks for the information. Sounds like my novel idea :) has been
hashed over a few times.

Hopefully for the next version (3?) collectively there will be some
work to try and figure out how to open the event handling mechanism a
bit to support developer extensions.

They idea about subclassing HandlerManager sounds fine, but I don't
see how to make it work with existing widgets. Also, the
Widget.ensureHandler() is package private, so subclassing specific
widgets doesn't help me - even if I could get them to fire the right
event. While I don't like modifying GWT proper, I'm not in the mood
to manage an event sub system where I am basically delegating from the
GWT events to my event handling (even if it is basically copy and
paste).

I'll keep that idea in the back of my mind in case I have other use
cases that require further extension. Besides, I have two other small
changes to GWT (modify a constructor access permission on
DecoratedPopupPanel and replace the Date_serializer) so what is one
more managed change :)

Thanks again,
Chris....
Reply all
Reply to author
Forward
0 new messages