内容


创建基于 Flex 的小部件以在 Business Space 中显示 WebSphere Business Monitor 数据

Comments

引言

WebSphere Business Monitor V6.2(以下称为 Monitor)的 Business Space 使用 iWidget 组件模型(要阅读规范,请参见参考资料)。iWidgets 允许 Business Space 支持多种类型的浏览器组件,包括纯 HTML、JavaScript、使用 Dojo 框架的 JavaScript和使用 Adobe Flex 框架编写的基于 Adobe Flash® 的组件。通过 iWidget 模型,您可以使用所选浏览器技术为 Business Space 开发和部署自己的小部件。

在本文中,您将了解如何将 Flex 小部件部署到业务空间中。提供了一个企业应用程序供下载。此应用程序包含基于 Flex 的示例 iWidget,该 iWidget 能访问来自 Monitor 数据库的数据。您将了解如何注册 iWidget,以便将其从 Business Space 小部件菜单拖放到页面上,以及如何从 Flex 应用程序访问 Monitor 数据。您通过本文获得的知识将帮助您开发 Flex 小部件,从而为您的业务环境提供独特的功能。

假设

对于本文,我们有以下假设:

  1. 您对 Monitor V6.2 安装有管理访问权限。
  2. 您知道如何安装 WebSphere 应用程序。如果不知道,请参见参考资料,以了解安装应用程序或模块的多种方式。
  3. 您熟悉如何在 Business Space 中管理空间和页面。
  4. 您熟悉 Adobe Flex、JavaScript、Dojo 和 XML。

下载并解压缩示例文件

本文提供了以下示例文件

  • FlexKPIHistorySample.ear 是一个企业应用程序存档(Enterprise Application Archive,EAR)文件,可安装到 Monitor V6.2 中。我们要使用的 Flex 小部件就包含在此 EAR 文件中。
  • flexSampleFiles.zip 包含本文中讨论的文件。

下载这两个文件,并将 flexSampleFiles.zip 解压缩到您计算机上的目录中。

部署并运行 Flex iWidget 示例

本文提供的示例将在部署在 Business Space 中的 Flex 小部件中显示关键性能指标(Key Performance Indicator,KPI)历史数据。KPI 数据从 Better Lender Showcase 检索得到,后者在从 First steps 中选择 Showcase model 时将自动随 Monitor V6.2 安装。

部署示例

要部署示例,请执行以下操作:

  1. 将 FlexKPIHistorySample.ear 安装到 Monitor V6.2 中,并启动应用程序。
  2. 在解压缩 unzipped flexSampleFiles.zip 的位置找到 registryData 目录,将 flexKPIHistorySampleWidget.xml 和 flexSampleEndpoints.xml 复制到您的 Monitor V6.2 安装的以下目录中:
    <installdir>\profiles\<profilename>\BusinessSpace\registryData
    例如,在 Windows® 计算机上:
    Q:\IBM\WebSphere\MonServer\profiles\WBMon01\BusinessSpace\registryData
    请注意,此目录位于 profiles 目录下,不是更高级别的目录(在 Windows 上):
    Q:\IBM\WebSphere\MonServer\BusinessSpace\registryData

运行示例

要运行示例,请进行以下操作:

  1. 登录到 Business Space,并导航到您希望放置示例小部件的页面。
  2. 打开 Add Widgets 菜单,并找到名为 Flex Samples for Business Space 的类别。您将在此类别中看到小部件 Flex KPI History Sample
  3. 将此小部件拖动到您的页面上。此小部件显示名为 Month-to-Date Amount of Completed Loans 的 KPI 的历史数据(每天和每周的数据)。小部件左下角的下拉列表允许您在数据的曲线图、面积图和柱状图表示形式之间切换。
图 1. 向 Business Space 添加 Flex 小部件
向 Business Space 添加 Flex 小部件
向 Business Space 添加 Flex 小部件

iWidget 定义和实现文件

在 Business Space 中部署的每个小部件都有 iWidget 定义和实现文件。示例文件为:

  • flexKPIHistorySample_iWidget.xml,定义文件
  • flexKPIHistorySample.js,实现文件

这些文件位于解压缩 flexSampleFiles.zip 文件目录的子目录 iWidgetFiles 中。

在文本编辑器中打开这些文件,查看其内容。

iWidget 定义文件

