My favorites | English | Sign in

Faster JavaScript with Closure Tools New!

Google Wave API (Labs)

WaveProtocol.org

Learn about the Google Wave Federation Protocol and get involved

Google Wave Robots: Java Tutorial

The easiest way to understand how Wave extensions work is to build a Wave robot. Robots are applications that interact with a Wave through the Wave protocol (HTTP interface). Currently, we only support robots hosted with Google App Engine. In the future, we will support any client architecture that implements the Wave protocol.

In this tutorial, we'll use the Java client library to develop a sample robot. (The concepts apply here equally well to users of the Python client library, though implementation details will be different.) In this brief tutorial, you will create a simple robot, upload it to App Engine, and see it working with Wave.

Before you get started, make sure you have the Java 6 development kit installed. A future release will also support developing apps with Java 5. You can determine if you have Java installed (and what version is installed) by executing the following command from the command line:

hostname$ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06-153)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_07-b06-57, mixed mode)

Note: to enable Java 6 on Mac OS X, you may need to set Java 6 as the default using the /Applications/Utilties/Java/JavaPreferences application.

The Java Client Library

Development of Google Wave robots requires compiling with a client library. This tutorial uses the Java client library, a JSON library, and a JSON RPC library. You can download these libraries from the Wave Robot Java Client Library home page on Google Project Hosting:

http://code.google.com/p/wave-robot-java-client/

A Python client library is also available.

Setting Up App Engine

You can develop Wave robots and other Java web applications for App Engine using your favorite Java development tools. The Google Plugin for Eclipse makes it especially easy to develop App Engine applications with the Eclipse IDE. The Plugin includes the App Engine Java SDK, and adds several features to Eclipse for creating, testing and uploading projects.

Registering Your Application with App Engine

You will also want to register your robot using an Application ID at https://appengine.google.com.. You are allowed to register up to 10 application IDs, and application registrations cannot be undone or deleted, nor can an application ID be changed after it is registered. If you wish to conserve your allotted application registrations, you may want to choose an application ID you know you will use for a future project. As well, you may wish to reserve one ID for testing purposes of your robots.

Go to the App Engine Administrator Console in your web browser. Sign in using your Google account, creating one if necessary. If you haven't used this account with App Engine before, you may also be prompted to verify your account using SMS and a mobile phone.

Under My Applications click the Create an Application button. Choose an application ID, and follow the prompts to complete the registration. The new application appears in the list. You can click its name to visit the Administrator Console for this application.

Setting Up Eclipse

To keep things brief, this tutorial assumes you are using Eclipse and the Google Plugin. All of the Plugin's features are also provided by the App Engine SDK as Apache Ant build tasks, and as command-line tools and Java classes. If you'd prefer not to use Eclipse or the Plugin, see the App Engine Java documentation for alternatives.

Download and install Eclipse from the Eclipse website. Be sure to get the Java EE bundle, which includes several useful features for web application development.

You can install the Google Plugin and the App Engine SDK using the Software Update feature of Eclipse.

If you are using Eclipse 3.5 (Galileo), use the following Software Update location:

http://dl.google.com/eclipse/plugin/3.5

If you are using Eclipse 3.4 (Ganymede), use the following Software Update location:

http://dl.google.com/eclipse/plugin/3.4

Select the Plugin and the App Engine SDK from the list of available software, then install. For more information on installing the Google Plugin for Eclipse, see the Google Plugin for Eclipse documentation and the App Engine docs for the Plugin.

Create a new App Engine project, as follows:

  1. Select File > New > Web Application Project. Alternatively, click the New Web Application Project button in the toolbar: The New Web Application Project button.
  2. The "Create a Web Application Project" wizard opens. For "Project name," enter a name for your project, such as Parroty. For "Package," enter an appropriate package name, such as parroty.
  3. Since we're not going to use Google Web Toolkit for this project, uncheck "Use Google Web Toolkit." Verify that "Use Google App Engine" is checked.
  4. Click Finish to create the project.

