Errai: The browser as a platform

Friday, August 9, 2013

Block Drop -- A fun demo and tool for learning the fundamentals of Errai

Three months ago I became the Red Hat intern for Errai. Shortly afterwards I embarked on a modest task: to make a demo showing the world how awesome Errai is. I am now happy to present Block Drop, a simple multi-player, Tetris-like web game for the desktop or touch screen browsers.

If you're new to Errai, Block Drop is a great example of how Errai can be used to simplify the task of making rich and interactive web applications. In particular, Block Drop made use of the following elements of Errai:
  • CDI Events
  • Message Bus
  • Errai UI
  • Data Binding
In this post I will cover some basic use cases of CDI Events with examples from Block Drop. (Note that code snippets below may be slightly modified for readability and clarity. You can check out the full source here.)

CDI Events

Making a Simple Game Lobby

In Block Drop players must log into a lobby page before they can begin playing. From this page we want players to be able to do the following tasks:
  1. See other idle players
  2. See current games being played
  3. Start new games, possibly inviting other players to them
  4. Join currently existing games
Furthermore, the lobby state will frequently be changing, and we want all clients to have up-to-date information.

CDI Events to the Rescue

In order to satisfy (1) and (2) above, we need a way to broadcast a list of players and a list of games to all connected clients. Thankfully this task is a piece of cake with Errai. First we need an object to store the information we need for transit. For the sake of simplicity, I have chosen to send the entire lobby state on each update, but in a real-world application one might prefer to send an incremental update.

/** 
 * A portable bean for transmitting lists of players in lobby and games in progress. 
 */ 
@Portable 
public class LobbyUpdate { 

  /** A map player ids to Player objects (of players in lobby). */
  private Map<Integer, Player> playerMap = null;
  /** A map of game ids to Game objects (of games in progress). */
  private Map<Integer, GameRoom> gameMap = null;

 /** 
   * Construct a LobbyUpdate instance. 
   *  
   * @param playerMap 
   *          A map of player ids to players, for all the players in the lobby. 
   *  
   * @param gameMap 
   *          A map of game ids to games, for all the currently in progress games. 
   */ 
  public LobbyUpdate(Map<Integer, Player> players, Map<Integer, GameRoom> games) {
    this.playerMap = players; 
    this.gameMap = games; 
  }

  // Getters and setters omitted

Like the name suggests, a LobbyUpdate object exists for the sole purpose of transmitting information about the state of the lobby. You'll notice that:
  • playerMap contains the idle players
  • gameMap contains the current games
  • Both of these fields have getters and setters (omitted here for brevity)
  • The class is annotated with @Portable
The Portable annotation is what will allow us to send and receive this object over the network. What we need next is way to send LobbyUpdates to clients. Since we want to broadcast this update to all clients indiscriminately, we'll use a CDI Event.

In it's simplest case, a CDI Event in Errai is a simple way for a server to send an object to all of the connected clients. By using an Event object, we will be able to fire LobbyUpdate objects to all clients with one simple command.


  /** Used for sending lobby updates to clients. */ 
  @Inject 
  private Event<LobbyUpdate> lobbyUpdate; 

  /** 
   * Fire an LobbyUpdate to connected clients. This should result in clients
   * refreshing their lobby lists. 
   */ 
  public void sendLobbyList() {
    lobbyUpdate.fire(new LobbyUpdate(lobbyPlayers, games));
  }

The above is an excerpt from the game's Server class. The private field, lobbyUpdate, is the Event object used in the method sendLobbyList to transmit LobbyUpdates. The @Inject annotation tells Errai to assign an event to the lobbyUpdate field when the server is started.

So what happens when this event is sent to the clients? On the client side we need tell the clients to observe LobbyUpdate. So in the Lobby class we add the following method.