定义文件 flexKPIHistorySample_iWidget.xml 描述小部件的属性。以下属性对于示例小部件非常重要。

<iw:iwidget> 标记:

  • id="flexKPIHistorySample"

    此 ID 在部署文件 flexKPIHistorySampleWidget.xml 中引用。

  • id="flexKPIHistorySample"

    此 ID 在部署文件 flexKPIHistorySampleWidget.xml 中引用。

  • iScope="com.ibm.bspace.widgets.samples.FlexKPIHistorySampleWidget"

    iScope 值是示例小部件的完全限定名称。此值也出现在 iWidget 实现文件 flexKPIHistorySample.js 中。

  • supportedModes="view"

    此小部件支持查看模式,但不支持编辑模式。

<iw:resource> 标记:

  • uri="<relativepath>/BSpaceCommonUtilityLoader.js"

    此文件提供 Business Space 实用程序。

  • uri="flexKPIHistorySample.js"

    这是 iWidget 实现文件,因此当然也是必需的!

<iw:content> 标记

  • mode="view"

    此内容用于视图模式(视图模式是此小部件唯一的模式)。

  • span id="_IWID_KPIHistorySampleSampleWidget"

    这是放置 Flash 内容的位置。

iWidget 实现文件

实现文件 flexKPIHistorySample.js 显示小部件,并处理刷新和卸载之类的事件。实现文件的以下部分对示例小部件非常重要。

dojo.provide 和 dojo.declare:

  • "com.ibm.bspace.widgets.samples.FlexKPIHistorySampleWidget"

    这是示例小部件的完全限定名称。此值也出现在 iWidget 定义文件 flexKPIHistorySample_iWidget.xml 中。

onview: function(){}

  • var endpoint = this.getServiceURLRoot();

    此小部件将需要访问 Monitor 数据。endpoint 将包含请求 Monitor 数据库的必要 URL。

  • var url = this.iContext.io.widgetBaseUri+"FlexKPIHistorySample.swf";

    这将定位 Flash 内容;在页面上放置 Flash 内容时,将使用 url

  • selectionTextNode.innerHTML = "<object id='"+id etc.

    这将在页面上放置 Flash 内容。

Business Space 注册文件

在 Business Space 中部署的每个小部件都必须向 Business Space 注册。我们的示例有两个注册小部件的文件。示例文件为:

  • flexKPIHistorySampleWidget.xml,小部件的注册文件
  • flexSampleEndpoints.xml,小部件的端点文件

这些文件位于解压缩 flexSampleFiles.zip 文件目录的子目录 registryData 中。

现在将其打开,以查看其内容。

小部件注册文件

注册文件 flexKPIHistorySampleWidget.xml 告知 Business Space 小部件所在位置、其在小部件菜单中所属的类别以及小部件的显示名称和其他详细信息。注册文件的以下部分对示例小部件非常重要。

<tns:Category> 标记:

  • <tns:id>{com.ibm.bspace}bspaceflexsamplewidgets</tns:id>

    这是我们的新小部件类别的 ID。

  • <tns:name>, <tns:description>, etc.

    一目了然的属性

<tns:Widget> 标记:

  • <tns:id>{com.ibm.bspace}flexKPIHistorySample</tns:id>

    ID flexKPIHistorySample 也在 iWidget 定义文件中使用;此 ID 将注册表项与 iWidget 定义文件关联。

  • <tns:type>{com.ibm.bspace}iWidget</tns:type>

    将小部件标识为 Business Space iWidget.

  • <tns:categoryId>{com.ibm.bspace}bspaceflexsamplewidgets</tns:categoryId>

    标识此小部件所属的类别。

  • <tns:widgetEndpointId>{com.ibm.bspace}flexKPIHistorySampleId</tns:widgetEndpointId>

    提供承载我们的小部件的示例应用程序的上下文根。上下文根实际上在小部件端点文件(在下面描述)中定义。

  • <tns:url>widgets/samples/flexKPIHistorySample
    /flexKPIHistorySample_iWidget.xml</tns:url>

    标识我们示例应用程序内 iWidget 定义文件的位置。如前面所述,iWidget 定义文件标识实际在页面上放置小部件的 JavaScript 实现文件。

  • <tns:serviceEndpointRef…
    <tns:name>serviceUrlRoot</tns:name>
    <tns:refId>{com.ibm.wbimonitor}monitorServiceRootId</tns:refId>

    标识为 Monitor 数据访问提供 URL 的服务端点。请注意,{com.ibm.wbimonitor}monitorServiceRootId 在与我们的小部件注册文件相同的目录中的另一个文件中声明。这个文件是 monitorEndpoints.xml。

