Creating Google wave robots in Grails

Updated 17/11: A grails plugin for Wave have been released see MasteringWave for more information.

I just got access to Google wave, where I would like to create a robot. A robot is a participant in the wave conversation and can do the same as everyone else in the wave. Wave robots can currently only be used by applications running on Google App-engine, so you need access to App-Engine. You can get this access here.

The application that I’m using is running grails, so it needs to fit into that application. When you read the robot functional specification, robots should extend AbstractRobotServlet. In grails Apps you have Controllers and no servlets, so this is a bit tricky. But really easy, when you find the trick.

To create your app, you need to create a grails app, to be deployed in app-engine using the Grails app-engine plugin. Follow the guide on the page and you should have an app running on app-engine.

I’ll use the wave robot tutorial as starting point for the app. The first thing you need is to download the following files and place them in the ./lib folder of your project.

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

The you need to create a capabilities.xml file. This is a configuration file, telling wave what your app responds to. capabilities.xml should be placed in the folder ./web-app/_wave/

<?xml version="1.0"?>
<w:robot xmlns:w="http://wave.google.com/extensions/robots/1.0">
  <w:capabilities>
    <w:capability name="blip_submitted"/>
  </w:capabilities>
  <w:version>1</w:version>
</w:robot>

You can add as many capabilities as you want. Remember the version element should correspond to you application appspot version.

Update: For a clarification on the version numbering see http://www.masteringwave.com/2009/08/capabilities-xml

You can add the servlet file that need to be extended. This is done by placing the file in the ./src/groovy or ./src/java in your project. If it is a groovy file, it should probably be place4d in the groovy folder. You should maintain the package path within these folders. Create the following file ./src/groovy/com/wave/ParrotyServlet.groovy. (It is not very groovy code, but it is a start)

package com.wave
import com.google.wave.api.*;
class ParrotyServlet extends  AbstractRobotServlet {
  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.BLIP_SUBMITTED) {
          Blip blip = wavelet.appendBlip();
          TextView textView = blip.getDocument();
          textView.append("Copying: " + e.getBlip().getDocument().text);
        }
      }

  }
}

Then you need to add the servlet mapping this is done by installing the template. Run the following command, when you are in your project.

grails install-templates

Then you can edit the file ./src/templates/war/web.xml and add the servlet and the serveletmapping. This is done with the following elements. Remember that two elements should be placed after corresponding elements; otherwise the XML is not valid.

   <servlet>
            <servlet-name>Parroty</servlet-name>
            <servlet-class>com.wave.ParrotyServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Parroty</servlet-name>
        <url-pattern>/_wave/robot/jsonrpc</url-pattern>
    </servlet-mapping>

Deploy the service, and you can test you application. Create a new wave. Add you robot with the name <yourappspotname>@appspot.com. Try to add a comment and you should get something like this screencast.

This is not a very functional robot, but it works. To store data you can use a service, which can be called from the servlet.

15 thoughts on “Creating Google wave robots in Grails”

  1. Thank you very much for the howto, very useful.

    BTW, here’s a somewhat “Groovier” version of the bot impl. code:

    package com.wave

    import com.google.wave.api.*

    /**
     * Minimal hello-world-ish Parroty Wave bot impl.
     */
    class ParrotyServlet extends AbstractRobotServlet {

        void processEvents(RobotMessageBundle bundle) {
            def wavelet = bundle.wavelet
            if (bundle.wasSelfAdded()) {
                def blip = wavelet.appendBlip()
                def textView = blip.document
                textView.append("Yay, I'm alive!")
            }
            for (event in bundle.events) {
                if (event.type == EventType.BLIP_SUBMITTED) {
                    def blip = wavelet.appendBlip()
                    def textView = blip.document
                    textView.append("Copying: ${event.blip.document.text}")
                }
            }
        }

    }
  2. Great article! I may go through this again after I get my Java robot at a good state to see about a porting to Groovy. It seemed to me the version in the capabilities.xml doesn’t have to match the application version. In fact this is a benefit because, you can increment the capabilities version and it will cause the Wave server robot proxy cache to be refreshed and you won’t chew up an application version in the process. I will go back a try it again since I haven’t done it in a few days but it seemed to work that way for me.

  3. Hi. Could you please send me this project source code.

    Because i tried, but something is going wrong, and my robot responds only to WAVELET_SELF_ADDED event 🙁 …

    my email is maris.plots@gmail.com

    Thanks.
    Maris.

  4. Hi Maris,
    I dont have the project anymore, so i cannot send it to you.
    Have you updated the cababilities.xml. to accept other commands. When you change the file you need to change the version number of the appengine with set-version command, and maybe upload the it to a different project. Wave does not fetch the cababilites.xml file every time.
    /daniel

  5. Yes. That was a problem. 🙂 I changed version number and everything works grate now.

    Thanks

    Maris

  6. Hey i am a little confused about this whole thing .Actually i am quite a novice with grails.To me grails seems to be all about controller whereas Wave seems to be making use of servlets now how to use this servlet with the controller ?

Comments are closed.