Google Wave Programming Articles Update
There were 2 articles posted in Google App Engine experiments blog.
1. Episode 7: Writing your First Google Wave Robot (https://gaejexperiments.wordpress.com/2009/11/04/episode-7-writing-your-first-google-wave-robot/)
2. Episode 11: Develop Simple Google Wave Robots using the WadRobotFramework (https://gaejexperiments.wordpress.com/2009/12/03/episode-11-develop-simple-google-wave-robots-using-the-wadrobotframework/)
I have updated both of these articles. The reasons for updating them are:
1. Google released a newer version of the Robots API : Version 2.0. They have recommended that all Robots written with the earlier API (which the articles covered) should be ported to use the new Version 2.0 API. The older API will be deprecated by end June.
2. WadRobotFramework (http://code.google.com/p/wadrobotframework) has also undergone an update to use the newer version 2.0 of the Robot API internally. Along with that, WadRobotFramework has also introduced several new features including a generator (so you almost end up writing as few lines as possible, the concept of obedience, etc.).
You will find both these articles updated at my new Blog (Google Wave Experiments) that is focused on Google Wave programming. Please find the articles over here:
Episode 1 : Writing your First Google Wave Robot using Robot API v2
Episode 2 : Writing a Wave Robot using WadRobotFramework
Hope you like the articles. I am looking forward to your feedback and want to know what you would like to see covered vis-a-vis Google Wave Programming so that I can conduct my experiments accordingly.
Episode 11: Develop Simple Google Wave Robots using the WadRobotFramework
Welcome to Episode 11 of this series. We saw in earlier Episode # 7, how you can write a Google Wave Robot. Please go through that tutorial to get familiar with the basics. This episode will be focused on writing a Google Wave Robot using a framework called the WadRobotFramework. This framework aims to help you develop your Robot quickly so that you can focus on the logic of your Robot, while letting the framework do the heavy lifting. Sure, you can do your programming with the Google Wave Robot API as explained in Episode 7, but this framework as we shall see wraps the details nicely so that you get to focus on your Robot logic.
What is the WadRobotFramework?
The WadRobotFramework is available at http://code.google.com/p/wadrobotframework. This framework is the work of Jerome BATON, who has stated that the goal of the framework is to make writing Google Wave Robots in Java much simpler.
The framework goes ahead and defines two kinds of Robots: Simple and Advanced.
Simple Robots
Simple Robots are typically those that can react to a new Blip. This kind of Robots simply wait till a Blip is submitted. And on submission of the Blip, they will append a message to the Blip. It could be as simple as just analyzing the text of the blip and appending some new information or simply a fun sort of a Robot, which simply prints a random message.
An example of a this is shown below and which we will build in this episode:
In the above wave, there are two participants (myself and the Robot). The Robot announces itself when it is added to the Wave. Additionally, whenever I submit a Blip (for e.g. Hello), it simply appends a new blip with some text.
Simple Robots are also those that can modify the Blip Text instead of appending a new blip. For e.g. They could read the blip text and filter out the profanities, do automated spell checks or simply add some information to the existing Blip Text itself. In other words, it modifies the Blip Text.
Shown below is an example of a Simple Robot that modifies the Blip Text:
In the above wave, there are two participants (myself and the Robot). The Robot announces itself when it is added to the Wave. Additionally, whenever I submit a Blip (for e.g. Hello), it simply modifies the Blip Text by mentioning when I submitted the Blip text.
There is also a 3rd thing that the Simple Robots could do, which is very useful too. They can act in a stealth manner and simply do their work quietly. For e.g. whether you wish to write a Robot that appends a Blip or modifies a submitted Blip, you can simply chose not to append or modify but instead get the Blip text and do your work quietly. For e.g. count the words in the background, etc.
The WadRobotFramework also supports Advanced Robots, which are particularly interesting and will be covered in the Next Episode.
Advanced Robots are those that can react to commands in the Blips. Here are some samples of Advanced Robots and how they would react to commands from Blips:
1. A character Counting Advanced Robot:
Your submitted Blip Text contains : “Here is some text in the blip. Please count the length of this message for me. {mycountingrobot:count}”.
You can write an advanced Robot (mycountingrobot) that knows how to count the length of the message. So it gets notified when it there is a command (count) in the Blip. Your Advanced Robot can then count out the characters and then either append or modify a blip as needed.
2. A Tweeting Robot:
Your submitted Blip Text contains the following text : “{mytweetingrobot:tweet}
You can write an advanced Robot (mytweetingrobot) that knows how to tweet the message to Twitter. So it gets notified when it there is a command (tweet) in the Blip. Your Advanced Robot can then append a blip or modify a blip saying that the message has been tweeted.
The best part of it all is that you could combine all of this into a single Robot that can respond to one or more commands. For example, take a look at Today’s Special Robot (see http://ppandhi.wordpress.com/2009/11/08/todays-special-robot/) that can respond to more than one command. It can give you the quotes, day in history, word of the day, cricket score, your daily horoscope by simply responding to the command that you type in. With the WadRobotFramework, we shall see in the next episode how you can write such an Advanced Robot that responds to different commands. If you cannot wait, take a look at the documentation at the site (Advanced Robots).
Since this episode will be focusing on Simple Robots, let us recap what we know so far: The WadRobotFramework supports Simple Robots in two flavours: The BlipAppenderRobot and the BlipModifierRobot. The BlipAppenderRobot is used to simply append to a Blip. The BlipModifierRobot is used to modify a submitted Blip.
Simple, isnt it? Lets develop and deploy our Simple Robots using the WadRobotFramework.
Create a New Project
We need to create a New Project first. Follow the steps below:
1. Either click on File –> New –> Other or press Ctrl-N to create a new project. Select Google and then Web Application project. Alternately you could also click on the New Web Application Project Toolbar icon as part of the Google Eclipse plugin.
2. In the New Web Application Project dialog, deselect the Use Google Web Toolkit and give a name to your project. I have named mine MyGoogleWaveRobot and I suggest you go with the same name so that things are consistent with the rest of the article (but if you wish to name it something else, that is fine too). The Screenshot is shown below:
3. Click on Finish. This will generate the project and also create a sample Hello World Servlet for you. But we will be writing our own Servlet. So I suggest that you can delete the Servlet Java class and the mappings made in the web.xml or you can leave it for now since we are going to write our own.
Adding Google Wave Robot JAR files and WadRobotFramework JAR file to your Project Path
Since we are going to be writing a Wave Robot, we need some additional files on the client side. These additional files (JAR files) are required for the additional Wave API’s and also for deployment in your WEB-INF\lib folder, so that they are correctly deployed and available to the run-time engine. These JAR files do not ship along with the Google Eclipse plugin, so you will need to download them for a website. The Google code website for the JAR files is:
http://code.google.com/p/wave-robot-java-client/downloads/list
The web page when you navigate to the above URL is shown below:
Download all the above files to your machine.
The WadRobotFramework JAR file is available at the following location :
http://code.google.com/p/wadrobotframework/downloads/list
The web page when you navigate to the above URL is shown below:
Once you have downloaded the files, follow these steps to setup your Project Build Path and runtime correctly.
1. Copy all the 5 JAR files to the WEB-INF\lib folder of your Eclipse Project. After copying you should see the files as shown in the project hierarchy below:
2. Right-click on the Project in the Project Hierarchy. Select Properties and then Java Build Path. Click on Add JARs and then select the 5 JAR files from your Project WEB-INF\lib folder.
3. Your Project Build Path should like the screenshot below.
Click on OK to proceed. This completes your Build Path setup with the Google Wave Robot JAR and WadRobotFramework JAR files.
Writing the Simple Robot: MyAppenderRobot : MyAppenderRobot.java
Let us first create our Simple Robot Java class based on the WadRobotFramework. This Simple Robot is the one that will react to a new Blip. So all we will do is to make the robot append to the blip, when the blip is submitted. The Robot demonstrated here will be straightforward and you can easily modify it to make it react in your own way.
As discussed, this is known as the BlipAppenderRobot and so all we need to do is to extend the BlipAppenderRobot class in the WadRobotFramework and provide our simple implementation.
The steps are straightforward and given below. All we need to do is write our class that extends the org.wadael.waverobotfrmwrk.simple.BlipAppenderRobot class and provide an implementation for the getTextToAppend method.
Follow these steps:
1. Create a new Java class within the same package. The New Java Class dialog is shown below. I have named the class MyAppenderRobot as shown below. Click on the Browse button to select a Super Class.
2. In the Superclass Selection dialog shown below, type the word BlipAppenderRobot (some part of it is also OK as the screenshot shows below) in the Choose a type field as shown. This will bring up the correct Matching items i.e. org.wadael.waverobotfrmwrk.simple.BlipAppenderRobot. Click on OK.
This will generate the code and you simply replace it with the following code listing given below:
package com.gaejexperiments.waverobot; import org.wadael.waverobotfrmwrk.simple.BlipAppenderRobot; public class MyAppenderRobot extends BlipAppenderRobot { @Override protected String getTextToAppend(String msg) { return "I am appending some text too"; } @Override protected String getRobotSelfIntroduction() { return "I am the Appender Robot"; } }
Let us go through the code now:
1. We have extended the BlipAppenderRobot since all we want to do in this Robot is to react to the blip and append our own Blip
2. All we need to do as part of extending the BlipAppenderRobot class is to implement the getTextToAppend method. This method gets passed one parameter msg that is the blip text that was submitted. So in all essence, you could inspect what the text was in the blip submitted and then react to it. The implementation simply returns the string that it wants to append. The WadRobotFramework’s BlipAppenderRobot will take care of creating a Blip and appending it to the current blip.
3. We also implement an optional method named getRobotSelfIntroduction. This method returns a string and you can return something that identifies the addition of your Robot to the Wave. So when your Robot is added as a participant and if you have implemented the getRobotSelfIntroduction method, then it will display this message out. It is sort of announcing to the other wave participants about your presence.
That is all there is to implemented the MyAppenderRobot. If you would have studied the earlier tutorial on writing a Google Wave Robot, you would have noticed that the WadRobotFramework has done away with all the Event processing that you had to handle yourself and also shielded you from methods that you need to know to create a blip and append to it.
Configuring the MyAppenderRobot in web.xml
We need to add the MyAppenderRobot in the <servlet/> and <servlet-mapping/> entry to the web.xml file. This file is present in the WEB-INF folder of the project. The necessary fragment to be added to your web.xml file are shown below.
<servlet> <servlet-name>MyAppenderRobot</servlet-name> <servlet-class>com.gaejexperiments.waverobot.MyAppenderRobot</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyAppenderRobot</servlet-name> <url-pattern>/_wave/robot/jsonrpc</url-pattern> </servlet-mapping>
In the above fragment, you will note that url-pattern /_wave/robot/jsonrpc has to be mapped to the Robot Servlet that you have written. This is because the Google Wave system will invoke this url to communicate with your Robot using its protocol.
Creating the MyAppenderRobot capabilities.xml files
We need an additional file to describe the capabilities of the Robot that we have written. This file is called the capabilities.xml and it needs to reside in a certain location. You need to create a _wave directory inside of the war directory of your project. The location of this file is war/_wave directory.
You will need to create the _wave directory and create the capabilities.xml file over there. The capabilities file shown below is pretty straightforward and is shown below:
<?xml version="1.0" encoding="utf-8"?> <w:robot xmlns:w="http://wave.google.com/extensions/robots/1.0"> <w:capabilities> <w:capability name="BLIP_SUBMITTED" content="true" /> </w:capabilities> <w:version>1</w:version> </w:robot>
There are two elements of interest over here.
The <capability> element is of particular interest and we have registered for the BLIP_SUBMITTED event. This is important because it informs Google Wave that whenever a BLIP is submitted by a participated, then our Robot needs to be notified of it. The WadRobotFramework will notify the Robot by invoking the getTextToAppend method.
The other element is the <version> element. If you change any capabilities in your robot, then it is recommended that before you deploy, you change the version value over here, so that Google Wave can detect that there is a newer version and hence it can then query for your modified capabilities if any.
Writing our MyAppenderRobot Profile Servlet (not required but nice)
This is not a required step but it would be good practice to do so to make your Robot look more professional. A Profile Servlet is used to tell the following about your Robot:
1. A Name for your Robot
2. A custom image for your Robot
3. A profile page for your Robot (a URL)
If you provide these, then the Google Wave client is able to retrieve them and set it for your Robot when it is added as a participant. This makes the Robot look more professional.
This profile information needs to be provided by you by writing a Profile Servlet. The Profile Servlet is nothing but extending the com.google.wave.api.ProfileServlet class and providing simple implementations for the overwritten methods.
Follow these steps to write the Profile Servlet:
1. Create a new Java class within the same package. Name the classs MyRobotProfileServlet and mention the Superclass as com.google.wave.api.ProfileServlet class. Click on OK.
2. This will generate a MyRobotProfileServlet.java file.
The simplest way to generate the stubs for the required methods would be to go to Source –> Override/Implement Methods. This will bring up the dialog box as shown below and you only need to select the 3 methods to override as shown:
Click on OK. This will generate the stubs, which you can then overwrite with the code shown below. The code is easy to understand, all we are doing is providing values for the Name, Avatar(Image) and the Profile Page URL. Note that for the Avatar, we are providing a file myimage.jpg present in the WAR/_wave folder. You will need to copy an appropriate image file for yourself and make sure that it is physically copied to the folder locally in your Eclipse project before you deploy your application.
I have used my AppId as myinfoagent but you can replace it with your AppId.
package com.gaejexperiments.waverobot; import com.google.wave.api.ProfileServlet; public class MyRobotProfileServlet extends ProfileServlet { @Override public String getRobotAvatarUrl() { return "http://myinfoagent.appspot.com/_wave/myimage.jpg"; } @Override public String getRobotName() { return "MyRobot"; } @Override public String getRobotProfilePageUrl() { return "http://myinfoagent.appspot.com"; } }
Configuring the Profile Servlet
We need to add the Profile Servlet <servlet/> and <servlet-mapping/> entry to the web.xml file. This file is present in the WEB-INF folder of the project. The necessary fragment to be added to your web.xml file are shown below.
<servlet> <servlet-name>MyRobotProfileServlet</servlet-name> <servlet-class>com.gaejexperiments.waverobot.MyRobotProfileServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyRobotProfileServlet</servlet-name> <url-pattern>/_wave/robot/profile</url-pattern> </servlet-mapping>
|
In the above fragment, you will note that url-pattern /_wave/robot/profile has to be mapped to the Profile Servlet that you have written. This is because the Google Wave system will invoke this url to get hold of your profile.
Deploying the Application
To deploy the application, you will need to first create your Application ID. The Application Identifier can be created by logging in at http://appengine.google.com with your Google Account. You will see a list of application identifiers already registered under your account (or none if you are just getting started). To create a new Application, click on the Create Application button and provide the Application Identifier as requested. Please note this name down since you will be using it for deployment.
For e.g. I have registered an application identifier named myinfoagent.
To deploy the application, follow these steps (they should be familiar to you now):
- Click on the Deploy Icon in the Toolbar.
- In the Deploy dialog, provide your Email and Password. Do not click on Deploy button yet.
- Click on the App Engine Project settings link. This will lead you to a dialog, where you need to enter your Application ID [For e.g. my Application Identifier myinfoagent]
- Click on OK. You will be lead back to the previous screen, where you can click on the Deploy button. This will start deploying your application to the GAEJ cloud. You should see several messages in the Console window as the application is being deployed.
- Finally, you should see the message “Deployment completed successfully”.
MyAppenderRobot in Action
Your application is going to be available at the http://yourapplicationid.appspot.com. In my case, the application is available at http://myinfoagent.appspot.com.
You can test for the presence of your robot capabilities file by simply typing in the following:
http://yourapplicationid.appspot.com/_wave/capabilities.xml [Replace yourapplicationid with the Application ID that you have] and you should see the capabilities.xml file being served up.
To test out the Robot, you need to launch the Google Wave client and login in with your account by going to http://wave.google.com. On successful login, you will be inside the Wave client from where you can create a new wave by clicking on the New Wave link. When you do that, currently you are the only participant (myself) as shown in the screen below:
Click on the + sign next to your icon and you can add one or more participants as shown below:
NOTE : Your Google Wave Robot is going to be available at <YOURAPPLICATIONID>@appspot.com , hence I have added [email protected] as that was my application id. But you can replace it with your application id.
If all goes well, you will see your Robot added as a participant (with the icon and all, since the Profile Servlet is invoked behind the scenes by the Google Wave system). It announces itself and this was done via the implementation that we provided in the getRobotSelfIntroduction method.
Now I type a message “Hello” as shown below and click on the Done button, the BLIP_SUBMITTED event is fired and our Robot gets the event i.e. the getTextToAppend method is invoked on our Robot Java class. The method simply appends a blip as shown below:
Writing another Simple Robot: MyBlipModifierRobot : MyBlipModifierRobot.java
We saw how easy it was to create our Simple Robot that simply appended a blip to the wave conversation when a blip was submitted. Let us now write another Simple Robot that will modify the Blip Text when the blip is submitted.
As discussed, this is known as the BlipModifierRobot and so all we need to do is to extend the BlipModifierRobot class in the WadRobotFramework and provide our simple implementation.
The steps are straightforward and given below. All we need to do is write our class that extends the org.wadael.waverobotfrmwrk.simple.BlipModifierRobot class and provide an implementation for the modifyBlipText method.
Follow these steps:
1. Create a new Java class within the same package. Name it MyBlipModifierAppenderRobot as shown below and mention the superclass as org.wadael.waverobotfrmwrk.simple.BlipModifierRobot
This will create the MyBlipModifierRobot.java file and you can replace it with the following source:
package com.gaejexperiments.waverobot; import java.util.Date; import org.wadael.waverobotfrmwrk.simple.BlipModifierRobot; public class MyBlipModifierRobot extends BlipModifierRobot { @Override protected String modifyBlipText(String originalBlipText) { return originalBlipText + " [You typed this at :" + new Date().toString() + "]"; } @Override protected String getRobotSelfIntroduction() { return "I am the Blip Modifier Robot"; } }
Let us go through the code now:
1. We have extended the BlipModifierRobot since all we want to do in this Robot is to modify the Blip that was submitted.
2. All we need to do as part of extending the BlipModifierRobot class is to implement the modifyBlipText method. This method gets passed one parameter originalBlipText that is the blip text that was submitted. So in all essence, you could inspect what the text was in the blip submitted and then modify it as needed . The implementation above appends the text “You typed this at [DateTimeStamp]” to the originalBlipText and simply returns that string. The WadRobotFramework’s BlipModifierRobot will take care of modifying the Blip Text.
3. We also implement an optional method named getRobotSelfIntroduction. This method returns a string and you can return something that identifies the addition of your Robot to the Wave. So when your Robot is added as a participant and if you have implemented the getRobotSelfIntroduction method, then it will display this message out. It is sort of announcing to the other wave participants about your presence.
That is all there is to implemented the MyBlipModifierRobot. If you would have studied the earlier tutorial on writing a Google Wave Robot, you would have noticed that the WadRobotFramework has done away with all the Event processing that you had to handle yourself and also shielded you from methods that you need to know to create a blip and append to it.
Configuring the MyBlipModifierRobot in web.xml
We need to add the MyBlipModifierRobot in the <servlet/> and <servlet-mapping/> entry to the web.xml file. This file is present in the WEB-INF folder of the project. The necessary fragment to be added to your web.xml file are shown below.
<servlet> <servlet-name>MyBlipModifierRobot</servlet-name> <servlet-class>com.gaejexperiments.waverobot.MyBlipModifierRobot</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyBlipModifierRobot</servlet-name> <url-pattern>/_wave/robot/jsonrpc</url-pattern> </servlet-mapping>
If you wish to check out this Robot in action, you can do so with the same project. Simply replace the previous Robot’s (MyAppenderRobot) servlet entries with the one shown above. And deploy the application following the same steps in the Deploying the Application section. Leave the Profile Servlet and the capabilities.xml file as is because the same applies in this case too.
Once you deploy the MyBlipModifierRobot, you should see it in action as shown below. The first screen shows the MyBlipModifierRobot announcing itself and then the second screen shows how it modified the blip text that I submitted by appending the TimeStamp to it.
Conclusion
This concludes Episode 11 of the series. We saw how easy it was to write Simple Google Wave Robots using the WadRobotFramework. Several Google Wave Robots that are out there simply do one of the things that we have seen in this episode i.e. modify a blip’s contents or append a blip in reaction to a blip submitted. You can get going with such Robots by using this framework which hides you from the underlying Google Wave API.
In the next episode, we shall see how to write an Advanced Google Wave Robot that can implement several commands. Till then, unleash those Simple Robots!
Episode 7: Writing your First Google Wave Robot
Please note that this article uses the older version of the Robot API. A newer release (version 2.0) of the Robot API is out and is recommended by Google. An updated article that uses the new Robot API version 2.0 is published here.
Welcome to Episode 7 of this series. Hope that the series has been interesting for you so far. In this episode, we plan to jump onto the Google Wave bandwagon. Google Wave, as you must have heard is a collaborative messaging platform from Google. A Wave is a collaboration between several participants (humans and non-humans) using threaded conversations/documents/gadgets to achieve their task. The task could be as simple as chatting among themselves to figure out where to dine tonight to as complex as achieving a Return Order process between a purchaser and seller.
I will not delve into the specifics of Google Wave and will assume that you have a high level idea of what it is. In fact, a great online book has just been released that covers Google Wave in depth. I strongly recommend you to read it if you want to look into Google Wave in detail. The book is named The Complete Guide to Google Wave and you can read it here.
What does this episode cover?
In this episode, we are going to look at how you can write a Google Wave Robot using the Google plugin in Eclipse. We will then deploy it and host this robot in the Google App Engine cloud. This Robot is then live and can be added to any Wave and participate in the conversation.
It helps to see the final result before we start out. Even if you do not understand whats going on, just bear with me. So here is the screenshot:
Let us dissect this screen and in the process, I can hopefully explain to you some Google Wave terminology in a straightforward manner without too many details. The main points are:
1. What you see in the screen above is a Google Wave that me (the person with the photo created). A Wave is a collaboration between one or more participants (human or Robots).
2. Since we need participants to make it meaningful, you can add one or more of them. All you need to do is click the + sign that you see on the top. And you can add one or more participants who are also signed up for Wave. In this case, my Robot GAEJ Application is hosted at http://gaejrobot.appspot.com and so I can add [email protected] as a participant.
3. On adding the Robot participant, Google wave system pulls up its profile (image, etc) and adds it as a participant in the Wave that I created.
4. The Robot can receive events and it can respond to them. We shall see how to write them later (source code!!), but at this point it is enough to understand that the Robot can choose what events to listen to as the Wave collaboration happens and it can then react to them. So in the case of my GAEJ Robot, I have specified that I am interested in knowing when participants come and leave the Wave and when someone has submitted a message.
5. So you can see that the GAEJ Robot was notified when it was added to the Wave, so in response to that it printed out the message “Hi! Your GAEJExperiments Bot…..” at the bottom. Similarly, when I finished typing the message (Hello GAEJ Robot), the GAEJ Robot got notified. It then took the message and along with some metadata like ID and Creator Name, it simpy echoed back what I typed.
Hope this makes things clear. But a few more terms first : Wave, Wavelet and Blip. Let me keep it simple. In the above example, the Wave was the entire container. A Wave consists of one or more Wavelets. A Wavelet can be thought of as a threaded conversation that can go on within the wave (both public and private). And each Wavelet consists of one or more messages known as a Blip. A Blip is the actual message that was typed and submitted by the user. So when I typed “Hello GAEJ Robot” above, it was a Blip.
I have simplified things a bit here but even if things are not clear at this point, do not worry. Once you get your code working, things will fall in place.
A final note above Google Wave Extensions. Extensions are the mechanism by which you can extend Google Wave by adding your own creations. Extensions are of two types : Gadgets and Robots. Gadgets are like mini-applications that run within the Google Wave client. They can be typically thought of as a UI which several participants can share at the same time. A Robot is a full blown participant in the Wave. It can be aware of most things happening in the Wave by subscribing to Events. It also has a lot of potential to modify things in the Wave like messages, etc. This article focuses on writing a Robot. If you are interested in a good summary of Google Wave Extensions and some key differences between a Gadget and a Robot, read it here.
OK, so enough of theory. Let us get down to coding. If you are new to developing with the Google Plugin for Eclipse, please read the earlier episodes to setup your environment (Episode 1 and Episode 5)
Create a New Project
We need to create a New Project first. Follow the steps below:
1. Either click on File –> New –> Other or press Ctrl-N to create a new project. Select Google and then Web Application project. Alternately you could also click on the New Web Application Project Toolbar icon as part of the Google Eclipse plugin.
2. In the New Web Application Project dialog, deselect the Use Google Web Toolkit and give a name to your project. I have named mine MyFirstGoogleWaveRobot and I suggest you go with the same name so that things are consistent with the rest of the article. The Screenshot is shown below:
3. Click on Finish. This will generate the project and also create a sample Hello World Servlet for you. But we will be writing our own Servlet. So I suggest that you can delete the Servlet Java class and the mappings made in the web.xml or you can leave it for now since we are going to write our own.
The directory structure for your project should now look like this.
Adding Google Wave Robot JAR files to your Project Path
Since we are going to be writing a Wave Robot, we need some additional files on the client side. These additional files (JAR files) are required for the additional Wave API’s and also for deployment in your WEB-INF\lib folder, so that they are correctly deployed and available to the run-time engine. These JAR files do not ship along with the Google Eclipse plugin, so you will need to download them for a website. The Google code website for the JAR files is:
http://code.google.com/p/wave-robot-java-client/downloads/list
The web page when you navigate to the above URL is shown below:
Download all the above files to your machine. Once you have downloaded the files, follow these steps to setup your Project Build Path and runtime correctly.
1. Copy all the 4 JAR files to the WEB-INF\lib folder of your Eclipse Project. After copying you should see the files as shown in the project hierarchy below:
2. Right-click on the Project in the Project Hierarchy. Select Properties and then Java Build Path. Click on Add JARs and then select the 4 JAR files from your Project WEB-INF\lib folder as shown below and click on OK.
3. Your Project Build Path should like the screenshot below.
Click on OK to proceed. This completes your Build Path setup with the Google Wave Robot JAR files.
Writing the Google Wave Robot Servlet : MyFirstGoogleWaveRobot.java
Let us first create our Robot Java class. The steps are straightforward and given below. All we need to do is write our class that extends the com.google.wave.api.AbstractRobotServlet class and provide an implementation for the processEvents method.
Follow these steps:
1. Create a new Java class within the same package. The New Java Class dialog is shown below. I have named the class MyFirstGoogleWaveRobot as shown below. Click on the Browse button to select a Super Class.
2. In the Superclass Selection dialog shown below, type the word AbstractRobot (some part of it is also OK as the screenshot shows below) in the Choose a type field as shown. This will bring up the correct Matching items i.e. com.google.wave.api.AbstractRobotServlet. Click on OK
This will generate the code as shown below in your Eclipse IDE.
Simply overwrite it with the code shown below:
package com.gaejexperiments.waverobot; import com.google.wave.api.AbstractRobotServlet; import com.google.wave.api.Blip; import com.google.wave.api.Event; import com.google.wave.api.EventType; import com.google.wave.api.RobotMessageBundle; import com.google.wave.api.TextView; import com.google.wave.api.Wavelet; public class MyFirstGoogleWaveRobot 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("Hi! Your GAEJExperiments Bot is waiting for your command..."); } for (Event e: bundle.getEvents()) { if (e.getType() == EventType.BLIP_SUBMITTED) { //Get the Blip that was submitted Blip blip = e.getBlip(); //Extract out MetaData information like ID and the creator of the Blip String strBlipMetaData = "Blip Id : " + blip.getBlipId() + " , " + "Blip Creator : " + blip.getCreator(); //Extract out the text that was entered in the blip String strBlipText = "You typed : " + blip.getDocument().getText(); //Echo that out by creating a child within the submitted blip blip.createChild().getDocument().append(strBlipMetaData + "\r\n" + strBlipText); } } } }
Let us discuss the main points of the source code:
1. A Robot class needs to extend the com.google.wave.api.AbstractRobotServlet class
2. The only method that you need to implement to get going is the processEvents() method as shown above in the code. In this method, all we need to do is process the Events that we are interested in and take some action.
3. What we want our Robot to do is to announce itself to everyone when it is added to the Wave. This event is also pumped into the processEvents method but the API provides us a nice convenient method to detect if we have been added to the Wave via the bundle.wasSelfAdded() method. The code snippet is shown below:
public void processEvents(RobotMessageBundle bundle) { Wavelet wavelet = bundle.getWavelet(); if (bundle.wasSelfAdded()) { Blip blip = wavelet.appendBlip(); TextView textView = blip.getDocument(); textView.append("Hi! Your GAEJExperiments Bot is waiting for your command..."); } //...Rest of processEvents method }
So the first thing we are doing is determining if we (i.e. the Robot has been added to the Wave. If yes, we need to add a message to the Wavelet (Threaded Conversation). Remember a message is known as a Blip. So we append a new Blip to the current wavelet. And now we need to set the message text for the Blip. To do that, we need to get the handle to a TextView for the Blip and then we append our Text to it. As simple as that.
4. Then we have the main Events loop in which we navigate through the events that are pumped into the loop by the Google Wave system. The code snippet is shown below:
for (Event e: bundle.getEvents()) { if (e.getType() == EventType.BLIP_SUBMITTED) { //Get the Blip that was submitted Blip blip = e.getBlip(); //Extract out MetaData information like ID and the creator of the Blip String strBlipMetaData = "Blip Id : " + blip.getBlipId() + " , " + "Blip Creator : " + blip.getCreator(); //Extract out the text that was entered in the blip String strBlipText = "You typed : " + blip.getDocument().getText(); //Echo that out by creating a child within the submitted blip blip.createChild().getDocument().append(strBlipMetaData + "\r\n" + strBlipText); } }
If the EventType is BLIP_SUBMITTED i.e. someone has submitted a message, then we first get the handle to the Blip. The Blip is not just the Text but a lot of other useful metadata. I simply demonstrate here two kinds of information about the blip, a BlipId and a Blip Creator. The blip creator is the name of the participant that created this blip. Then as we saw, we get to the Text of the Blip, by getting a handle on the getDocument() and then the getText() method. This gives us the text that was typed by the creator of the Blip. Finally, I insert a child Blip inside the Blip so that it looks like a response to that blip within the Google Wave. The response is nothing but a text appended with the metadata extracted and the echoing of the text that the creator typed.
Using this boiler plate of code, you can do your own thing. You could interpret commands given in a Blip by anyone and execute them and append the responses to their Blip. You could look up data on Amazon or any other web site if given the ISBN. The possibilities are limitless if you wish to modify the above code and make your Robot do something else.
That is all to writing a Robot but we still have some configuration to do to let Google Wave know that we have a Robot running in our GAEJ Application. And we will do that through the standard servlet entries in the web.xml file along with new XML configuration file that you need for the Robot called the capabilities.xml file.
Configuring the Robot Servlet
We need to add the Robot Servlet <servlet/> and <servlet-mapping/> entry to the web.xml file. This file is present in the WEB-INF folder of the project. The necessary fragment to be added to your web.xml file are shown below.
<servlet> <servlet-name>MyFirstGoogleWaveRobot</servlet-name> <servlet-class>com.gaejexperiments.waverobot.MyFirstGoogleWaveRobot</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyFirstGoogleWaveRobot</servlet-name> <url-pattern>/_wave/robot/jsonrpc</url-pattern> </servlet-mapping>
In the above fragment, you will note that url-pattern /_wave/robot/jsonrpc has to be mapped to the Robot Servlet that you have written. This is because the Google Wave system will invoke this url to communicate with your Robot using its protocol.
Creating the Robot capabilities.xml files
We need an additional file to describe the capabilities of the Robot that we have written. This file is called the capabilities.xml and it needs to reside in a certain location. You need to create a _wave directory inside of the war directory of your project. The location of this file is shown below under the war/_wave directory.
You will need to create the _wave directory and create the capabilities.xml file over there. The capabilities file shown below is pretty straightforward. Two items are of interest. One is the a <capability> element for each EVENT that you wish your Robot get notified about. If you go back to the Source code of our Robot, you will notice that we were primarily interested in two events:
1. BLIP_SUBMITTED : Take a look at the source code. You will find that we checked for this event in our Events Loop and once a Blip (Message) was available, we extracted information and sent back a child Blip.
2. WAVELET_PARTICIPANTS_CHANGED: Take a look at the source code. This event was fired and we used a convenience method called bundle.wasSelfAdded() to find if we were added. In fact, you can put in an if else clause and catch this event in the Events loop too to get notified whenever anyone joins or leaves the Wave.
Now that it is clear that we need these two events, we subscribe to them by specifying the events in the capabilities.xml document. Any other events (Look at the com.google.wave.api.EventType class) that you are interested in should be mentioned here, otherwise your robot will not get notified about them. The other element is the <version> element. If you change any capabilities in your robot, then it is recommended that before you deploy, you change the version value over here, so that Google Wave can detect that there is a newer version and hence it can then query for your modified capabilities if any.
<?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:capability name="BLIP_SUBMITTED" content="true" /> </w:capabilities> <w:version>1</w:version> </w:robot>
Writing our Robot Profile Servlet (not required but nice)
This is not a required step but it would be good practice to do so to make your Robot look more professional. A Profile Servlet is used to tell the following about your Robot:
1. A Name for your Robot
2. A custom image for your Robot
3. A profile page for your Robot (a URL)
If you provide these, then the Google Wave client is able to retrieve them and set it for your Robot when it is added as a participant. This makes the Robot look more professional.
This profile information needs to be provided by you by writing a Profile Servlet. The Profile Servlet is nothing but extending the com.google.wave.api.ProfileServlet class and providing simple implementations for the overwritten methods.
Follow these steps to write the Profile Servlet:
1. Create a new Java class within the same package. The New Java Class dialog is shown below. I have named the class GAEJRobotProfileServlet as shown below. Click on the Browse button to select a Super Class.
2. In the Superclass Selection dialog shown below, type the word ProfileServlet in the Choose a type field as shown. This will bring up the correct Matching items i.e. com.google.wave.api.ProfileServlet class. Click on OK.
3. This will generate a GAEJRobotProfileServlet.java file.
The simplest way to generate the stubs for the required methods would be to go to Source –> Override/Implement Methods. This will bring up the dialog box as shown below and you only need to select the 3 methods to override as shown:
Click on OK. This will generate the stubs, which you can then overwrite with the code shown below. The code is easy to understand, all we are doing is providing values for the Name, Avatar(Image) and the Profile Page URL. Note that for the Avatar, we are providing a file myimage.jpg present in the WAR/_wave folder. You will need to copy an appropriate image file for yourself and make sure that it is physically copied to the folder locally in your Eclipse project before you deploy your application. You should also replace the word gaejerobot in the source code below with your Application ID.
package com.gaejexperiments.waverobot; import com.google.wave.api.ProfileServlet; public class GAEJRobotProfileServlet extends ProfileServlet { @Override public String getRobotAvatarUrl() { return "http://gaejrobot.appspot.com/_wave/myimage.jpg"; } @Override public String getRobotName() { return "GAEJ Robot"; } @Override public String getRobotProfilePageUrl() { return "http://gaejrobot.appspot.com"; } }
Configuring the Profile Servlet
We need to add the Profile Servlet <servlet/> and <servlet-mapping/> entry to the web.xml file. This file is present in the WEB-INF folder of the project. The necessary fragment to be added to your web.xml file are shown below.
<servlet-name>GAEJRobotProfileServlet</servlet-name> <servlet-class>com.gaejexperiments.waverobot.GAEJRobotProfileServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>GAEJRobotProfileServlet</servlet-name> <url-pattern>/_wave/robot/profile</url-pattern> </servlet-mapping>
In the above fragment, you will note that url-pattern /_wave/robot/profile has to be mapped to the Profile Servlet that you have written. This is because the Google Wave system will invoke this url to get hold of your profile.
Deploying the Application
To deploy the application, you will need to first create your Application ID. The Application Identifier can be created by logging in at http://appengine.google.com with your Google Account. You will see a list of application identifiers already registered under your account (or none if you are just getting started). To create a new Application, click on the Create Application button and provide the Application Identifier as requested. Please note this name down since you will be using it for deployment.
For e.g. I have registered an application identifier named gaejrobot.
To deploy the application, follow these steps (they should be familiar to you now):
- Click on the Deploy Icon in the Toolbar.
- In the Deploy dialog, provide your Email and Password. Do not click on Deploy button yet.
- Click on the App Engine Project settings link. This will lead you to a dialog, where you need to enter your Application ID [For e.g. my Application Identifier gaejrobot]
- Click on OK. You will be lead back to the previous screen, where you can click on the Deploy button. This will start deploying your application to the GAEJ cloud. You should see several messages in the Console window as the application is being deployed.
- Finally, you should see the message “Deployment completed successfully”.
GAEJ Robot in Action
Your application is going to be available at the http://yourapplicationid.appspot.com. In my case, the application is available at http://gaejrobot.appspot.com.
You can test for the presence of your robot capabilities file by simply typing in the following:
http://yourapplicationid.appspot.com/_wave/capabilities.xml [Replace yourapplicationid with the Application ID that you have]
For e.g. when I navigate to the following url (http://gaejrobot.appspot.com/_wave/capabilities.xml) for my robot application, I get the capabilities xml as shown below, which means that the robot is ready and serving if all is right.
<w:robot> <w:capabilities> <w:capability name="WAVELET_PARTICIPANTS_CHANGED" content="true"/> <w:capability name="BLIP_SUBMITTED" content="true"/> </w:capabilities> <w:version>1</w:version> </w:robot>
To test out the Robot, you need to launch the Google Wave client and login in with your account by going to http://wave.google.com. On successful login, you will be inside the Wave client from where you can create a new wave by clicking on the New Wave link as shown below:
When you do that, currently you are the only participant (myself) as shown in the screen below:
Click on the + sign next to your icon and you can add one or more participants as shown below:
NOTE : Your Google Wave Robot is going to be available at <YOURAPPLICATIONID>@appspot.com , hence I have added [email protected] as that was my application id. But you can replace it with your application id.
If all goes well, you will see your Robot added as a participant (with the icon and all, since the Profile Servlet is invoked behind the scenes by the Google Wave system). Since the Robot got added, it received a WAVELET_SELF_ADDED Event and since we had coded our Robot Servlet to receive that event and print out the greeting message, you see the message saying “Hi! Your GAEJExperiments Bot …..”. The message is shown twice at this point since there is some bug in the Google Wave system at this point in time but if it does not seem to go away, you can ignore this event and still continue to process the BLIP_SUBMITTED event. (This issue has been fixed by Google now, at least it seems to be working fine for me)
Next I start typing a message “Hello GAEJ Robot” as shown below. But note that I have still not pressed the Done button. Till the Done button is pressed, the BLIP_SUBMITTED is not fired.
Once I click on the Done button, the BLIP_SUBMITTED event is fired and our Robot Servlet gets the event. On receiving the event, it simply prints out some metadata and echoes back the messag
That is all there is to writing a Google Wave Robot. The example here is not useful as such but the intent of the article is to make sure you get your Robot running and have the right setup in place. Several examples are available over the web in which talented programmers are writing Robots that do clever stuff. Just look around and get inspired.
Going back in Time
In Episode 2 of this series, we discussed how to write a XMPP Bot that you could add as a friend in XMPP Chat clients like Google Talk, Spark, etc. That bot is not ready to be added to a Google Wave since it does not implement the end-points that are discussed here i.e. /_wave/robot/jsonrpc, etc. So all you will need to do is to follow the steps outlined here and provide these Servlet implementations along with the end-points and capabilities file. Just add them to your previous project and redeploy your Google App Engine application. You should then have a Bot that is both XMPP compliant and also Google Wave compliant.
Parting notes
Google has posted some excellent documentation on Wave extensions over here and I recommend them to be read. Key among them is the design aspects about the extensions which are covered here. It is important to add a parting note that Google Wave is about collaboration. Collaboration is a process in which participants join each other and engage in doing something. And if your Robot is to participate in a collaboration then you need to think out well in advance how it will collaborate with the other participants and how it can add value to the process. It has to do something that brings meaning and utility to the collaboration. Of course one can write a fun Robot or a pretty much useless Robot that I have demonstrated here, but the key thing to take away is the immense power that a Robot could play in a collaborative process. Imagine a Robot querying a backend system and fetching a Purchase Order or an Order just placed at a website. Think of a recruiter asking a Robot to pull up interview slots from a backend system and then presenting that to the candidate to choose. The possibilities are endless and it should be an exciting journey ahead to see the Robots that people come up with.
Till the next episode…as the Skipper of the Penguins in the great Madagascar movie said, “Just Smile & Wave, Boys. …. Smile & Wave!!”
P.S:
1. Google Wave has been thrown open to a lot of developers and I hope that you have received an invite already. In case you do not, I still have a few invites to give away. Just write an email to me and I shall send across the invite. First come, First served.
2. (Update: 5-Nov-09): The issue of the Blip message “Hi! Your GAEJ Experiments Bot is waiting…..” arrival message appearing twice has been fixed by Google. So you should no longer see that message appearing twice.