对于查询关系中的角色,您可以选择业务对象,或将键属性指向静态映射中使用的属性,或者还可以选择要映射的简单类型值。建议采用后一种方法,因为此方法可提高关系的重用性。 例如,您可以在 Address 业务对象的 StateCode 查询关系中定义角色并让键属性指向 State字段,或者,可以直接对每个角色使用简单字符串类型。通过字符串类型,如果业务对象之间需要字符串类型的属性之间的州名称到州代码的映射,则可以在这些业务对象之间的任意映射中重用此关系。通过在角色中使用 Address 对象,可将关系限制为地址间的映射。我们的 StateCode 关系定义如图11 中所示。
创建查询关系需要进行一个额外的步骤,即预先填充实例数据。 图 11 显示了 StateCode 关系的实例数据窗口。实例按实例 ID 列出,您可以对其添加或删除。要指定值,请在实例中选择角色名称,并输入特定值。
图 11.StateCode 关系定义

将关系添加到转换
您可以在使用业务对象映射时向转换添加关系。
通过在源属性和目标属性之间绘制 Relationship Lookup 转换,即可应用查询关系。此转换类型是 Process ServerV6.1 中新推出的,仅能将其用于身份查询关系。要配置此转换,请在 details 窗格中选择关系名称、源对象和目标对象。图 12 显示了包含StateCode 关系的关系查询转换的映射定义。
图 12. 业务对象映射中的关系查询转换
创建查询关系需要进行一个额外的步骤,即预先填充实例数据。 图 11 显示了 StateCode 关系的实例数据窗口。实例按实例 ID 列出,您可以对其添加或删除。要指定值,请在实例中选择角色名称,并输入特定值。
图 11.StateCode 关系定义

将关系添加到转换
您可以在使用业务对象映射时向转换添加关系。
通过在源属性和目标属性之间绘制 Relationship Lookup 转换,即可应用查询关系。此转换类型是 Process ServerV6.1 中新推出的,仅能将其用于身份查询关系。要配置此转换,请在 details 窗格中选择关系名称、源对象和目标对象。图 12 显示了包含StateCode 关系的关系查询转换的映射定义。
图 12. 业务对象映射中的关系查询转换
在 Process Server 的早期版本中以及很多多对多查询中,都需要使用 Relationship Service API 来手动从自定义转换查询属性值。有关如何进行此操作的信息,请参见手动调用关系。 要在业务对象映射中应用动态关系,请在其标识符要相关的两个业务对象之间绘制一个 Relationship转换。使用关系的名称和特定于应用程序的角色配置转换。因为源或目标必须为通用业务对象,而且每个关系中只存在一个托管角色,因此不需要托管角色名称。图9 显示了使用 CustomerRelationship 的示例关系转换。
图 13. 业务对象映射中的关系转换

正如我们前面讨论的,动态关系并不独立工作,必须将其在端到端集成模式中使用。因此,调用动态关系的业务对象映射必须恰当地嵌入在围绕之前讨论的规则构建的上下文中。您可以按照图 14 中所示在 Process Server 中实现此模式。
图 14. Process Server 中的数据同步

业务对象映射 (
) 通过使用关系 (
) 执行数据转换,将从接口映射 (
) 进行调用,这些接口映射用于在应用程序特定的接口和通用接口之间进行传输 (
)。接口映射导入和导出的服务用于在应用程序及中央调度逻辑之间发送和接收业务对象。
图 13. 业务对象映射中的关系转换

正如我们前面讨论的,动态关系并不独立工作,必须将其在端到端集成模式中使用。因此,调用动态关系的业务对象映射必须恰当地嵌入在围绕之前讨论的规则构建的上下文中。您可以按照图 14 中所示在 Process Server 中实现此模式。
图 14. Process Server 中的数据同步

业务对象映射 (
) 通过使用关系 (
) 执行数据转换,将从接口映射 (
) 进行调用,这些接口映射用于在应用程序特定的接口和通用接口之间进行传输 (
)。接口映射导入和导出的服务用于在应用程序及中央调度逻辑之间发送和接收业务对象。
调度逻辑直接将业务对象发布到所有与更改相关的应用程序(在本例中只有一个应用程序)。 当接口映射调用业务对象映射时,将会传递 Relationship Service 所必需的信息,以确定其调用上下文。
提示:从 V6.1 开始,可以在中介流组件中使用业务对象映射和关系。因此,您还可以直接在 WebSphere Enterprise Service Bus 中通过将接口映射替换为中介流组件实现上述流。
此模式的另一个方面是,标记如何与业务对象关联来指示是否已创建、更新或删除了对象。Process Server使用业务图包装业务对象,业务图是与业务对象关联的额外元数据的容器。要生成业务图,请使用 IntegrationDeveloper;右键单击业务对象并选择 Create a Business Graph 即可。
业务图具有两个可用于表示标记的工具(请参见图 15):谓词和更改摘要。
谓词是指示要对对象图执行的操作的字符串,通常为 Create、Update 或 Delete。谓词为 Update,则要由图的接收方确定图中修改了哪些内容;该谓词应用到整个图。
更改摘要记录从开启后应用于图中对象和属性的所有更改。然后可以直接从更改摘要派生出图中任何对象或属性的标记。
图 15. 业务图中的谓词和更改摘要