小部件端点文件

端点文件 flexSampleEndpoints.xml 告知 Business Space 承载小部件的应用程序的上下文根。

<tns: Endpoint > 标记:

  • <tns:url>flexKPIHistorySample/</tns:url>

    这是我们的示例应用程序的上下文根。

使用 Flex 创建用户界面

创建 Flex 应用程序的第一个步骤是指定哪些内容将位于页面上,以及位于何处。对于我们的示例,我们希望看到:

  • 位于右上角的 KPI 名称
  • 两个并列的 Flex 图表,在图表上部有历史数据粒度级别的标签
  • 控制图表数据级数类型的下拉菜单

为了方便起见,可以利用 Flex Builder 的设计视图。打开 Flex Builder 并创建新 Flex 项目。创建新 Flex 应用程序后,切换到设计视图。通过此视图,您可以通过将组件拖放到设计面板来快速组装 UI 的框架,如图 2 中所示。

图 2. Flex Builder 设计视图
Flex Builder 设计视图
Flex Builder 设计视图

图 3 显示了设计视图面板旁边的组件列表。

图 3. 组件列表
组件

切换回 Source 视图,将能够看到构建程序生成的 MXML 代码,如清单 1 中所示。

清单 1. 生成的 MXML 代码
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 <mx:VBox x="10" y="10" width="100%" height="100%">
  <mx:Label text="Label"/>
   <mx:HDividedBox width="100%">
	<mx:VBox height="100%">
       <mx:Label text="Daily"/>
	 <mx:LineChart id="linechart1">
	   <mx:series>
		<mx:LineSeries displayName="Series 1" yField=""/>
	   </mx:series>
	 </mx:LineChart>
	</mx:VBox>
	<mx:VBox height="100%">
	 <mx:Label text="Weekly"/>
	 <mx:LineChart id="linechart2">
	   <mx:series>
	      <mx:LineSeries displayName="Series 1" yField=""/>
	   </mx:series>
	 </mx:LineChart>
	</mx:VBox>
  </mx:HDividedBox>
  <mx:ComboBox></mx:ComboBox>
 </mx:VBox>
</mx:Application>

让我们看看构建程序生成的代码。根级别是 Application 的 MXML 标记,这是任何 Flex 应用程序的起点。在 Application 中,可以定义基础布局和其他可视化组件。您可以使用 ActionScript 通过将组件作为现有组件的子项追加来动态地将其添加到页面。

在我们的示例中,Application 之上的级别是 VBox。顾名思义,这是布局容器,将自动地垂直对齐所有子组件。Flex 提供了以下布局容器组件,以便设计 Flex 应用程序的结构:

  • Application ControlBar
  • Box(HBox 和 VBox)
  • Canvas
  • ControlBar
  • DividedBox(HDividedBox 和 VDividedBox)
  • Form
  • Grid
  • Panel
  • Tile
  • TitleWindow

有关这些组件的更多信息,请参见参考资料

在我们的 VBox,我们希望看到三个垂直对齐的子组件,如图 4 中所示:

图 4. VBox 中的布局
VBox 中的布局

Label 组件用于显示 KPI 名称;HDividedBox 是图表及其标签的占位符;ComboxBox 作为切换不同的图表数据级数的控制器使用。我们选择了三个级数类型在这里进行演示:LineSeries、AreaSeries 和 PlotSeries。我们将在本文稍后进一步讨论图表组件。

图 5. HDividedBox 中的布局
HDividedBox 中的布局

HDividedBox 中,我们嵌套了另一个 VBox。这两个 VBoxe 中的图表将自动在 HDividedBox 并排水平对齐。内部的 VBox 用于将粒度标签与对应图表分组到一起。

此页上的最后一个可视化组件是 ComboBox。这个 ComboBox 旨在控制两个图表的数据级数类型,但如果不使用正确值和标签对其填充,就不能正常工作。