The wizard creates a directory structure for the project, including a src/ directory for Java source files, and a war/ directory for compiled classes and other files for the application, libraries, configuration files, static files and other data files. The wizard also creates a servlet source file and two configuration files. The complete directory structure looks like this:

Parroty/
  src/
    parroty/
      server/
        ParrotyServlet.java
    META-INF/
      jdoconfig.xml
    log4j.properties
    logging.properties
  war/
    WEB-INF/
      lib/
        ...App Engine JARs...
      appengine-web.xml
      web.xml
    index.html

For more information on getting started with App Engine, see the App Engine Getting Started Guide for Java.

Hello, Robot!

To make this app into a robot, we need the Java robot application library from the Wave extensions SDK. We also need the JSON libraries, also included with the SDK. These libraries are provided by the following JARs:

  • wave-robot-api.jar
  • json.jar
  • jsonrpc.jar

Copy these files from the SDK to the following directory in your project:

Parroty/war/WEB-INF/lib/

Refresh the project by selecting the File menu > Refresh. Select the Project menu > Properties, then in the Properties window, select the "Java Build Path" category. Click the "Libraries" tab, then click the Add JARs... button. Navigate to and select the new JARs, then click OK. Click OK to close the Properties window.

Event Handing

To implement the main event handler, create a servlet that extends the AbstractRobotServlet class (from the com.google.wave.api package) and implement the method processEvents() which accepts a RobotMessageBundle object. This bundle contains data about the events and related waves "bundled" together, as the Wave system takes the liberty of bundling multiple events together for efficiency.

As your code manipulates the data, the API generates a list of operations to be performed by Wave. The servlet sends these operations back to Wave when the processEvents() method exits. The AbstractRobotServlet class takes care of processing the HTTP request, parsing event data, calling processEvents(), and communicating the operations back to Wave.

Let's create a simple robot that adds a greeting to a wave when it is added to the wave. Additionally, we will add a different greeting whenever a new participant is added to the Wave. Edit src/parroty/ParrotyServlet.java, and give it the following contents:

package com.google.wave.api.samples;

import com.google.wave.api.*;

public class ParrotyServlet extends AbstractRobotServlet {

  @Override
  public void processEvents(RobotMessageBundle bundle) {
    Wavelet wavelet = bundle.getWavelet();
	      
    if (bundle.wasSelfAdded()) {
      Blip blip = wavelet.appendBlip();
      TextView textView = blip.getDocument();
      textView.append("I'm alive!");
    }
	    
    for (Event e: bundle.getEvents()) {
      if (e.getType() == EventType.WAVELET_PARTICIPANTS_CHANGED) {    
        Blip blip = wavelet.appendBlip();
        TextView textView = blip.getDocument();
        textView.append("Hi, everybody!");
      }
    }
  }
}

The processEvents() method of the ParrotyServlet class takes a RobotMessageBundle, and calls a convenience method to test if at least one of the events in the bundle represents the robot being added to the wavelet. If so, it gets the wavelet, then creates a new blip at the end of the wavelet. The robot accesses the new blip's document, and adds a friendly message.

Additionally, the processEvents() method iterates through the events contained within the RobotMessageBundle and checks whether any events are of type WAVELET_PARTICIPANTS_CHANGED. If so, the robot adds a special greeting.

These two techniques illustrate the two different ways to handle events, either by using a convenience method in the API, or by specifically inspecting the individual events.

Servlet Mapping

To map this servlet to the URL path /_wave/robot/jsonrpc, edit the file war/WEB-INF/web.xml so that it looks like this:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <servlet>
        <servlet-name>Parroty</servlet-name>
        <servlet-class>parroty.ParrotyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Parroty</servlet-name>
        <url-pattern>/_wave/robot/jsonrpc</url-pattern>
    </servlet-mapping>
</web-app>

Creating a Configuration File

This robot needs a configuration file to prove to Wave it's a robot, and to tell Wave that it's interested in new participants. From the Package Explorer, create a new folder named war/_wave/, then inside this folder create a file named capabilities.xml with the following contents:

<?xml version="1.0" encoding="utf-8"?>
<w:robot xmlns:w="http://wave.google.com/extensions/robots/1.0">
  <w:capabilities>
    <w:capability name="WAVELET_PARTICIPANTS_CHANGED" content="true" />
  </w:capabilities>
  <w:version>1</w:version>
</w:robot>

(In Eclipse, you may need to click the "Source" tab at the bottom of the editor window to enter the XML as text.)

This configuration file says the robot has one capability: it can understand events of the type WAVELET_PARTICIPANTS_CHANGED. When this event occurs for a wavelet in which this robot is a participant, Wave will contact the robot with the content of the wavelet (content="true"). Notice that the robot will be contacted about all changes to participants for such wavelets, except when the robot itself is added.

The case of the robot itself being added is a special case, and will automatically dispatch the special event WAVELET_SELF_ADDED, which a robot is guaranteed to receive when added to a wave. You do not need to register for this event; it is always sent to the robot when added to a wave, and it can serve as an initialization event. A robot can keep track of the wavelets in which it is currently participating by storing and deleting wavelet IDs (such as in the App Engine datastore) when participant change events occur.

Robot Profiles

A Robot's Profile contains information about the robot, which a Wave client may use to display information identifying the robot (such as its avatar). Robots built using the Java client library create profiles by using a ProfileServlet interface, which responds to profile information requests.

To set up a Robot's profile, simply extend the ProfileServlet class and override any (or all) of the following default methods:

  • getRobotName() returns a Robot's name.
  • getRobotAvatarUrl() returns a Robot's imageUrl.
  • getRobotProfileUrl() returns a Robot's profileUrl, which should contain more information about this robot.
import com.google.wave.api.ProfileServlet;

public class Profile extends ProfileServlet {
  @Override
  public String getRobotName() {
    return "My Robot Name";
  }
 
  @Override
  public String getRobotAvatarUrl() {
    return "My Robot Image URL";
  }
 
  @Override
  public String getRobotProfileUrl() {
    return "My Robot Profile URL";
  }
}

Robot Versioning

Robots within the Wave API are versioned. This allows the Wave system to detect when robots have changed and/or their capabilities have been altered. If you modify a robot's capabilities (by adding or removing monitored events, for example), you should also modify the version identifier of the Robot within the Robot's capabilities.xml file.

When deploying a robot, the Wave system will check if the robot identifier is different than what it has cached. (The robot identifier is simply a text string.) If so, Wave will refresh the capabilities.xml file and alter the system to generate any new events you've indicated interest in.

Deploying the Robot

You can test your new robot by deploying it to App Engine, then adding it to a wave.

Note: No mechanism currently exists to test Wave robots on your local machine with the App Engine development server. A future release of the Wave SDK will include tools to test robots locally before deploying them to App Engine.

Within Eclipse, edit the file war/WEB-INF/appengine-web.xml. Inside the <application> element, enter the application ID you registered. For example, if your registered application ID is parrotybot, your appengine-web.xml file might look like this:

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>parrotybot</application>
  <version>1</version>
</appengine-web-app>

To deploy the application to App Engine, click the "Deploy to App Engine" button in the Eclipse toolbar: The App Engine deploy button.. Enter your Google account email address and password when prompted. Eclipse builds your project, then uploads it to App Engine.

You can check that your application is available by loading the following URL:

http://applicationName.appspot.com/_wave/capabilities.xml

You should receive an XML capabilities file like the one shown below:

You can also check your application within App Engine by logging into https://appengine.google.com/

Adding the Robot to the Wave

You add a robot to a wave by adding it as a participant in the wave with which you want it to interact. To do so, you must first add the Robot's address to your existing contacts. (You must do this outside of the current wave, currently.)

Within Wave, now create a new wave. Add your robot to the wave using its Wave ID, which is the App Engine application ID followed by @appspot.com (for example, dummyrobot@appspot.com.) The robot joins the wave, and adds its greeting.

Congratulations! You've built your first Wave Robot!