动态关系所维护的业务对象必须始终包装在包含谓词或更改摘要信息的业务图中,以便 Relationships Service 可以确定采取什么操作。
手动调用关系
您还可以通过 Relationship Service API 在业务对象映射内外采用编程方式使用关系。其中主要的相关 API 元素有:
提示:从 V6.1 开始,可以在中介流组件中使用业务对象映射和关系。因此,您还可以直接在 WebSphere Enterprise Service Bus 中通过将接口映射替换为中介流组件实现上述流。
此模式的另一个方面是,标记如何与业务对象关联来指示是否已创建、更新或删除了对象。Process Server使用业务图包装业务对象,业务图是与业务对象关联的额外元数据的容器。要生成业务图,请使用 IntegrationDeveloper;右键单击业务对象并选择 Create a Business Graph 即可。
业务图具有两个可用于表示标记的工具(请参见图 15):谓词和更改摘要。
谓词是指示要对对象图执行的操作的字符串,通常为 Create、Update 或 Delete。谓词为 Update,则要由图的接收方确定图中修改了哪些内容;该谓词应用到整个图。
更改摘要记录从开启后应用于图中对象和属性的所有更改。然后可以直接从更改摘要派生出图中任何对象或属性的标记。
图 15. 业务图中的谓词和更改摘要