  /** 
   * Update the lobby list model and display with newest lobby update from the server. 
   */ 
  public void updateLobby(@Observes LobbyUpdate update) {
    // Updating logic goes here 
  }

The @Observes tells the framework that this method should be called when an Event containing a LobbyUpdate is received. And that's all it takes to transmit the state of the lobby.

CDI Events from the Client

To go about task (3), we need to send an invitation from one client to a subset of the other connected clients. From the previous code examples, you might be expecting something like this:

@Override 
public void onClick(ClickEvent event) {
  Invitation invite = new Invitation(); 
  // Invitation setup logic goes here...

  gameInvitation.fire(invite); 
}

This click handler is called in the lobby when a user presses the "New Game" button. The Invitation object is a @Portable class with setters and getters as its only methods, much like the LobbyUpdate class shown previously. On the last line, the event is fired using gameInvitation, an Event object, which was created using the @Inject annotation as in the previous example.

This is a good start, but the only hiccup is that a CDI Event fired from a client will only go to the server. So we'll need a method to catch and relay this event at the server.

/** 
 * Respond to an invitation by relaying it to the appropriate client. 
 */ 
public void handleInvitation(@Observes Invitation invitation) {
  // Relaying logic goes here 
}

Limitations of CDI Events

But what exactly is the relaying logic that will go in the handleInvitation method above? Can we target specific clients with events? The answer is that we cannot. At least, not with events as we've seen them so far.

In my next post, I'll discuss the Errai Message Bus and how it can be used to relay messages to specific clients as well as lots of other neat things.

5 comments:

  1. Thanks, this is really helpful, and appreciated!

    ReplyDelete
  2. Really Appreciated! I have a question. What does mean by , "We cannot target specific clients with CDI events" ?
    Thanks!

    ReplyDelete
    Replies
    1. It is possible for the Server to have a conversation with a client from which the Server has received an event.

      But it isn't possible for the Server to initiate a CDI Event to be received by by a specific subset of client. If the Server fires an Errai CDI event that is not conversational, it will be sent to all connected clients.

      Please let me know if my explanation was not descriptive enough.

      Delete
  3. I'm very happy being Herpes free now. It was a sad incident that was announced to me after the check up in the hospital and I was diagnosed of HSV 2. I thank God now for using Dr.odey Abang to cure my virus. I'm not ashamed to say this because no virus of such can be detected in me. I'm Charlotte from Columbia. I thought about it many Times when I heard about this Herbal cures for Herpes. I was really happy when I came across blogs of comments of Doctors who run cures sicknesses and was comfortable to try Dr. Abang from patients testimony I came across here on my online page. I knew now they are real Africa herbalists who run cures for Herpes. There's every opportunity to be cure with natural herbs, because all medical prescriptions are derived from herbs and roots. Its really hard time living with Herpes on drugs which can't get you cure. I tried this and I can boost of myself now as a woman. I need to be loved not to lost, get your instant cure to all sicknesses from Dr, Odey Abang.
    He cures HSV,HPV,Cancer,low spam count and much more from the evidence I saw 💯 % sure no site effects with active immune booster

    Email him for you cure
    Odeyabangherbalhome@gmail.com
    WhatsApp/calls
    +2349015049094

    ReplyDelete
  4. Nothing is not possible in this word.
    Herpes I cried out for 8moths had a cure and was making use of the Medication that never wanted a life living on drugs, I applied Antibiotics, he prescribed for me the acyclovir(Zovirax), famciclovir (Famvir), andvalacyclovir (Valtrex).
    They never get me cured.
    My God keep blessing you and your Family. Dr
    ODEY ABANG, your a powerful Herbalist fir your work in my life
    I wish you know how I feel inside me when I was making use of does tablets that never could there get me cured. I had to search about some of my favourite blogs when I thought about Dr Odey abang from the testimonies of patients and I remember a friend who told me I should try Dr. Odey Abang herbal medicine. He told me the man can cure me,but was shy and feel its dirty taking in herbs made with African herbalists.
    You need to know I would have been cured before now since I knew him then, but still interested in letting you that was my punishment.
    Thanks reading my article, feel good and not make my mistake, I love testimonies and explanations of the new beginning is all I hope for
    Think about your live and use herbs to get you cured of your challenge on
    HIV/Aids
    SYPHILIS
    DIABETES
    CANCER
    ALL CAN BE CURED WITH MANY OTHERS BY DR. ODEY ABANG
    His email is for you so you speak to him

    Odeyabangherbalhome@gmail.com
    WhatsApp number +2349015049094

    ReplyDelete