接下来我们向 Application 添加 Script 部分,并定义包含 ComboBox 的值的 CHART_TYPES 变量,如清单 2 中所示。

已完成的本示例的 MXML 源代码可以在解压缩 flexSampleFiles.zip 的 FlexSource 目录的 FlexKPIHistorySample.mxml 中找到。

清单 2. 定义图表类型(摘自 FlexKPIHistorySample.mxml 的代码片段)
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
   <![CDATA[
   [Bindable] privatevar CHART_TYPES:Array = 
				[{label:"Line Chart",data:"Line Chart"},
				 {label:"Area Chart",data:"Area Chart"}, 
				 {label:"Plot Chart",data:"Plot Chart"}];
   ]]>
</mx:Script>

为了使用这些 CHART_TYPES 填充 ComboBox,您现在所需要做的就是,指定 CHART_TYPES 变量作为其 dataProvider,如此处所示:
<mx:ComboBox dataProvider="{CHART_TYPES}"></mx:ComboBox>

要完成定义 ComboBox 的工作,请添加以下属性:

<mx:ComboBox id="chartTypeDropDown" dataProvider="{CHART_TYPES}" 
editable="false" enabled="true" change="updateChart();"></mx:ComboBox>

change 属性告知应用程序在所选的 chartTypeDropDown 值更改时的操作。在我们的示例中,选择更改时将调用 updateChart 函数。您需要在 Script 下定义 updateChart 才能让 chartTypeDropDown 工作,如清单 3 中所示。

清单 3. 定义 updateChart(来自 FlexKPIHistorySample.mxml 的代码片段)
<mx:Script>
   <![CDATA[
   [Bindable] privatevar CHART_TYPES:Array = 
				[{label:"Line Chart",data:"Line Chart"},
				 {label:"Area Chart",data:"Area Chart"}, 
				 {label:"Plot Chart",data:"Plot Chart"}];
   [Bindable] privatevar chartTypeSelection:String = "Line Chart"; 
			
    privatefunction updateChart():void{
	  chartTypeSelection = new String(chartTypeDropDown.value);	
					
	  if(chartTypeSelection=="Line Chart")
			addLineSeries();	
	  elseif(chartTypeSelection=="Area Chart")
			addAreaSeries();  
	  else 
			addPlotSeries();  
	}
   ]]>
</mx:Script>

首先,updateChartchartTypeDropDown 选择值保存在全局变量 chartTypeSelection 中。然后,将根据 chartTypeDropDown 选择值调用对应的函数,以添加两个图表的数据级数。

有关 ComboBox 使用的更多信息,请参见参考资料

创建 KPI History 数据服务和构建 URL

存储在服务器上的 KPI 历史记录可以使用 Monitor 代表性状态传输(Representational State Transfer,REST)服务进行访问。在我们的示例中,我们将使用 Month-to-Date Amount of Completed Loans KPI。

KPI History 服务需要模型 ID、模型版本和 KPI ID 来构建 URL。在此示例中,我们将使用 Better Lender Showcase Model。其模型 ID 为 MortgageLendingBAMShowcase,模型版本为 20080918060000,KPI ID 为 Monthly_Total_of_Completed_Loan_Dollars

History 服务支持在检索历史记录值时使用各种时间范围。可以使用变化区间、固定区间或当前区间检索历史记录,还可以使用上次使用的期间筛选器进行检索。对于此示例,我们将使用一年的变化区间检索历史记录。在服务器上,使用 rollingPeriod 引用变化区间。使用了以下参数构造筛选器:

  • timerangemethod = rollingPeriod
  • rollingperiodduration = years
  • rollingperiodquantity = 1

可以使用查询参数在 URL 上传递其他参数。例如,History 服务支持通过传入地区和时区进行本地化。我们将这些值分别硬编码为 enAmerica/New_York。您可以在 WebSphere Business Monitor 信息中心找到受支持的完整参数列表(请参见参考资料)。

使用 Flex 访问 REST 服务

构造 URL 之后,Flex 可提供各种方式进行请求。对于我们的示例,我们将使用 URLLoader 类。URLLoader 能排除一系列事件。我们将使用 Event.COMPLETEIOErrorEvent.IO_ERROR 事件来确定请求是成功还是失败。清单 4 显示了如何使用 URLLoader 构建 REST URL 和创建请求。您可以调用 getKpiHistoryByIdRollingTimePeriod,以请求粒度为每天的数据,如清单 5 中所示。