动态关系所维护的业务对象必须始终包装在包含谓词或更改摘要信息的业务图中,以便 Relationships Service 可以确定采取什么操作。
手动调用关系
您还可以通过 Relationship Service API 在业务对象映射内外采用编程方式使用关系。其中主要的相关 API 元素有:
[create|retrieve|deactivate|delete|exists]Participant创建、检索、禁用或删除参与者。参与者是给定实例中的角色的值,可以为简单值,也可以为业务对象。[exists|deactivate|delete]ParticipantByID 按实例ID(与按值操作的方式相对)检查参与者是否存在、禁用或删除。 addParticipantWithID将新参与者添加到给定实例(仅用于多对多关系) retrieveInstanceIDs 返回给定角色的参与者的 ID数组。对于身份关系,该数组最多只能包括一个实例 ID。 staticLookup 根据输入业务对象中的属性值在输出业务对象中查询属性值(6.1中新推出的功能)correlate 在动态关系中自动维护两个业务对象间的相关性(6.1 中新推出的;以前为 maintainIdentity)[get|set|unset][Relationship|Role]Property 将属性(如创建时间)与角色或关系实例关联 清单 1 显示了采用编程方式检索、添加和删除实例数据的代码示例。
清单 1. 使用关系实例数据的 CRUD API 元素
//locate the Relationship Service
RelationshipService relService = (RelationshipService)ServiceManager.INSTANCE.
locateService("com/ibm/wbiserver/rel/RelationshipService");
//The names of our relationship and its roles
String relati;
String roleName_full = "http://CRMLib/FullStateName";
String roleName_code = "http://CRMLib/StateCode";
//programmatically query a lookup relationship
String fullName = "California";
String code = null;
int[] ids =
relService.retrieveInstanceIDsByString(relationshipName, roleName_full, fullName);
if( ids.length > 0 ){
List codes = relService.retrieveParticipants(relationshipName, roleName_code, ids[0]);
if( !codes.isEmpty() )
code = (String)codes.get(0);
}
//add a new relationship instance
String newFullName = "Alabama";
String newCode = "AL";
int genId =
relService.addParticipantString(relationshipName, roleName_full, newFullName);
relService.addParticipantStringWithID(relationshipName, roleName_code, genId, newCode);
//remove relationship instance
relService.deleteParticipantString( relationshipName, roleName_full, newFullName);
relService.deleteParticipantString(relationshipName, roleName_code, newCode);
清单 1. 使用关系实例数据的 CRUD API 元素
//locate the Relationship Service
RelationshipService relService = (RelationshipService)ServiceManager.INSTANCE.
locateService("com/ibm/wbiserver/rel/RelationshipService");
//The names of our relationship and its roles
String relati;
String roleName_full = "http://CRMLib/FullStateName";
String roleName_code = "http://CRMLib/StateCode";
//programmatically query a lookup relationship
String fullName = "California";
String code = null;
int[] ids =
relService.retrieveInstanceIDsByString(relationshipName, roleName_full, fullName);
if( ids.length > 0 ){
List codes = relService.retrieveParticipants(relationshipName, roleName_code, ids[0]);
if( !codes.isEmpty() )
code = (String)codes.get(0);
}
//add a new relationship instance
String newFullName = "Alabama";
String newCode = "AL";
int genId =
relService.addParticipantString(relationshipName, roleName_full, newFullName);
relService.addParticipantStringWithID(relationshipName, roleName_code, genId, newCode);
//remove relationship instance
relService.deleteParticipantString( relationshipName, roleName_full, newFullName);
relService.deleteParticipantString(relationshipName, roleName_code, newCode);
清单 2 显示了如何以编程方式使用 staticLookup(V6.1 中新推出的)执行对 StateCode 关系的查询。 清单 2. 查询转换
//locate the Relationship and BOFactory Service
RelationshipService relService = (RelationshipService)ServiceManager.INSTANCE.
locateService("com/ibm/wbiserver/rel/RelationshipService");
BOFactory boFactory =
(BOFactory)ServiceManager.INSTANCE.locateService("com/ibm/websphere/bo/BOFactory");
//The names of our relationship and its roles
String relati;
String roleName_full = "http://CRMLib/FullStateName";
String roleName_code = "http://CRMLib/StateCode";
//name space and BO names
String tns_app1 = "http://CRMLib";
String addressName_app1 = "Address_App1";
String stateProp_app1 = "state";
String tns = "http://CRMLib";
String addressName = "Address";
String stateProp = "state";
//create input and output address with input state set
DataObject address_app1 = boFactory.create(tns_app1, addressName_app1);
address_app1.setString(stateProp_app1, "California");
DataObject address = boFactory.create(tns, addressName);
//Have the Relationship Service set the state code into the output
relService.staticLookup(relationshipName,
roleName_full,
address_app1,
new String[]{stateProp_app1},
roleName_code,
address,
new String[]{stateProp});
//locate the Relationship and BOFactory Service
RelationshipService relService = (RelationshipService)ServiceManager.INSTANCE.
locateService("com/ibm/wbiserver/rel/RelationshipService");
BOFactory boFactory =
(BOFactory)ServiceManager.INSTANCE.locateService("com/ibm/websphere/bo/BOFactory");
//The names of our relationship and its roles
String relati;
String roleName_full = "http://CRMLib/FullStateName";
String roleName_code = "http://CRMLib/StateCode";
//name space and BO names
String tns_app1 = "http://CRMLib";
String addressName_app1 = "Address_App1";
String stateProp_app1 = "state";
String tns = "http://CRMLib";
String addressName = "Address";
String stateProp = "state";
//create input and output address with input state set
DataObject address_app1 = boFactory.create(tns_app1, addressName_app1);
address_app1.setString(stateProp_app1, "California");
DataObject address = boFactory.create(tns, addressName);
//Have the Relationship Service set the state code into the output
relService.staticLookup(relationshipName,
roleName_full,
address_app1,
new String[]{stateProp_app1},
roleName_code,
address,
new String[]{stateProp});
要使用 correlate API 元素来维护动态关系,必须手动传递在其他情况下由接口映射提供的上下文信息。Process Server提供了如何进行此工作的关系示例项目。您可以在 Process Server 目录的 samples/lib/RelSample下找到该示例及其源代码。 如何管理关系?
Process Server 提供了用于管理关系的管理接口RelationshipManager,并集成到了管理控制台中。您可以在运行时使用此接口对查询关系和动态关系的关系示例进行查询和操作。RelationshipManager 将调用 Relationship Service 公开的 JMX API,您也可以使用此 API 来构建自己的自定义管理功能。
图 16. Relationship Manager

