将 Flex 应用程序与 IBM Mashup Center 集成

IBM® Mashup Center 为构建 mashup 应用程序提供了很多即用型小部件(widget)。另外,还可以使用 Lotus Widget Factory、JavaScript™ 和其他编程语言开发更多的小部件。本文将探索如何在 IBM Mashup Center 中使用 Adobe® Flex 应用程序。

Ronald C. Leung, 软件工程师,Mashup Hub Enablement, IBM

Ronald Leung 是 IBM Mashup Center Customer Enablement 小组的成员,是 IBM InfoSphere MashupHub 的解决方案架构师。



2009 年 6 月 05 日

IBM Mashup Center 提供了很多可用于构建 mashup 应用程序的即用型小部件。使用这些小部件可以在网格、线形图甚至地图上显示数据。有时候,需要对图形用户界面(GUI)的显示进行更多的定制,而已有小部件 中可用的设置还不够。

有多种方式可以开发自己定制的小部件。IBM Mashup Center 附带有 Lotus Widget Factory,这是一个很棒的 GUI 工具,通过它无需编写代码就可以开发定制的小部件。如果您熟悉 JavaScript、Dojo 或其他编程语言,那么可以根据 iWidget 规范通过编写代码开发定制的小部件。iWidget 框架非常灵活,它允许与其他技术无缝集成。在本文中,学习如何将 Adobe Flex 应用程序与 IBM Mashup Center 集成,从而显著增强 mashup 的威力。

您应该对 iWidget 框架和 Adobe Flex 编程有基本的认识。

Flex 应用程序概述

Flex 是用于构建富 Internet 应用程序的一个流行的开源框架,可以使用 Adobe Flash Player 在大多数浏览器中运行这些应用程序。Flex 提供很多 GUI 界面组件。图 1 显示一个示例 Flex 仪表板应用程序,其中有交互式和动画效果的图表。

图 1. Flex 销售仪表板演示
Flex 销售仪表板演示

要在浏览器中运行 Flex 应用程序,只需将一个 object 标记嵌入到 HTML 页面中。这个标记用于装载 Flash 播放器,并传入适当的参数。清单 1 是脚本的一个例子。

清单 1. 将 object 标记嵌入到 HTML 页面中
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 
id="BasicDataGrid" width="482" height="348"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" 
value=" http://drill.svl.ibm.com/mashuphub/demo/Flex/FlexDataGridSample.swf"/>
	<param name="wmode" value="opaque"/>
	<param name="quality" value="high"/>
	<param name="bgcolor" value="#869ca7"/>
	<param name="allowScriptAccess" value="always"/>
<embed src= 
"http://drill.svl.ibm.com/mashuphub/demo/Flex/FlexDataGridSample.swf" quality="high"
bgcolor="#869ca7" width="482" height="348" name="BasicDataGrid" align="middle" 
play="true" loop="false" wmode="opaque" allowScriptAccess="always" 
type="application/x-shockwave-flash"
		pluginspage="http://www.adobe.com/go/getflashplayer">
	</embed>
</object>

可以在 Adobe 站点 上了解更多关于 Flex 的信息。


Flex 应用程序开发环境

Adobe 为开发 Flex 应用程序提供了很多不同的工具。Flex Builder 是一个基于 Eclipse 的 IDE,它提供了很多很棒的特性,例如代码完成、分步调试和可视化布局的拖放设计。另外还有一个免费的 SDK 可以作为商业的 Flex Builder 的替代品。请访问 Adobe 站点,了解更多关于 Adobe 工具 的详细信息。


开发 Lotus Mashups iWidgets

IBM Mashup Center wiki 提供了关于小部件开发的一些有用的信息。

对于不熟悉 iWidgets 的开发人员,这个演示 是最好的入门点。

对 iWidget 开发的详细描述超出了本文的范围,但我们还是回顾一下 iWidget 中和 Flex 应用程序集成相关的一些关键组件:widget 定义 XML 文件和小部件 JavaScript 类文件。

Widget 定义 XML 文件

该文件有以下用途:

  • 指定 JavaScript 类文件:

    <iw:resource uri="FlexWrapper.js"/>
  • 定义小部件应该发布的事件。清单 2 显示该小部件发布一个名为 sendData 的事件。
清单 2. 定义小部件发布的事件
<iw:event id="sendData" published="true"   
    eventDescName="desc_sendData" /> 
<iw:eventDescription id="desc_sendData" payloadType="any" 
    description="This event sends data out." lang="en"> </iw:eventDescription>
  • 定义小部件应该处理的事件,以及收到事件时调用的方法。清单 3 显示该小部件可以接收名为 receiveData 的事件,收到这种事件时会触发函数 handleData。
清单 3. 定义小部件处理的事件
<iw:event id="receiveData" handled="true"    
      onEvent="handleData" description="receiveDataDesc"/>  
      <iw:eventDescription id="receiveDataDesc" payloadType="any" 
      description="Receive some data" lang="en">
</iw:eventDescription>
  • 定义小部件在 view 模式下显示的内容。这是在 mashup 页面上装载小部件时显示的主界面。在这个例子中,如清单 4 所示,小部件的视图中有一个 <div> 标记,其中显示 “Hello”。在运行时,可以使用 JavaScript 操纵该标记的内部 HTML 代码,以显示其他内容。
清单 4. 定义 view 模式下的内容
<iw:content mode="view">
   <![CDATA[ 
      <div id="_IWID_FlexDiv">
         Hello.
      </div> 
   ]]>
</iw:content>
  • 定义小部件在 edit 模式下显示的内容或小部件的设置。settings 标记通常包含一些 HTML 输入元素,以便用户输入一些值,另外它还包括一个 save 和 cancel 按钮,如清单 5 所示。
清单 5. edit 模式中的 settings 标记
<iw:content mode="edit">
    <![CDATA[
        <table>
        <tr>
            <td>Settings 1: 
            </td>
            <td><input id="param1" type="text" size="50">
            </td>
        </tr>
        <tr>
            <td>Settings 2: 
            </td>
            <td><input id="param2" type="text" size="50">
            </td>
        </tr>
    </table>
    <div class="mmDialogBottomArea">
    <a  
      href="javascript:iContext.iScope().cancelConfigData()" 
      id="_IWID_CONF_CANCEL" class="common_cancel">Cancel
     </a>
     <input id="_IWID_CONF_SAVE" class="lotusFormButton" 
         type="button" value="Save" name="save" 
         onclick="iContext.iScope().saveParams();" >
    </div>
   ]]>
</iw:content>

Widget JavaScript 类文件

该文件包含小部件对象的实现。该文件中的代码负责在初次装载小部件时初始化小部件,并发布和处理事件,以便与其他小部件通信。


在 Lotus Mashup 中运行简单的 Flex 应用程序

如前所述,只需在 HTML 页面中添加一个 object 标记,就可以将 Flex 应用程序嵌入到 Web 页面中。IBM Mashup Center 提供了一个即用型小部件,用于将 HTML 片段嵌入 mashup 页面。

遵循以下步骤:

  1. 在 Tools 下找到小部件,将它拖放到画布上。如图 2 所示。

    图 2. 添加 HTML Markup 小部件
    添加 HTML Markup 小部件
  2. 编辑设置,并粘贴 Flex 应用程序的 Flex 应用程序脚本标记,如图 3 所示。

    图 3. 设置 HTML Markup 小部件
    设置 HTML Markup 小部件
  3. 单击 Save。Flex 应用程序在 mashup 页面上运行,如图 4 所示。

    图 4. 在 HTML Markup 小部件中运行 Flex 应用程序
    在 HTML Markup 小部件中运行 Flex 应用程序

能用这种方法显示 Flex 应用程序是件很棒的事情。但是,要真正与 Lotus Mashups 集成,这些应用程序必须能够与其他 iWidget 通信。本文后面将讨论设置 Flex 应用程序与其他 iWidget 之间的通信框架的架构。


将 Flex 应用程序与 Lotus Mashups 集成

要将 Flex 与 Lotus Mashup 集成,关键的思想是构建一个包装器 Lotus Mashup iWidget。这个包装器 iWidget 有三个作用:

  • 显示 Flex 应用程序的用户界面。
  • 发布 iWidget 事件。当 Flex 应用程序需要发送事件时,Flex 应用程序首先将数据发送到这个包装器 iWidget,然后,包装器 iWidget 将真正的事件和数据发布到其他 iWidget。
  • 处理 iWidget 事件。当其他 iWidget 需要发送事件到 Flex 应用程序时,包装器 iWidget 首先处理事件。然后,包装器 iWidget 将数据转发到 Flex 应用程序以作进一步的处理。

本文的下载小节提供了一个示例 Flex 应用程序和相应的包装器 iWidget。这个 Flex 应用程序包含具有预先装载的数据的数据网格。我们展示如何通过发布和接收事件,将这个 Flex 应用程序与其他 iWidget 连接。通过这个包装器 iWidget,可以将 Flex 应用程序中选择的数据发送到另一个 iWidget。同样,还可以使用其他 iWidgets 将行添加到这个 Flex 应用程序中。