已完成的示例的 KpiHistoryService 的 Action Script 源代码可以在解压缩 flexSampleFiles.zip 的 FlexSource 目录的 KpiHistoryService.as 中找到。

清单 4. 构建 REST URL(摘自 KpiHistoryService.as 的代码片段)
private const HISTORY_URL: String = 
 "/bpm/monitor/models/#/versions/##/kpis/history/###";

public function getKpiHistoryByIdRollingTimePeriod(kpiId:String, granularity:String, 
   rollingPeriodDuration:String, rollingPeriodQuantity:int):void{
getKpiHistoryById(kpiId, KpiHistoryDataModel.rollingTimeRangeMethod, 
         granularity, rollingPeriodDuration, rollingPeriodQuantity);
}

public function getKpiHistoryById(kpiId:String, timerangemethod:String = null, 
 granularity:String = null, rollingPeriodDuration:String = null, 
   rollingPeriodQuantity:int = -1):void{

      // Setup events
      loader.addEventListener(Event.COMPLETE, historyLoadComplete);
      loader.addEventListener(IOErrorEvent.IO_ERROR, historyLoadFailure);
           
// Build the url
      var modelURL:String = HISTORY_URL.replace('#', _model);
      var modelVersionURL:String = modelURL.replace('##', _version);
      var modelVersionKpiURL:String = modelVersionURL.replace('###', kpiId);

      // Add query params
      var queryString:String = "?locale=" + _locale + "&timezone=" + _timezone;

      // Setup the rolling params for rest, will vary with different time range methods
if(timerangemethod != null && timerangemethod == 
         KpiHistoryDataModel.rollingTimeRangeMethod){
         queryString = queryString + "&timerangemethod=" + timerangemethod + 
         "&granularity=" + granularity + "&rollingperiodduration=" + 
             rollingPeriodDuration + "&rollingperiodquantity=" + rollingPeriodQuantity;
      }

 var request:URLRequest = new URLRequest(_restHost +
         modelVersionKpiURL + queryString);
      loader.load(request);
}
清单 5. 请求粒度为每天的数据(摘自 FlexKPIHistorySample.mxml 的代码片段)
_kpiHistoryService.getKpiHistoryByIdRollingTimePeriod(
 "Monthly_Total_of_Completed_Loan_Dollars", KpiHistoryDataModel.granularityDaily, 
   KpiHistoryDataModel.rollingPeriodDurationYearly, 1);

历史记录请求中使用的 URL 将与以下所示类似:
<hostname>/rest/bpm/monitor/models/MortgageLendingBAMShowcase/versions/20080918060000
/kpis/history/Monthly_Total_of_Completed_Loan_Dollars?locale=en&timezone=America/New_York&timerangemethod
=rollingPeriod&granularity=daily&rollingperiodduration=years&rollingperiodquantity=1

定义错误处理

对于网络错误,将调用错误处理程序 historyLoadFailure,以便相应地处理错误。由于模型访问或错误 URL 而产生的未授权 URL 可能会导致网络错误。对于成功 REST 请求,将调用 historyLoadComplete。必须在 historyLoadComplete 中进行一项额外的检查,因为可能返回了请求,但其中可能包括来自 REST 服务的错误。可能会因为各种原因产生错误。开发环境中最常见的原因是,缺少参数或出现不能识别的参数。在生产环境中,KPI 被删除或历史记录不存在的情况更为常见。如果检测到错误,我们使用 setKpiHistory 将返回数据设置为数据模型,并发出完整事件。调用方应该在 kpiHistoryService 上设置完整事件的侦听器,从而在调用 getKpiHistoryByIdRollingTimePeriod 之前建立一个侦听器来处理成功获取数据的操作。KPI 历史记录请求是异步的;可以在验证数据并完成错误处理后发出事件。清单 6 显示了如何指定返回数据的错误检查和发出事件。

清单 6. 检查错误和发出事件(摘自 KpiHistoryService.as 的代码片段)
private function historyLoadComplete(e:Event): void {
   // Reached this point with no network errors, could still be REST errors
   removeEventListeners()
   var jsonObject:Object = decodeJSONObject(e.target.data);
   var error:Object = getError(jsonObject);
   if(error != null){
      // Error received from the REST server
      trace("Rest error detected: " + error["formattedMessage"]);
   } else {
      // No errors from the server and no networks errors
      trace("No rest errors detected");
      KpiHistoryDataModel.getInstance().setKpiHistory(jsonObject["KPI ID"], jsonObject);
      dispatchEvent(new Event(Event.COMPLETE));
   }
}