还可以在不必进行任何额外配置的情况下在网络部署(Network Deployment,ND)环境中使用关系。在 ND环境中,关系安装在应用程序集群中。关系在集群中具有可见性,集群中的所有服务器都可以访问存储在关系数据库中的实例数据。在 ND 环境中运行Relationship Service 的能力使其具有了可伸缩性,并具有高度的可用性。
为了在 ND 环境中管理关系,Relationship Manager 通过选择其关系 MBean 连接到集群中的服务器。因此,可以通过集中的管理接口跨不同的集群对关系进行管理。
可以在哪里找到关于关系的更多信息?
既然已经了解了关系背后的概念和思想,您可能会迫不及待地想尝试一下或深入了解其工作方式。以下是一些我们推荐的资源,除非特别说明,否则都会在参考资料部分列出。
针对 Process Server 的 IBM Education Assistant 模块讨论了更多的 Relationship Service 基础技术细节,并提供了一些有用的实验和演示。
之前关于关系的 developerWorks 系列文章 WebSphere Process Server Relationship Service 提供了一些基本的操作信息,其中包括从自定义代码调用查询关系的示例。
随 Process Server 提供的关系示例演示了如何使用相关 API 来以编程方式维护动态关系。此示例位于 Process Server 目录的 samples/lib/RelSample 下。
WebSphere Business Process Management 信息中心提供了关于创作和管理工具的丰富参考信息。
最后,请关注 developerWorks WebSphere 推出的后续教程,其中将详细介绍为本文所述示例用例创建端到端集成解决方案的步骤。
词汇表
业务对象是代表业务功能或元素(如客户或发票)的应用程序数据的容器。
业务图是围绕业务对象或业务对象的层次结构添加的包装,用于提供额外的功能。例如,您可以在业务图中提供与业务对象相关的更改摘要和事件摘要信息。
业务对象映射支持源业务对象和目标业务对象间的映射。它们是 WebSphere Process Server 中的支持服务组件,负责基于源业务对象中的值向目标业务对象分配值。
接口映射在接口映射编辑器中创建,用于解析和协调交互组件的接口间的差异。
结束语
本文说明了如何在复杂的集成解决方案中利用关系来提供交叉引用功能。我们重点讨论了 Process Server 所支持的两个关系模式,静态属性值的查询和动态身份相关。您现在应该具有了将关系投入使用,将其应用于您特定的解决方案的必要知识。
Process Server 提供了用于管理关系的管理接口RelationshipManager,并集成到了管理控制台中。您可以在运行时使用此接口对查询关系和动态关系的关系示例进行查询和操作。RelationshipManager 将调用 Relationship Service 公开的 JMX API,您也可以使用此 API 来构建自己的自定义管理功能。
图 16. Relationship Manager

还可以在不必进行任何额外配置的情况下在网络部署(Network Deployment,ND)环境中使用关系。在 ND环境中,关系安装在应用程序集群中。关系在集群中具有可见性,集群中的所有服务器都可以访问存储在关系数据库中的实例数据。在 ND 环境中运行Relationship Service 的能力使其具有了可伸缩性,并具有高度的可用性。
为了在 ND 环境中管理关系,Relationship Manager 通过选择其关系 MBean 连接到集群中的服务器。因此,可以通过集中的管理接口跨不同的集群对关系进行管理。
可以在哪里找到关于关系的更多信息?
既然已经了解了关系背后的概念和思想,您可能会迫不及待地想尝试一下或深入了解其工作方式。以下是一些我们推荐的资源,除非特别说明,否则都会在参考资料部分列出。
针对 Process Server 的 IBM Education Assistant 模块讨论了更多的 Relationship Service 基础技术细节,并提供了一些有用的实验和演示。
之前关于关系的 developerWorks 系列文章 WebSphere Process Server Relationship Service 提供了一些基本的操作信息,其中包括从自定义代码调用查询关系的示例。
随 Process Server 提供的关系示例演示了如何使用相关 API 来以编程方式维护动态关系。此示例位于 Process Server 目录的 samples/lib/RelSample 下。
WebSphere Business Process Management 信息中心提供了关于创作和管理工具的丰富参考信息。
最后,请关注 developerWorks WebSphere 推出的后续教程,其中将详细介绍为本文所述示例用例创建端到端集成解决方案的步骤。
词汇表
业务对象是代表业务功能或元素(如客户或发票)的应用程序数据的容器。
业务图是围绕业务对象或业务对象的层次结构添加的包装,用于提供额外的功能。例如,您可以在业务图中提供与业务对象相关的更改摘要和事件摘要信息。
业务对象映射支持源业务对象和目标业务对象间的映射。它们是 WebSphere Process Server 中的支持服务组件,负责基于源业务对象中的值向目标业务对象分配值。
接口映射在接口映射编辑器中创建,用于解析和协调交互组件的接口间的差异。
结束语
本文说明了如何在复杂的集成解决方案中利用关系来提供交叉引用功能。我们重点讨论了 Process Server 所支持的两个关系模式,静态属性值的查询和动态身份相关。您现在应该具有了将关系投入使用,将其应用于您特定的解决方案的必要知识。