`
mondayw
  • 浏览: 139678 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

[译文]使用Java编写你的第一个Google Wave机器人(下)

    博客分类:
  • Java
阅读更多

原文:Write Your First Google Wave Robot in Java

作者:Mark Watson

出处:http://www.devx.com/Java/Article/43342

 

 

[译文]使用Java编写你的第一个Google Wave机器人(上)

 

 

App Engine上实现一个代理

 

就这个演示程序来说,代理必须能够完成三个步骤:

  1. 向我用来运行CookingSpace的测试服务器发起一个web service调用。
  2.  处理从web service调用中返回的JSON数据。(你可以在这里找到Java JSON库的文档。)
  3. 处理Wave事件。

发出一个web service调用

 

App Engine平台的一个限制就是,你必须使用某个特殊的URL提取服务来调用外部的web service,以下是演示机器人执行web service调用的代码:

 

String data = URLEncoder.encode("search_text", "UTF-8") + "=" + URLEncoder.encode(query, "UTF-8");

    data += "&" + URLEncoder.encode("format", "UTF-8") + "=" + URLEncoder.encode("json", "UTF-8");

    URL url = new URL("http://cookingspace.com");

    URLConnection conn = url.openConnection();

    conn.setDoOutput(true);

    OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());

    wr.write(data);

    wr.flush();

    BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));

    String line = rd.readLine();

    System.out.println("line: " + line);

    wr.close();

    rd.close();

    JSONTokener jt = new JSONTokener(line);

         //处理返回的JSON有效载荷

 

 

作者注:REST架构风格提倡使用HTTP GET来从数据源中获取数据表示,而使用HTTP PUT请求来创建及更新远端的数据源,尽管如此,PUT更常用,因此为了向你展示如何设置一个PUT请求,我决定在这一例子中使用这种方式,像http://cookingspace.com/?search_text=rice&format=json这样的GET请求同样也会很好地执行。

 

演示机器人的源代码包含了一个新的Javacom.cookingspace.rest和一个新的类ServiceCall,该类硬编码访问CookingSpace,如果看一下ServiceCall.java文件中的源代码的话,你就会发现其使用了JSON有效载荷中的数据来为符合搜索内容的食谱创建包含了格式化食谱(有成份、操作指南和营养数据)列表的串值,以下是一个看起来像返回的JSON有效载荷的例子(为了简洁起见,删除了许多文本内容)。

 

[[{"rating": 2.0, "name": "Arroz con Pollo", "directions": "Heat oil in a large skillet  .....",

   "num_served": 4, },

  ["Chicken (fryer)", "1 ", "unit ( yield from 1 lb ready-to-cook chicken)", "vegetable oil", ...],

  [["carbohydrate", 43.60446125], ["energy_in_kcal", 1208.3971164],

   ["fat_mono_unsaturated", 17.0170589726], ["fat_poly_unsaturated", 8.7905745974],

   ["fat_saturated", 5.7239387098], ["fiber", 1.82729], ...],  ....]]]

 

下一步,你将看到Wave演示机器人如何在类文件ServiceCall中使用这一代码。

 

实现Wave演示机器人

 

5展示了Eclipse IDE工程的另一个视图,这次显示了例子需要的所有文件,需要注意的是添加的ServiceCall.java文件以及war/_wave目录下的文件。


 

 

 

5. 添加了所有演示文件的App Engine工程:这是一个包含了演示特需的所有文件的Eclipse IDE工程视图

 

在使用Google App EngineEclipse插件创建新的App Engine工程的时候,Eclipse会自动创建文件src/META-INF/jdoconfig.xml,演示不会用到持久存储,所以你不需要理会该文件(可参阅我之前的关于DevX App Engine的文章,以了解使用App Engine数据存储的例子)。

目录war/_wave下包含的两个XML文件是值得注意的:capabilities.xmlprofile.xmlcapabilities.xml文件用来登记你希望你的机器人从Wave平台上接收的Wave事件:

 

<?xml version="1.0" encoding="utf-8"?>

<w:robot xmlns:w="http://wave.google.com/extensions/robots/1.0">

  <w:version>4</w:version>

  <w:capabilities>

    <w:capability name="wavelet_participants_changed" content="true" />

  </w:capabilities>

  <w:profile name="CookingSpace" />

</w:robot>

 

capabilities的细则要求无论何时只要有人加入wave就通知机器人。(接下来的关于wave机器人servlet的讨论会解释如何处理这一事件。)在另一个wave机器人例子中,登记了其他的需要通知的事件(虽然不是在这此演示):

 

<w:capability name="wavelet_blip_created" content="true" />

    <w:capability name="blip_submitted" content="true" />

 

文件war/_wave/profile.xml规定了演示机器人的名称:

 

<?xml version="1.0"?>

   <wagent-profile>CookingSpace</wagent-profile>

 

CookingSpace机器人使用wave标题作为查找匹配的食谱的搜索字词(参加图6中的标题为“salmon rice”的例子)。

 

6. 创建一个新的Wave这是创建标题为“salmon rice”的新wave的例子

 

CookingSpace机器人的servlet

 

现在来到了处理来自Wave平台的Wave事件通知的servlet中,通知发生在CookingSpace机器人作为一个参与者加入到一个wave中时,因为大部分的事件处理行为都由ServcieCall类来负责,所以这一servlet的实现是很简单的:

 

package com.cookingspace;

 

import com.cookingspace.rest.ServiceCall;

 

import java.util.logging.Logger;

import com.google.wave.api.AbstractRobotServlet;

import com.google.wave.api.Blip;

import com.google.wave.api.RobotMessageBundle;

import com.google.wave.api.TextView;

import com.google.wave.api.Wavelet;

 

@SuppressWarnings("serial")

public class CookingSpaceProxyServlet extends AbstractRobotServlet {

  private static final Logger log = Logger.getLogger(CookingSpaceProxyServlet.class.getName());

 

  @Override

  public void processEvents(RobotMessageBundle events) {

    log.info("Entered processEvents " + events);

    Wavelet wavelet = events.getWavelet();

 

    if (events.wasSelfAdded()) {

      Blip blip = wavelet.appendBlip();

      TextView textView = blip.getDocument();

      textView.append("I'm alive and ready to provide recipes. For more information: ");

      String title = wavelet.getTitle();

      log.info("CookingSpace.com Recipe lookup web service: " + title);

      // String text = eventBlip.getDocument().getText().trim(); // we don't need blip text

      if (title.length() > 3 && title.length() < 30) {

        String results = new ServiceCall(title).results();

        textView.append("CookingSpace.com Recipe lookup web service: " + title + "\n\n" + results);

      }

    }

  }

}

 

日志记录器(logger)用来把有用的信息插入到该应用的App Engine日志中,无论你是写简单的App Engine应用还是Wave机器人,你都会发现App Engine管理控制台的日志查看器是非常有用的,既可以跟踪应用的错误,又可以一般性地理解在处理请求的过程中发生了什么。我把这些日志记录器的调用当作是调试的打印输出,在对我的App Engine应用的正常运行感到满意之后,我通常会去掉他们。

方法调用events.getWavelet()返回Wave系统上的触发了被处理事件的waveletwaveletwave文档的组成部分,由一个或多个blip组成,blip是文档的最小组件。

如果事件是由被添加到wave中的CookingSpace机器人触发的话,方法调用events.wasSelfAdded()返回一个为真的布尔值,如果是这种情况,那么就希望获得wave的标题。“blip”是wave的组成部分,诸如初始的wave内容等等,在当前情况中,该bilp就是CookingSpace机器人将要添加到原来的wave中的新信息(参见图7)。

 

7. CookingSpace机器人加到新wave中:这是把CookingSpace机器人加到标题为“salmon rice”的新wave中的例子。

 

Blip的文本视图显示它的标题和文本内容,前面的代码用到了blip的标题但忽略了blip的文本内容,它把标题传递给ServceCall这一实用工具类,以发起到cookingspace.comweb service调用并格式化返回的食谱(如果有找到的话),然后把食谱的文本内容添加到由Blip blip = wavelet.appendBlip()这一调用所创建的新blip中。

就是这样了!你已经完成了实现机器人的工作,图8展示了添加了CookingSpace机器人后的Wave web客户端,图9展示了客户端显示由机器人添加的食谱,图10则给出了图9中显示的食谱的营养数据。

 

8. 在添加CookingSpace机器人之后:这是添加了CookingSpace机器人后的Wave web客户端。

 

 

9. 显示机器人添加的食谱:这是显示由机器人添加的通过查询“salmon rice”获得的食谱

 

10. 显示机器人添加的食谱的营养:这是显示图9中的食谱的营养数据的wave web客户端。

 

如果希望以Wave机器人的方式重用你的任何应用的话,这一简单的演示程序提供了一种快速启动的方法,演示程序的几乎所有的工作都已在ServiceCall这一实用工具类中开发并测试过了。当在Wave机器人方面积攒了更多经验之后,你只需要几分钟时间就可以完成开始一个新的Wave机器人工程的“样板”工作:

  1.  创建一个新的Eclipse工程
  2. 添加所需的Wave客户端JAR文件
  3. 编写事件处理servlet

 

Wave机器人开发过程中会遇到的问题

 

在开发Wave机器人的时候,我遇到了几种常见的问题:

  1. 因为无法本地测试Wave事件/机器人的交互而导致的开发周期缓慢
  2.  改动Wave API和我的机器人有时会导致接收不到事件通知,两种情况都是因为Wave平台还处于测试状态中。

不过这些问题都不是致命的。因为Wave机器人实际上是web service,因此我在本地测试了这些服务的应用代码,这样,当开始进行测试部署时,我通常只需要处理所遇到的Wave平台本身的问题,因此,测试尽可能都是在本地进行的,因为App Engine平台的构建/部署/测试周期只需要几分钟的时间。

可能有时候要耐心地处理一些Wave服务问题,如果我引发了一个Wave事件(例如创建一个新Wave并添加我的机器人),但这一事件没有在App Engine的控制台应用日志中显示出来的话,我通常就在另一工程上工作,然后再来重试我的测试,随着Wave平台越来越稳定,这种做法可能就变得不是那么需要了。

 

进一步

 

你现在应该可以使用Google Wave平台作为又一个发布和部署平台了,本文开始部分的图1和图2还展示了Facebook作为现有web应用的另一个发布平台的情形,在使用本文中的例子来把你的某个web应用以Wave机器人的方式发布之后,你可以尝试着根据这些简单的步骤来把它以Facebook应用的方式进行发布(如果你还没有这样做过的话)。

 

 

 

 

  • 大小: 36.7 KB
  • 大小: 14.5 KB
  • 大小: 12.4 KB
  • 大小: 12.5 KB
  • 大小: 46.6 KB
  • 大小: 17.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics