Home > Gwt, Java > Business Events with GWT 1.6

Business Events with GWT 1.6

Now that I have upgraded to 1.6, I’m looking at the new Event system.  Moving from the “Listener”‘ model to the “Event” model is pretty straight forward.  You can read all of the benefits of the new Event code on the GWT site.  For me, the best benefit is that I can use the new architecture to replace a home grown event bus.  Our existing infrastructure is very similar but not quite as robust.  The GWT docs are a good starting point and will walk you through how to use the new Event Handler methods with existing widgets.  Upgrading is a fairly painless change – just takes time to update everywhere.

The real payoff for me came when I added events.  This takes a little more work; but seems to be worth it.  The primary advantages for my framework are:

  • lower direct coupling between components
  • a given component can register for multiple different events (I was using a large switch statement after evaulating the “type” of event under the old architecture)

To use create a new Event, the following needs to be created.  I combined the Event and Handler into 1 class:

import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
 
public class MyEvent extends GwtEvent<MyEvent.IMyHandler>{
 
   //marker for handler logic in registration method
   public interface IMyHandler extends EventHandler{
      void onLoad(MyEvent event);
   }
 
   //marker on calling
   public interface ITakesMyEvent extends EventHandler{
      void process(MyEvent event);
   }
 
   private static final GwtEvent.Type<MyEvent.IMyHandler> TYPE = new GwtEvent.Type<IMyHandler>();
 
   public static GwtEvent.Type<IMyHandler> getType(){
      return TYPE;
   }
 
   @Override
   protected void dispatch(MyEvent.IMyHandler handler){
      handler.onLoad(this);
   }
 
   @Override
   public GwtEvent.Type<IMyHandler> getAssociatedType(){
      return TYPE;
   }
}

On your component you need to add a couple of methods:

import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
 
public class MyComponent {
 
   private HandlerManager handlerManager;
 
   /**
    * Adds this handler to the widget.
    *
    * @param  the type of handler to add
    * @param type the event type
    * @param handler the handler
    * @return {@link HandlerRegistration} used to remove the handler
    */
   //copied from GWT 1.6 Widget
   protected final <H extends EventHandler> HandlerRegistration addHandler(GwtEvent.Type<H> type, final H handler){
      return ensureHandlers().addHandler(type, handler);
   }
 
   /**
    * Ensures the existence of the handler manager.
    *
    * @return the handler manager
    * */
   //copied from GWT 1.6 Widget
   private HandlerManager ensureHandlers(){
      return handlerManager == null ? handlerManager = new HandlerManager(this) : handlerManager;
   }
 
   /**
    * Register a component for the specified event.
    */
   public void register(final MyEvent.ITakesMyEvent component){
      addHandler(MyEvent.getType(), new MyEvent.IMyHandler(){
         public void onLoad(MyEvent event){
            component.process(event);
         }
      });
   }
 
   /**
    * Fire an event.
    */
   void fireEvent(GwtEvent<?> event){
      handlerManager.fireEvent(event);
   }
}

In your component you then fire the event handler:

public void doSomething(){
   System.out.println("Doing Something");
   fireEvent(new MyEvent());
}

Your “listening” component would have look like:

public class TestComponent implements MyEvent.ITakesMyEvent {
   public TestComponent{
      MyComponent component = new MyComponent();
      component.register((MyEvent.ITakesMyEvent)this);
   }
 
   public void process(MyEvent event){
      //do something with event
   }
}

With GWT 1.6, we now have the ability to add very fine grained event processing to our components.