在 KPI 数据模型中存储数据

成功的 REST 请求之后,您需要存储数据,以便访问。从 REST 返回的数据是序列化的 JavaScript Object Notification (JSON)。这个格式可以使用 ascorelib 库中的实用程序转换为 JSON 对象。对于此示例,我们将使用对象存储每个 KPI 的最新请求。这里假设每个模型和版本都存在相应的配置。在这种情况下,每个 KPI 都具有唯一的标识符,可以作为访问历史记录数据的键使用。

KPI 数据模型包含用于访问 KPI 服务的实用常量。例如,数据模型中有一个有效的 timerangemethod。数据模型还具有访问数据的 setter 和 getter。清单 7 显示了一些常量和 setter 方法。

已完成的示例的 KpiHistoryDataModel 的 Action Script 源代码可以在解压缩 flexSampleFiles.zip 的 FlexSource 目录的 KpiHistoryDataModel.as 中找到。

清单 7. 数据模型常量和 setter 方法(摘自 KpiHistoryDataModel.as 的代码片段)
private var _history:Object = new Object();

public static const 
 rollingTimeRangeMethod:String="rollingPeriod";

public function setKpiHistory(kpiId:String, 
   historyDetails:Object):void{
      history[kpiId] = historyDetails;
}

加载图表数据

要加载图表数据,请按照清单 8 中所示使用 _kpiHistoryServiceKpiHistoryDataModel。服务在 init() 函数中创建。首先,添加事件侦听器,以在下一个服务事件完成时调用 loadChart() 函数。然后确保第一个历史记录服务请求持续时间为一年的期间内粒度为每天的数据。完成此请求后,将调用 loadChart() 函数,并删除当前事件侦听器。接下来,我们将从模型获得历史记录数据,并设置 mxml 中为标签文本 kpiNameLineChart dataProvider kpiValue 定义的变量。然后,我们将再次启动整个过程,以创建粒度为每周的第二个图表。

清单 8. 加载图表数据(摘自 FlexKPIHistorySample.mxml 的代码片段)
public function init():void {
   _kpiHistoryService = new KpiHistoryService(host, modelId, version, locale, timezone)

   // Make request for daily granularity
   _kpiHistoryService.addEventListener(Event.COMPLETE, loadChart);
   _kpiHistoryService.getKpiHistoryByIdRollingTimePeriod(
      "Monthly_Total_of_Completed_Loan_Dollars",
      KpiHistoryDataModel.granularityDaily,
      KpiHistoryDataModel.rollingPeriodDurationYearly, 1);
}

private function loadChart(e:Event):void{
   _kpiHistoryService.removeEventListener(Event.COMPLETE, loadChart);

   historyData = KpiHistoryDataModel.getInstance().getKpiHistoryById(
      "Monthly_Total_of_Completed_Loan_Dollars");
   kpiName = historyData["KPI Display Name"];
   kpiValue = historyData["KPI Value Array"];

   // Make request for weekly granularity
   _kpiHistoryService.addEventListener(Event.COMPLETE, loadChart2);
   _kpiHistoryService.getKpiHistoryByIdRollingTimePeriod(
      "Monthly_Total_of_Completed_Loan_Dollars",
      KpiHistoryDataModel.granularityWeekly,
      KpiHistoryDataModel.rollingPeriodDurationYearly, 1);
}

private function loadChart2(e:Event):void{
   _kpiHistoryService.removeEventListener(Event.COMPLETE, loadChart2);
   historyData2 = kpiHistoryDataModel.getInstance().getKpiHistoryById(
      "Monthly_Total_of_Completed_Loan_Dollars");
   kpiValue2 = historyData2["KPI Value Array"];
}

将级数类型添加到图表

