级别: 初级 Amanda Watkinson (amanda.watkinson@uk.ibm.com), 软件工程师, IBM
2004 年 10 月 01 日 本文演示了如何从业务事件和系统事件中创建通用基础事件 (Common Base Event),Common Event Infrastructure 可以消费这两种事件,它是作为 IBM® WebSphere® Business Integration Server Foundation V5.1 中的技术预览发布的。
引言
IBM WebSphere Business Integration Server Foundation V5.1 包括 Common Event Infrastructure 技术预览版,它可以用来创建、存储和分布事件。其内部的通用基础事件提供了捕捉关于重要系统或业务事件信息的方法。例如:
- 重要的
系统事件可能会发生在特定服务器的性能降低到临界阈值以下的时候。
- 重要的
业务事件封装了针对特定业务的信息,例如,当一位重要的客户下订单时,您可能需要存储额外的信息或提示某人该事件已经发生。
虽然通用基础事件提供了特定的标准信息,但是编程 API 使得用户可以用针对他们自己业务需要的信息来填充事件。本文介绍了通用基础事件 (CBE),它是 Common Event Infrastructure (CEI) 服务的一部分,并演示了创建和填充事件来捕捉并关联系统行为和业务行为的不同方法。
Common Event Infrastructure 和 Common Base Event API
图 1 概括描述了 Common Event Infrastructure:
- 应用程序从 JNDI 获取 EventFactory 对象。该对象是通用基础事件的访问点,并为创建空事件提供了 API。
- 用数据填充空通用基础事件并将其传送给 CEI 服务器(通过发射器),事件可以持久存储在 CEI 服务器上或分发给消费者。
- 发射器是从绑定在 JNDI 中的 EmitterFactory 对象创建的。根据发射器如何过滤事件、如何处理事务以及他们的发送方式,可以将发射器配置为拥有不同的行为。(本文没有详细描述 EmitterFactory 和 CEI 服务器的行为和功能。只大致的描述了如何使 CBE 适合 CEI 服务。)
图 1.Common Event Infrastructure 概览
CEI 为创建事件提供了 Java 编程接口。接下来的部分说明了如何创建通用基础事件、用系统信息和业务信息填充该事件,还描述了一些用于创建应用程序和特定于业务的数据的 CBE 属性和方法。接下来的信息全部用来演示如何创建通用基础事件。
获取 EventFactory 对象
EventFactory 是通用基础事件的起始点。有三种不同的方法可以获取并利用 EventFactory 生成通用基础事件。下面是这些方法间的区别:
- 第一个方法描述了如何获取一个简单的 EventFactory 对象,而第二个和第三个方法描述的是如何用 ContentHandler 获取 EventFactory 对象,ContentHandler 对象提供了一个完成事件填充的方法,当用户显式调用 CBE 上的 complete() 方法时,调用该方法,或在将事件发送到 CEI 服务器之前通过发射器调用该方法。
- 第二个方法着眼于特定于 WebSphere 的 EventFactory,而第三个方法则显示了一个运行于 WebSphere 环境之外的应用程序是如何用 ContentHandler 来创建它自己的 EventFactory 的。
每种方法的信息如下所示:
-
获取一般的 EventFactory
这种 EventFactory 提供了用于产生通用基础事件及其相关属性的 API。清单 1 显示了如何获取这种 EventFactory 对象。EventFactory 被绑定到
com/ibm/events/EventFactory 下的 JNDI 中。
清单 1.
import com.ibm.events.cbe.*;
EventFactory eventFactory = (EventFactory)javax.rmi.PortableRemoteObject.narrow
(initialContext.lookup("com/ibm/events/EventFactory"), EventFactory.class);
|
-
获取特定于 WebSphere 的 EventFactory
除了与 ContentHandler 对象相关联以外,这种 EventFactory 和一般的 EventFactory 是相似的。当通用基础事件被发送给 CEI 服务时,它自动完成 SourceComponentId 属性,除非应用程序明确指定要覆盖该属性值。(有关 SourceComponentId 属性的详细信息,请参阅
填充通用基础事件。)但是,使用这种 EventFactory,SourceComponentId 字段是用特定于 WebSphere 环境的信息填充的。WebSphere EventFactory 对象被绑定到
com/ibm/websphere/events/factory 下的 JNDI 中。为了确保 SourceComponentId 始终被填充,这种 EventFactory 应该供运行在 WebSphere 服务器环境中的所有应用程序使用。
清单 2.
EventFactory eventFactory = (EventFactory)javax.rmi.PortableRemoteObject.narrow
(initialContext.lookup("com/ibm/websphere/events/factory"), EventFactory.class);
|
-
获取用户定制的 EventFactory
对于运行于 WebSphere 环境之外的应用程序,可以创建自定义 ContentHandler,并将其联系到 EventFactory。下面的代码样本显示了应用程序是如何生成 ContentHandler 对象的,并用 EventFactoryFactory 类生成 EventFactory。然后可以将这个 EventFactory 对象绑定到 JNDI 中,使得其它的应用程序可以访问它。(有关 JNDI 的详细信息请参阅
参考资料。)
清单 3.
/* Create a custom class which holds the implementation needed to populate the Common Base Event */
CustomContentHandler implements ContentHandler{
public CustomContentHandler(){}
public void completeEvent() {
// Add code to populate the event with desired values
}
}
/* Create a new CustomerContentHandler and associate it with an EventFactory */
ContentHandler myCustomContentHandler = new CustomContentHandler();
EventFactory eventFactory = EventFactoryFactory.createEventFactory(myCustomContentHandler);
/* Bind the EventFactory object into JNDI */
Context myContext = new InitialContext();
myContext.bind("eventFactory/myCustomEventFactory");
/* Obtain the EventFactory from JNDI to be used to generate Common Base Events */
EventFactory = (EventFactory)javax.rmi.PortableRemoteObject.narrow
(initialContext.lookup("eventFactory/myCustomEventFactory"), EventFactory.class);
|

 |