My next step is to look into the memory handling aspect to make sure all of the “Event” objects are removed from memory when the declaring object (TestComponent above) is removed.  I’m fairly confident this is the case.  I just noticed some “removal” code in the PopupPanel class that I need to investigate further.

 
Categories: Gwt, Java
  1. April 30th, 2009 at 08:19 | #1

    I’ve very excited by this, especially the memory management aspect. I can’t wait for the next post.

    I know that this probably isn’t related, but do you know of a way to add additional DOM events, for instance some of the ones that the iPhone browser has, like orientationchange, touchstart, touchmove, touchend, etc?

  2. Mark Renouf
    June 3rd, 2009 at 13:46 | #2

    @Clay Lenhart

    Yes! In theory, this is now possible. You may define new events by extending DomEvent.

    public class ClickEvent extends DomEvent {
    private static final Type TYPE = new Type(
    “touchstart”, new ClickEvent());
    }

    But for this to work, you’ll also need to create a new Deferred binding for DOMImpl which knows about these events. Define a new bitfield for the event type and add the code which attaches the event listener. (See DOMImplMozilla#sinkEventsMozilla for an example)

  3. Daniel Lindberg
    June 11th, 2009 at 16:14 | #3

    How would you go about if you needed to fire multiple events from one component? Could you make the interfaces in “MyEvent” more general and move them outside the event class or would you need them in all events you create? Same with the register method in the component, would you need to create one register method for every event you´d want to fire, or could you make one that would be more general?

  4. chane
    June 12th, 2009 at 00:32 | #4

    We have components that do fire many different event types. There is a register method on the component for each EventType that it fires. We wanted fine grained events since we hook up components for only some specific events.

    An event only has the semantic value that you assign to it. The event can be as broad or generic as you want. We went very fine grained.

    For registration methods, you could have a hierarchy to your events and that would let you use one register method. That one register method would then have to be “smart” and know what to do with each different kind of thing that could be registered. With our usage, a register only takes one EventType and is very easy to write.

    Also, I made a mistake in the example (corrected now). I had forgotten to put the full TYPE definition in the example for the MyEvent:

    private static final GwtEvent.Type TYPE = new GwtEvent.Type();

    Should have been (and is now):

    private static final GwtEvent.Type TYPE = new GwtEvent.Type();

  5. Daniel Lindberg
    June 12th, 2009 at 05:21 | #5

    Thanks Chris, your examples have been very helpful to me (and others too I imagine). I do have some other questions however. Don´t know if there´s somehing weird with my environment or if the example is just missing some code.

    I get compiler errors for the function

    //copied from GWT 1.6 Widget
    protected final HandlerRegistration addHandler(GwtEvent.Type type, final H handler){
    return ensureHandlers().addHandler(type, handler);
    }

    Had to change this to

    //copied from GWT 1.6 Widget
    protected final HandlerRegistration addHandler(GwtEvent.Type type, final H handler){
    return ensureHandlers().addHandler(type, handler);
    }

    I also had problems with

    @Override
    protected void dispatch(MyEvent.IMyHandler handler){
    handler.onLoad(this);
    }

    For some reason I get errors saying that I must implement the inherited method
    dispatch(EventHandler). So for some reason MyEvent.IMyHandler isn´t recognized as a subclass of EventHandler. Had to change this to:

    @Override
    protected void dispatch(EventHandler handler){
    MyEvent.IMyHandler event = (MyEvent.IMyHandler) handler;
    event.onLoad(this);
    }

    This last example seems strange to me, it think your example ought to work?

    • Chris Hane
      June 12th, 2009 at 12:34 | #6

      Daniel – sorry for the errors, the code I wrote in the post was actually my attempt to generalize what we do in our code. I obviously didn’t do a good job. Here is the actual code for one of our events. Actually, I had the hardest time trying to paste in our code. It keep munging it. Anyway, I went back and edited the post to make the example Event compile. I think what happened was it got munged in the original post. My comment look identical to the post – so I believe wordpress is trying to be smart….

      Hope this works better for you. I know this works as the only thing I didn’t copy was the package declaration :)

      Chris….

  6. Chris Hane
    June 12th, 2009 at 12:49 | #7

    I have updated both the event and component code. Turns out wordpress (or a pluging I have installed) munges less/greater than when using the visual editor.

    I have fixed the code example and they should compile now.

    Sorry for the confusion.
    Chris….

  1. No trackbacks yet.

Spam Protection by WP-SpamFree