文件 FlexDataGridSample.mxml 包含 Flex 应用程序代码;如图 5 所示。文件 FlexWrapper.war 包含 iWidget 和 Flex 应用程序二进制文件。这个小部件可以像常规的 iWidget 一样部署到 Mashup Center 上。将小部件上传并添加到 Lotus Mashup 页面上之后,编辑该小部件的设置。对于 Flex 应用程序 URL 参数,值应该为:

http://[yourserver:port]/widgets/FlexWrapper/FlexDataGridSample.swf

图 5. 设置示例 Flex 包装器 iWidget
设置示例 Flex 包装器 iWidget

接下来的小节介绍示例小部件的一些重要部分,以展示如何集成这个包装器 iWidget 和 Flex 应用程序。

在包装器小部件中显示 Flex 应用程序

为了显示 Flex 应用程序,将 object 标记插入到小部件的视图中。在包装器 iWidget 的定义文件 FlexWrapper.xml 中,已经定义了 view 区段包含一个简单的 div 标记,作为 Flex 应用程序的占位符,如清单 6 所示。

清单 6. 定义 view 区段
<iw:content mode="view">
   <![CDATA[ 
      <div id="_IWID_FlexDiv">
      </div> 
   ]]>
</iw:content>

在运行时,包装器 iWidget 构造装载 Flex 应用程序的 object 标记。可以通过查看 FlexWrapper.js 文件中的 onview 函数,了解这个标记是如何构造的。这个标记需要很多参数。大多数值可以硬编码,还有一些值应该由用户提供,或者在运行时自动生成。例如,小部件包装器可以允许用户传入 Flex 应用程序的名称,Flash 文件的位置,以及这个小部件的大小,如图 5 所示。通过允许用户传入这些变量,可以将小部件包装器重复用于多个 Flex 应用程序,只要这些应用程序发布和接收相同的一组事件就行了。清单 7 中的代码显示需要生成的标记的一个示例。加粗的参数必须自动生成。斜体的参数由用户传入,必要时也可以硬编码。

清单 7. 标记示例
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 
id="XXXXXXXXX" width="482" height="348"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" 
value=" http://drill.svl.ibm.com/mashuphub/demo/Flex/FlexDataGridSample.swf"/>
	<param name="wmode" value="opaque"/>
	<param name="quality" value="high"/>
	<param name="bgcolor" value="#869ca7"/>
	<param name="allowScriptAccess" value="always"/>
	<param name="FlashVars" value="iWidgetID=XXXXXX"/>
<embed src= 
"http://drill.svl.ibm.com/mashuphub/demo/Flex/FlexDataGridSample.swf" quality="high"
bgcolor="#869ca7" width="482" height="348" name="XXXXXXXXXXX" align="middle" 
play="true" loop="false" wmode="opaque" allowScriptAccess="always" 
type="application/x-shockwave-flash"
FlashVars="iWidgetID=XXXXXXXXXX"
		pluginspage="http://www.adobe.com/go/getflashplayer">
	</embed>
</object>

我们来看看必须自动生成的参数。object 标记的 id 属性和 embed 标记的 name 属性在整个 mashup 页面内必须是惟一的。否则,当同一个页面上有这个包装器 iWidget 的多个实例时,它们之间会发生冲突。iWidget 框架为页面上装载的每个小部件生成一个惟一的 ID,可以通过下面的调用获取这个小部件 ID:

this.iContext.widgetId

我们将使用这个 ID 作为 object 标记的 ID 和 name 的一部分,以确保小部件包装器的每个实例都有一个惟一的 ID。在 Flex 包装器的 onview 函数中可以看到,您获取了这个小部件 ID,并将它保存在变量 domID 中。我们将 Flex 应用程序的名称与小部件 ID 连在一起,然后将这个字符串设置为该标记的 ID 和 name:

this.flexAppName + this.domID

这样一来,包装器 iWidget 的每个实例都有一个惟一命名的标记。最后需要动态生成的参数是 FlashVars 的值。FlashVars 中定义的变量可以从 Flex 应用程序中访问。在运行时,Flex 应用程序需要根据惟一的小部件 ID 找到包装器 iWidget 对象的正确实例。我们将小部件 ID 保存在一个名为 iWidgetID 的变量中,在后面的小节中,可以看到 Flex 应用程序如何获取这个值。

用正确的参数值构造好 object 标记后,就可以通过以下调用将它嵌入到 Flex 应用程序占位符 div 标记中:

dojo.byId(this.domID + "FlexDiv").innerHTML = flexDivHTML;

现在,当小部件装载并触发 onview 函数时,它会显示 Flash 应用程序,如图 6 所示。