调用 updateChart() 函数时,将添加清单 9 中所示的三个级数添加函数中的一个。正如示例中所示,Flex 允许向图表中添加不同的级数类型。此示例允许用户在 LineSeries, AreaSeries 和 PlotSeries 之间切换级数类型。通过创建新 Series 对象,在该对象上设置 IDxFieldyFielddisplayName 属性,然后将 Series 添加到图表的当前级数,您可以使用清单 9 中所示的 addLinesSeries() 函数创建级数。ID 与 mxml 的 mx:LineChart 中的 ID 对应。xFieldyFieldkpiValue dataProvider 数组中的键对应。

清单 9. AddSeries 函数(摘自 FlexKPIHistorySample.mxml 的代码片段)
private function updateChart():void{
   chartTypeSelection = new String(chartTypeDropDown.value);

   if(chartTypeSelection=="Line Chart")
      addLineSeries();	
   else if(chartTypeSelection=="Area Chart")
      addAreaSeries();
   else 
      addPlotSeries();
}

private function addLineSeries():void {
   var currentSeries_d:Array = dailyGranularityChart.series;
   if(currentSeries_d.length>0)
      currentSeries_d.pop();
   var series_d:LineSeries = new LineSeries;
   series_d.id = "dailyValueLine";
   series_d.xField = "KPI Period Timestamp";
   series_d.yField = "KPI Value";
   series_d.displayName = "Daily Kpi History Value";
   currentSeries_d.push(series_d);

   dailyGranularityChart.series = currentSeries_d;

   var currentSeries_w:Array = weeklyGranularityChart.series;
   if(currentSeries_w.length>0)
      currentSeries_w.pop();
   var series_w:LineSeries = new LineSeries;
   series_w.id = "weeklyValueLine";
   series_w.xField = "KPI Period Timestamp";
   series_w.yField = "KPI Value";
   series_w.displayName = "Weekly Kpi History Value";
   currentSeries_w.push(series_w);

   weeklyGranularityChart.series = currentSeries_w;
}

在运行时加载主题

您可以方便地将业务空间独特的外观应用到应用程序。BSpace_Skin 主题将覆盖大部分缺省 Flex 样式。Flex 提供了多种应用样式的方法。对于此示例,我们将通过编译我们的外部样式表 BSpace_Skin.css 将主题打包到 SWF 文件中。要向示例应用此主题,请使用 StyleManager 类在运行时加载 BSpace_Skin.swf,如清单 10 中所示。loadStyleDeclarations() 方法需要在第一个参数中提供 SWF 文件的路径。对于此示例,我们硬编码了 EAR 文件的上下文根。或者,您可以使用 flexKPIHistorySample.js 的 onview() 函数的 flashVars 参数将此信息传递到 Flex 中。然后在 FlexKPIHistorySample.mxml init() 函数中,可以使用 Application.application.parameters 读取此变量。因为样式可以立即更新,您要将 loadStyleDeclarations 的第二个参数设置为 true

清单 10. 应用 BSpace_skin 主题(摘自 FlexKPIHistorySample.mxml 的代码片段)
<mx:Script><![CDATA[

   private static const contextRoot:String="flexKPIHistorySample";

   public function init():void {
      StyleManager.loadStyleDeclarations("/"+contextRoot+
         "/widgets/samples/flexKPIHistorySample/BSpace_Skin.swf", true); 
   }
]]></mx:Script>

关于开发 Flex 小部件的提示

此部分包含关于开发 Flex 小部件的一些提示和实践建议。

从 Flex 在 Dojo 小部件中调用函数

您将会发现需要从 Flex 代码中的 Dojo 小部件内调用函数。这很简单!在您的 Flex 代码中,按照清单 11 所示使用 ExternalInterface.call 函数。将 window.invokeWidget 函数(清单 12)复制并粘贴到一个加载 Flex 应用程序时肯定会加载到页面上的 JavaScript 文件中。

在您的 Flex 代码中,使用 ExternalInterface.call 函数:

清单 11. ExternalInterface.call 函数
 // params is optional
ExternalInterface.call("invokeWidget", this.widgetId, "yourWidgetFunctionName", params);
  • “invokeWidget”是清单 12 中提供的函数的名称。
  • this.widgetId 是您的 Dojo 小部件的唯一 ID。可以在创建 Flex 应用程序时使用 flashVars 属性将此 ID 传入您的 Flex 应用程序。
  • “yourWidgetFunctionName”是希望调用的 Dojo 小部件中的函数的名称。
  • params。如果您传递参数(并非必需),这些参数需要位于对象中,例如:
    var params:Object=new Object();
    params["param1"]=param1Value;
    params["param2"]=param2Value;