|
创建通用基础事件
EventFactory 对象提供了三种创建 CommonBaseEvent 对象的方法,如清单 4 所示:
清单 4.
CommonBaseEvent event = eventFactory.createCommonBaseEvent();
CommonBaseEvent event = eventFactory.createCommonBaseEvent
(java.lang.String extensionName);
CommonBaseEvent event = eventFactory.createCommonBaseEvent
(java.lang.String extensionName, long creationTime);
|
在通用基础事件被发射器发送到 CEI 服务器之前,必须要对其进行有效性验证,确保已经设置了所有必需的字段。表 1 列出了有效通用基础事件至少要包括的字段。
表 1.必需的 CBE 字段
|
字段名称
|
描述
| |
ExtensionName
|
这个字段可以放在 CBE 构造函数中,用来标识事件的类型。
| |
CreationTime
|
创建时间可以放在 CommonBaseEvent 构造函数中或者用 CBE 方法 setCreationTime(java.lang.String creationTimeValue), setCreationTimeAsLong(long creationTime) 显式声明。
| |
SituationType
|
有效的 SituationType 有:
AvailableSituation、ConfigureSituation、ConnectSituation、CreateSituation、DependancySituation、DestroySituation、FeatureSituation、OtherSituation、ReportSituation、RequestSituation、StartSituation、StopSituation 。
| |
SourceComponentId
|
这个字段表示 ComponentIdentification 类型。属性包括,例如,组件类型、位置、流程以及线程信息。
| |
Version
|
CBE 必需有一个有效的版本号码。这是自动创建的。
|
表 1 中列出的 SituationType 是用于描述事件发生时的状态的。例如,StartSituation 用于标识组件启动时的事件。EventFactory 有创建每种状态类型的帮助方法,然后在被传送到通用基础事件之前用附加信息填充。在每种 SituationType 中,可以指定 reasoningScope、situationQualifier 和 situationDisposition。(有效字段的详细描述请参阅 API 文档。)
通用基础事件实例显示了如何填充这些字段。
特定于 WebSphere 的 EventFactory 自动设置 CreationTime,并且如果没有指定的话,还自动创建 OtherSituation 的 SituationType 属性。另外,SourceComponentId 也是自动创建和填充的。因此,如果使用特定于 WebSphere 以外的 EventFactory,应用程序只需要指定这些字段即可。表 2 描述了特定于 WebSphere 的 ContentHandler 对象创建的 ComponentIdentification 值。
表 2.用 WebSphere ContentHandler 对象创建的 ComponentIdentification 值
|
ComponentIdentification 字段
|
特定于 WebSphere 的值
| |
componentIdType
|
固定值设为
ProductName 。
| |
component
|
WebSphere 平台标识符,例如:
Platform 5.0 [BASE 5.0.2 ptf2O0320.06] [ND 5.0.2[ptf2O0320.06] 。
| |
componentType
|
固定值设为
WebSphereApplicationServer 。
| |
subComponent
|
值可以为:
-
J2EE_Application (默认的)
-
WebAppServer_EJB_Container
-
Workflow_Engine
| |
locationType
|
固定值设为
Hostname 。
| |
location
|
服务器或服务器区的主机名。
| |
instanceId
|
值可以为:
-
cell.node.server
-
node.server
-
server
单元、节点和服务器与 WebSphere 单元名称、节点名称和服务器名称是相对应的。
| |
executionEnvironment
|
运行 WebSphere application server 的操作系统。该信息是从 Java 虚拟机 (Java Virtual Machine,JVM) 中提取出来的。
| |
processId
|
JVM 标识。
| |
threadId
|
最初创建 CBE 的线程标识。
|
填充通用基础事件
这一部分详细描述了在
创建通用基础事件部分中描述的字段,并说明了用数据填充通用基础事件的一些方法。对于通用基础事件中的大多数字段来说,添加数据的方法不只一种。下面列出了一些最常用的属性,要了解完整的字段和方法请参阅 API 文档。

 |

|
通用基础事件实例
这一部分集中了上面描述的信息来显示通用基础事件是如何创建的,以及如何被发送到 CEI 服务器的。图 2 和下面的代码样本演示了当提交新的 Web 订单时,如何创建两个事件,以及这些事件是如何说明如何将具体数据存储到通用基础事件内。第一个事件记录订单数据,第二个事件用于标识重要的客户。该实例用的是特定于 WebSphere 的 EventFactory。(结尾部分提供了一个
实例,显示了如果用一般的 EventFactory 将会是什么样子的。)
图 2.订单应用程序事件
- 从 JNDI 获取 EventFactory。
清单 13.
EventFactory eventFactory = (EventFactory)javax.rmi.PortableRemoteObject.narrow
(initialContext.lookup("com/ibm/websphere/events/factory"), EventFactory.class);
|
- 用
NewOrder 和
ImportantCustomer 的扩展名创建两个 common base event。
清单 14.
CommonBaseEvent newOrderEvent = EventFactory.createCommonBaseEvent("NewOrder");
CommonBaseEvent importantCustomer = EventFactory.createCommonBaseEvent("ImportantCustomer");
|
- 用作为一个有效的通用基础事件所需的必需字段填充每个事件。(本实例使用特定于 WebSphere 的 EventFactory,自动完成 SourceComponentId。)在这个实例中,我们重载了 Situation,并提供了我们自己的唯一的 GlobalInstanceId。
清单 15.
/* Set the rest of the required fields for globalInstanceId, and situation */
OtherSituation situation = eventFactory.createOtherSituation();
situation.setReasoningScope("EXTERNAL");
situation.setAny("Application Event");
newOrderEvent.setSituation(situation);
importantCustomer.setSituation(situation);
newOrder.setGlobalInstanceId("0348yufgfgdgvc");
importantCustomer.setGlobalInstanceID("vgnruisw74yd");
|
- 为新订单事件设置业务数据。
清单 16.
newOrderElement.addContextDataElementWithValue("string", "OrderEJB_J2EE", "order_number1");
ExtendedDataElement extendedDataElement =
newOrderEvent.addExtendedDataElement("OrderInformation");
extendedDataElement.addType(ExtendedDataElememt.TYPE_NO_VALUE);
extendedDataElement.addChildWithIntValue("OrderNo", 1);
extendedDataElement.addChildWithIntValue("Quantity", 1000);
extendedDataElement.addChildWithIntValue("OrderValue", 250000);
ExtendedDataElement extendedDataElement =
newOrderEvent.addExtendedDataElement("CustomerInformation");
extendedDataElement.addType(ExtendedDataElememt.TYPE_NO_VALUE);
extendedDataElement.addChildWithStringValue("CustomerName", "Fred Bloggs");
extendedDataElement.addChildWithStringValue("Address", "1 High Street, L1 1OH");
extendedDataElement.addChildWithStringValue("ImportantCustomer", "Y");
newOrderEvent.setPriority(70);
importantCustomer.setPriority(90);
|
- 获取发射器并将事件发送到 CEI 服务器。
清单 17.
EmitterFactory emitterFactory = (EmitterFactory)javax.rmi.PortableRemoteObject.narrow
(initialContext.lookup("com/ibm/events/configuration/emitter/Default"), EmitterFactory.class);
Emitter emitter = emitterFactory.getEmitter();
emitter.sendEvent(newOrderEvent);
emitter.sendEvent(importantCustomer);
|
上面的实例使用特定于 WebSphere 的 EventFactory,自动完成了 SourceComponentId 和 CreationTime 字段。下面的代码显示了如果使用一般的 EventFactory 这个信息是如何完成的:
清单 18.
/* Specify the CreationTime */
newOrderEvent.setCreationTime((new Date()).getTime());
importantCustomer.setCreationTime((new Date()).getTime());
/* Specify the ComponentIdentification */
ComponentIdentification componentID = eventFactory.createComponentIdenticiation();
componentID.setComponentIdType(ComponentIdentification.COMPONENT_ID_TYPE_PRODUCT_NAME);
componentID.setComponent("WebSphere 5.1");
componentID.setComponentType("WebSphereApplicationServer");
componentID.setSubComponent("OrderEJB");
componentID.setLocationType(ComponentIdentification.LOCATION_TYPE_HOSTNAME);
componentID.setLocation("Machine2");
componentID.setInstanceId("123");
componentID.setExecutionEnvironment("Windows 2000");
componentID.setProcessId("4657A3");
componentID.setThreadId("564");
/* Set the ComponentIdentification for each of the CBEs using the setSourceComponentId method */
newOrderEvent.setSourceComponentId(componentID);
importantCustomer.setSourceComponentId(ComponentID);
|
结束语
Common Event Infrastructure 技术预览版让我们知道了业务信息和系统信息是如何作为通用基础事件被捕捉、持久存储和分布的。虽然编程 API 需要填充特定的字段,但是 API 使用户能根据他们自己的业务需要来捕捉数据。这篇入门文章介绍了一些用来描述系统信息和业务信息的重要字段,并描述了获取和填充事件的不同方法。当 Common Event Infrastructure 作为产品发行时,这些概念将更加让人兴奋,使用户能够跨系统关联和集成信息。
参考资料
关于作者  | |  |
Amanda Watkinson 是英国温彻斯特市 IBM Hursley 实验室的一位软件工程师。Amanda 已经开发了大量的 WebSphere 项目,包括 Common Event Infrastructure 技术预览版的配置管理。
|
对本文的评价
|