图 6. 在 iWidget 中显示 Flex 界面
在 iWidget 中显示 Flex 界面

将事件从 Flex 发送到其他小部件

Flex 中的大多数用户界面组件都可以处理用户事件。例如,每当用户单击一个特定的行时,DataGrid 组件触发一个事件。在这个例子中,当用户单击一个行时,需要将选中的数据往外发送到另一个 iWidget。要完成该任务,需要执行三个步骤:

  1. 在小部件定义 XML(见 FlexWrapper.xml 文件)中定义一个要发布的事件。
  2. 在包装器 iWidget 实现中实现发布该事件的 JavaScript 函数。
  3. 在 Flex 应用程序中,当需要发送事件时,调用该 JavaScript 函数。

要定义一个事件,可以像对待常规的 iWidget 一样,将清单 8 中的代码片段添加到小部件定义 XML 中。

清单 8. 定义事件
<iw:event id="sendData" published="true"   
    eventDescName="desc_sendData" /> 
<iw:eventDescription id="desc_sendData" payloadType="any" 
    description="This event sends data out." lang="en"> </iw:eventDescription>

发布事件只需一行代码。函数 sendData 使用清单 9 中显示的代码发布事件。

清单 9. 发布事件
 sendData : function(data) {                    
      if(data != null){            
         this.iContext.iEvents.publishEvent("sendData", data);
      }
   }

最后一步是从 Flex 应用程序中调用这个 sendData JavaScript 函数。在 flex 应用程序中,首先像通常一样定义数据网格组件的 Flex 事件处理程序。当用户单击一行时,函数 sendData 被调用:

<mx:DataGrid id="dgPeople" x="10" y="10" initialize="initDG()"
width="422" height="268" click="sendData()">

在函数 sendData 中,需要找到并调用发布事件的 JavaScript 函数。如清单 10 所示。

清单 10. 找到并调用 JavaScript 函数
    public function sendData():void
    {           
      if (ExternalInterface.available) { 
     ExternalInterface.call(Application.application.parameters.iWidgetID + 
     "iContext.iScope().sendData", dgPeople.selectedItem);        
      } 
    }

可以看到,只需几行代码就可以触发 JavaScript 函数。ExternalInterface 是一个 Flex 对象,通过它可以调用 Flex 应用程序之外的对象。要找到适当的包装器 iWidget,可以调用:

Application.application.parameters.iWidgetID +
"iContext.iScope().sendData"

iWidgetID 这个值看上去是否有点熟悉?这就是在前一小节中设置的值。之前是在 FlashVars 参数中设置它,现在 Flex 应用程序可以获取该值,并找到要调用的正确的函数。值 dgPeople.selectedItem 包含数据网格中被选中的行,格式为 JSON。图 7 显示了整个架构。

图 7. 通过包装器从 Flex 发布事件
通过包装器从 Flex 发布事件

可以将包装器 iWidget 连接到一个常规的 Event Explorer 小部件。当用户从 Flex Wrapper 小部件中选择一行时,数据以 JSON 的格式被发送到 Event Explorer,如图 8 和图 9 所示。

图 8. 将 Flex 包装器连接到 Event Explorer
将 Flex 包装器连接到 Event Explorer
图 9. 将数据从 Flex 发送到 Event Explorer
将数据从 Flex 发送到 Event Explorer

在 Flex 中处理来自其他小部件的事件

可以以类似的方式在 Flex 中处理 iWidgets 事件。要完成该任务,需要执行四个步骤:

  1. 定义要在包装器 iWidget 中处理的事件。
  2. 在 Flex 应用程序中,像在任何其他 Flex 应用程序中一样,实现一个事件处理程序。对于示例的数据网格,可创建一个名为 receiveData 的处理程序,它接收一些字符串,并将一个行添加到网格中。
  3. 在 Flex 应用程序中,注册一个回调函数,以公布事件处理程序 receiveData。当收到事件时,这个回调使包装器 iWidget 可以触发这个函数。
  4. 在包装器 iWidget 中实现事件处理程序,以调用 Flex 回调函数。

包装器 iWidget 首先在 XML 实现文件中定义它接收的事件。如清单 11 所示。

清单 11. 定义事件
<iw:event id="receiveData" handled="true"    
      onEvent="handleData" description="receiveDataDesc"/>  
      <iw:eventDescription id="receiveDataDesc" payloadType="any" 
      description="Receive some data" lang="en">
</iw:eventDescription>

该代码允许其他小部件将数据传递到包装器 iWidget。当收到一个事件时,会触发 handleData 函数(后面会实现)。

