Thursday, June 12, 2014

Google Web Toolkit (GWT) Event Bus

Recently doing some GWT development and wanted to expand an example of the toolkit's event bus.
This contrived example doesn't involve widgets, or UI handling and is only meant to highlight the principle using simple example/pseudo-code. This assumes some knowledge on the internal workings of the GWT Event Bus or observer design pattern, treated as a black box here.

Imagine a virtual restaurant where you have a cook, waiter, and a customer.

The business process is, "The waiter takes the customer's order and gives it to the cook."
In this familiar scenario you have; cook, waiter, order, and customer.

In the GWT Event Bus world you have Events, Event Handlers, and Entities(Widgets, Objects etc).

Mapping to our little scenario thusly.

Events {OrderPlacedEvent}
Event Handler {OrderPlacedEventHandler}
Entity {Waiter, Customer, Order}

The real question is, how to design for an event bus, or, what to design first?

Handlers are used by entities that need to "handle" events.  Our waiter is interacting directly with the customer and so doesn't need to handle an order "event", he's the interface (virtually maybe) taking/constructing the orders. The cook on the other hand is in the kitchen and busy doing non customer related tasks, but he's very interested in orders so he can do his job of making the food.

So, the cook wants to be informed of orders being placed, and what they are, and the waiter will be the one to inform. With the event bus ANYONE can be informed about the order immediately as it's placed, cooks, managers, supply systems, etc.

First thing is to create the Handler. The reason is that the Event will actually need to register the Handler Type in the Event bus, and your Event will also reference it.

/**
 *
 */
public interface OrderPlacedEventHandler extends EventHandler {

     void onOrderPlaced(OrderPlacedEvent event);

}

Now we have a handler interface with a method to invoke with an event IF one occurs.

Next we create OrderPlacedEvent,  but first the order would be helpful.

/**
 *
 */
public class Order{ 

      private List<FoodItems> items;          

      public Order(FoodItems...items){
            items = new ArrayList<>(Arrays.asList(items));
      }

      public List<FoodItems> getItems{
             return this.items; 
      }
      ...
}

The actual Event, conventions as per GWT plus a reference to the order.

/**
 *
 */
public class OrderPlacedEvent extends GwtEvent<OrderPlacedEventHandler>{

       public final Order order;
       public static final Type<OrderPlacedEventHandler> TYPE =
                                     new TYPE<OrderPlacedEventHandler>();

        public OrderPlacedEvent(Order order){
              this.order = order;
        }

        public Order getOrder(){
              return this.order;
        }

       @Override
        public Type<OrderPlacedEventHandler> getAssociatedType() {
              return TYPE;
        }

        @Override
        protected void dispatch(OderPlacedEventHandler handler) {
               handler.onOrderPlaced(this);
        }

}


The cook needs to register the handler and do something with the return value, in this simple case he adds it to the internal list of orders he's working on. The event bus listens for the TYPE to arrive and then iterates through every registered handler calling it's implementation as defined in dispatch.

/**
*
*
*/
public class Cook{

     private List<Order> orders = new ArrayList<>();

     public Cook(EventBus bus){
                eventBus.addHandler(new OrderPlacedEventHandler(){
                                void onOrderPlaced(OrderPlacedEvent event){
                                                   addOrder(event.getOrder);
                                                   }}, OrderPlacedEvent.TYPE);
     }

     public addOrder(Order order){
              orders.add 
     }     
}


Waiter will be the one to "fire off" an order placed event to let everyone know at the end of his order taking process.


/**
 *
 */
public class Waiter{

    private EventBus eventBus;
    
    public Waiter(EventBus eventBus){
            ...

     }

     public void takeFoodOrder(Order order){ 
           ...
         eventBus.fireEvent(new OrderPlacedEvent(order));

      }

}



That's it! Hope it clears up some of the design and workings using this simple scenario.  I highly suggest using the EventBinder when coding in GWT proper instead the classes you see here, does all the same things but it's less coding!