清单 12 中的函数需要在加载 Flex 应用程序的页面上可用。它只是 .js 文件中的函数。确保在窗口级别使用“window”对其定义,否则将无法在 Internet Explorer 上工作。如果您将函数“invokeWidget”重命名为了别的名称,请确保在 ExternalInterface.call 函数中使用这个新名称,第一个参数就是该函数的名称。

清单 12. invokeWidget 函数
window.invokeWidget=function(widgetId, fnName, params) {
	// summary:
	//  Invoke a function on a widget
	//
	// description:
	//  This is a generic function that is being defined at the window
	//  level to allow Flex and other plug-ins a way to invoke functions
	//  defined on our widgets.
	var result = undefined;
	var widget = dijit.byId(widgetId);
	if (widget) {
		var fn = widget[fnName];
		if (fn && dojo.isFunction(fn)) {
			result = fn.call(widget, params);
		}
	}
	return result;
}

从 Dojo 小部件函数调用 Flex

您可能会发现需要从 Dojo 小部件中调用 Flex 代码。为此,您必须使用 ExternalInterface.addCallback 方法告知 Flex 将函数注册为可调用:

在 Flex 中:

清单 13. 在 Flex 中将函数注册为可调用
// to keep it simple, both args are the same string          
ExternalInterface.addCallback("flexFunctionName", flexFunctionName);

在 Dojo 中:

清单 14. 从 Dojo 小部件调用 Flex 代码
myDojoWidgetFunction: function(){
     // Note that swfId is the id attribute of the OBJECT tag and the name attribute 
     // of the EMBED tag that loaded your Flex application.
        var swfId=yourFlexAppId;
        myObj=new Object();
        myObj["var1"]="myVar1";
        myObj["var2"]="myVar2"
      // Call your Flex app here!  Note that passing arguments is optional, but if you 
      // do pass args the signature of the function in Flex must match what you call.
        if (dojo.isIE) {
            console.log(" is IE");
            window[swfId].flexFunctionName(myObj);
        } else {
            console.log(" is NOT IE");
            document[swfId].flexFunctionName(myObj);
        }
    }

编码 flashVars 属性

根据 Adobe,您必须按照清单 15 中所示的示例对 flashVars 属性值进行编码。

清单 15. 编码 flashVars 属性
        var flashVars = 'flashVar1=' + encodeURI(yourArg1) +
            '&flashVar2=' + encodeURI(yourArg2) + ............

将您的小部件附加到新节点

请确保将您的小部件附加到新节点;不要直接将其附加到 Dojo HTML 中的 dojoattachpoint 或 iWidget XML 文件中的 div 元素。销毁 Dojo 小部件时,其根节点也会被销毁。通过向 dojoattachpoint 或 iWidget 的 div 元素追加新节点,并使用此新节点作为小部件的根节点,将能确保您的 dojoattachpoint 或 div 不会销毁,而且可以使用相同的 dojoattachpoint 或 div 重新创建小部件。在清单 16 的示例中,viewAttach 是 iWidget XML 文件中的 div 元素的 ID。

清单 16. viewAttach div 元素
<!-- View mode markup -->
    <iw:content mode="view">
	<![CDATA[
	<div id="viewAttach" class="yourThemeClassNames"></div>
		]]>
    </iw:content>

在此代码中,为了将您的小部件附加到页面,您应该首先创建一个 div 元素,将其附加到您模板或 iWidget 文件中的 div 元素,并将新 div 作为小部件的根节点传递。

清单 17. 将小部件附加到页面
       var viewAttach = this.getElementById('viewAttach');
       var div = document.createElement('div');
       div.id = this.widgetId;
        viewAttach.appendChild(div);
		
        this.viewWidget = new my.widget.package.MyViewWidget(params, div);

总结

通过本文学习的知识,您将能够为 Business Space 部署、开发和注册自己的基于 Flex 的自定义小部件。您的业务客户将能够方便地从 Business Space 小部件菜单将您的新小部件拖放到每天用于监视业务流程的页面上。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=407775
ArticleTitle=创建基于 Flex 的小部件以在 Business Space 中显示 WebSphere Business Monitor 数据
publish-date=07162009