Errai: The browser as a platform

Monday, August 26, 2013

Mobile design with Errai

Recently we had quite some discussions on our IRC channel about mobile user interface design with Errai. I think that what we've discussed will be interesting for a larger audience.

The question that came up was: Should hybrid applications be designed and behave like native mobile applications?

The mobile applications you develop with Errai are so called "hybrid apps", basically a native “shell” that executes HTML and Javascript. So, the UI will look and feel more or less the same on all supported devices (factoring out rendering differences) and will not be geared towards a specific platform.

We could try and emulate native behaviour but this could lead to what is know as the Uncanny valley, a term from robotics and animation that refers to the problem of an interaction or feature designed to mimic human behaviour that just doesn’t feel right to actual human observers. So, rather than providing a good user experience it causes a repulsive effect that occurs when you get very close to real human behaviour, but not quite there.

Have a look at the scary android, to 'feel' exactly what I'm talking about!

Simulating the native look and feel in hybrid applications could lead to that same negative effect. This is one of the reasons why jquery mobile is designed independently of specific platforms, although some fork it and make it look native again.

One way to easily create something that feels mobile without trying to look native is to use a CSS framework. The latest Twitter bootstrap and Foundation 4 embrace what they call "Mobile First" where you first build your user interface for mobile and then add more "complexity" later on. Errai UI is great when it comes to use CSS frameworks like these because you can quickly create your mockups and then reuse these in your app.

Here is one I've created with Twitter bootstrap for example. I'm not a designer and found it easy to build this mobile UI. I am sure anyone can create something in plain HTML and CSS that “feels” like a mobile app using these tools.

On the other hand, if you want to build a quick prototype of an mobile app you might want to combine Errai with something like mgwt. One of the reasons for frameworks to start emulate the native UIs is that users will automatically know how your app works.

There are also some popular applications that are avoiding these issues altogether by relying on their own custom look and feel (e.g. Skype and GMail). They focus on having their own brand identity aligned on all devices. If you work with good designers you can have a brand that looks great on all platforms.

So, what do you think? Should we support both hybrid and native applications with Errai? Even though there is this uncanny valley your app might fall into? Do you still want to create a mobile app that looks native? We would love to hear what you think!

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.