首先需要在 Flex 中实现一个处理程序。在这个示例 Flex 数据网格中,要显示一些雇员的姓名、职称和年龄。这里实现一个将一名雇员添加到列表中的处理程序,如清单 12 所示。

清单 12. 添加一名雇员
    public function receiveData(name:String, title:String,
      age:String):void
    {
      (dgPeople.dataProvider as ArrayCollection).addItem(
          {Name: name, Title: title, Age: age});
    }

清单 12 中的变量 dgPeople 是对显示人员列表的 Flex 数据网格对象的一个引用。JavaScript 如何触发 Flex 函数?只需添加一个回调。首先创建一个名为 initApp() 的函数,当 Flex 应用程序初始化时,将触发该函数,如清单 13 所示。

清单 13. 添加一个回调
   <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
      layout="absolute" width="482" height="348" 
      initialize="initApp()">

在 initApp() 中,添加一个回调,以公布函数 receiveData,如清单 14 所示。

清单 14. 添加一个公布 receiveData 函数的回调
   public function initApp():void
   {
      if (ExternalInterface.available)
        ExternalInterface.addCallback("receiveData", receiveData);  
   }

最后一步是实现 iWidget 事件处理程序,以触发 Flex 回调。要找到 Flex 回调,首先需要按标记名称找到 Flex 应用程序。在 “在包装器小部件中显示 Flex 应用程序” 小节中,已经将 Flex 包装器小部件标记的 ID 指定为 this.flexAppName + this.domID。这就是用于找到 Flex 应用程序的 ID。清单 15 中的代码找到 Flex 应用程序并触发 receiveData 函数。

清单 15. 找到 Flex 应用程序并触发 receiveData 函数
    handleData: function(JSONpayload) { 	      
        var data = eval('(' + JSONpayload.payload + ')');    	     	    
        this.getFlexApp(this.flexAppName + this.domID).receiveData(
           data.Name, data.Title, data.Age);  
    },
    getFlexApp: function(appName) {
        if (navigator.appName.indexOf ("Microsoft") !=-1) {
            return window[appName];
        } else {
        return document[appName];
        }
    }

handleData 函数被实现为处理 JSON 数据,但是可以对它进行定制,使之处理其他数据类型。图 10 显示了架构的轮廓。

图 10. 在 Flex 中处理 iWidget 事件
在 Flex 中处理 iWidget 事件

现在可以连接这个小部件,以处理一些事件。对于这个例子,可以使用 User Input 小部件创建一个表单,用于输入新的雇员数据。然后,可以将输入的值以 JSON 的格式连接到 Flex 包装器小部件。遵循以下步骤:

  1. 从 Favorites 中拖出一个 User Input 小部件,如图 11 所示。

    图 11. 添加 User Input 小部件
    添加 User Input 小部件
  2. 编辑设置,添加 3 个名为 Name、Title 和 Age 的文本框,如图 12 所示。

    图 12. 设置 User Input 小部件
    设置 User Input 小部件
  3. 将 User Input 小部件连接到 Flex 包装器 iWidget,如图 13 所示。

    图 13. 将 User Input 小部件连接到 Flex 包装器
    将 User Input 小部件连接到 Flex 包装器
  4. 现在小部件已连接。在 User Input 小部件中输入新员工的姓名,单击 Submit,新的姓名就出现在 Flex 数据网格中,如图 14 所示。

    图 14. 将数据从 User Input 小部件发送到 Flex 包装器
    将数据从 User Input 小部件发送到 Flex 包装器

祝贺您!您已经成功地将一个 Flex 应用程序包装在一个 iWidget 中,这个 Flex 应用程序现在可以发布和处理 iWidgets 事件,并且可以与其他 iWidget 通信。


结束语

在本文中,您了解了将 Flex 应用程序与 IBM Mashup Center 集成的架构。将 Flex 与 iWidget 集成的关键思想是构建一个包装器 iWidget。通过这个包装器 iWidget,Flex 应用程序可以将事件发布到其他 iWidget,也可以处理来自其他 iWidget 的事件。示例应用程序演示了如何将 Flex 数据网格对象中的内容发送到 Event Explorer iWidget;它还展示了如何接收 User Input iWidget 中输入的内容,并将它添加到 Flex 数据网格中。通过本文描述的机制,还可以将其他 Flex 用户界面组件,例如树视图、图表等与 IBM Mashup Center 集成。mashup 创建者可以利用 Flex 的这种功能增强 mashup 的特性。


下载

描述名字大小
FlexDataGridSample.mxml1.98KB
FlexWrapper.zip986KB

参考资料

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Lotus
ArticleID=394586
ArticleTitle=将 Flex 应用程序与 IBM Mashup Center 集成
publish-date=06052009