内容


使用 IBM Operational Decision Manager 管理业务规则应用程序中的引用数据的策略

Comments

概述

所有业务规则应用程序都在使用引用数据,简言之,引用数据就是一个值列表,但它可以包含代码、值、类型、子类型、有效期等。代码元素用在规则的条件或操作部分。当使用 IBM Operational Decision Manager (ODM) 时,引用数据集成必须在编写组件中完成,也可以在运行时完成。完成此集成是设计和实现期间的一个重要事项。在本文中,您将学习在使用 ODM 时,规则编写和和执行过程中用于引用数据管理的一些最常用策略。

本文中提供的重要的技术设计和实现考虑因素基于 IBM ODM V8,但它们也适用于 WebSphere® ILOG JRules V7.x。本文中提供的方法与产品版本无关。我们假设读者已经对基本的 ODM 概念有很好的理解。

业务规则应用程序中使用的引用数据通常是单一值列表的形式,比如产品类型、营销类别、地址类型、医疗程序代码、调整代码等的列表。这些列表是可枚举的。有时,引用数据是值、描述和有效期的组合。例如,位置列表、美国的州列表、地理区域和错误代码可能适合以下格式:

  • 代码
  • 描述
  • 生效日期
  • 过期日期

大多数值列表都是静态的,不会不断变化。但是,一些列表确实会发生变化,甚至被认为很容易变化。一些列表的有效性基于时间戳。这些列表可能需要更复杂的结构。管理业务规则应用程序中的引用数据的需求列表可能很长,包含许多项,比如:

  • 如何和在何处持久化数据
  • 规则中的使用模式是什么
  • 是否存在与定义值列表有关联的任何业务逻辑
  • 数据更新策略是什么
  • 所有者是谁
  • 开发和维护这些值有何成本

所有这些限制都必须同时在规则执行和规则编写层面上进行评估和设计。没有一种万能方法来解决 BRMS 中的引用数据集成。本文将介绍每种不同的解决方案。

规则处理中的引用数据用例

在规则编写环境中,可使用引用数据控制规则作者可以使用的可能值的列表。该列表是规则词汇表的一部分,被定义为域值。图 1 演示了一个有关开支类型的条件语句。因为开支类型不是强类型的,所以用户可输入任何字符串值。

图 1. 松散类型的属性 - 没有域值
松散类型的属性 - 没有域值
松散类型的属性 - 没有域值

图 2 显示了具有一组受控的可能值的开支类型:Hotel、Airfare、Meal 或 Taxi。

图 2. 强类型的属性 - 域值集
强类型的属性 - 域值集
强类型的属性 - 域值集

在强类型属性中,用户受到所提供的选择的限制。这样的值列表有不同的需求和不同的使用场景,包括:

  • 简单挑选列表,比如州列表、产品类型列表、开支列表
  • 简单但较长的挑选列表,可能需要分层导航或排序、过滤机制(比如邮政编码、医疗程序代码、……)
  • 名称和值的组合,名称仅在规则内显示,但值与规则执行紧密相关,比如错误代码值在业务对象中设置,而描述用在规则中。
  • 同一组引用数据用在其他组件中,可能需要与业务逻辑分开维护。
  • 由业务用户维护,最好集成在同一个编写环境中。
  • 需要实时更新,以支持高频率的更新,解决特殊的环境设置,比如支持本地化。
  • 直接从运行时访问,以应对高性能限制。

支持引用数据管理的环境

可使用三种不同的环境在业务规则应用程序上下文中管理引用数据。第一种环境是规则编写环境,在这种环境中,定义规则词汇表的规则开发人员可以使用静态域、动态域和自定义的值编辑器。第二种环境是用来保存值列表的数据源。它可以包含数据库表和外部文件,比如 XML 文档、表列式工作表、逗号分隔的变量文件等。最后一种环境支持在规则处理运行时内公开引用数据。考虑到缓存技术、访问协议、数据可用性、刷新机制、数据大小、业务需求和使用模式等各种因素,可能需要使用不同的集成方法。在许多业务规则应用程序或决策服务实现中,所有这三种环境都可使用。我们将会详细看看每种环境。

规则编写方法

在规则编写环境(例如 Rule Designer 或 Decision Center)中,规则作者选择一个值作为值列表的一部分,以便完成规则语言中的条件或操作。引用数据或挑选列表在 IBM ODM 中被定义为域:

静态域
值列表是在业务对象模型 (BOM) 内定义的。只要需要执行更改,就需要使用 Rule Designer 调整 XOM/BOM。在很少更新时,适合使用静态域。
动态域
值列表被定义为一个 BOM 域值,但数据源是外部的。BOM 域可由规则作者在设计时在 Decision Center 或 Rule Designer 内更新。在经常执行更改且 BOM 很容易更改时,适合采用这种方法。不需要更改 XOM,因为属性始终处于某种原始类型,比如 String、int 等。
值编辑器
该编辑器是为了 BOM 属性而定义。当规则作者单击某个词汇表标志时,编辑器会访问内存中的值列表。此访问可直接从数据源或使用 Decision Center 或 Rule Designer JVM 中的缓存完成。对数据源执行的所有更改都会立即在规则词汇表中反映出来。在引用数据的改动很频繁时,适合使用这个选项。在图 3 中,为了促销产品而定义了一个值编辑器。
图 3. BOM 元素的值编辑器
BOM 元素的值编辑器
BOM 元素的值编辑器

无论是动态域还是值编辑器方法,都需要一个外部数据源来管理引用数据。表 1 总结了每种引用数据管理方法的优缺点。

表 1. 不同引用数据支持方法的对比
静态域动态域值编辑器
可重用性减号在 BOM 内部维护,无法在外部应用程序中重用。加号在 BOM 内部维护,可访问远程数据源。引用数据可重用且在设计时与 BOM 同步。
无需更改 XOM。
加号用于在编写期间实时访问值。BOM 不持有任何值。可高效地重用。
无需更改 XOM。
实现工作加号工作量较少,仅限于更改 BOM。减号需要开发 Java 类来访问数据源。需要执行 JDBC 编码(不复杂)。一旦完成,刷新就非常容易。减号需要多种 Java 类和配置,包括 JDBC 和 UI 代码。
维护工作减号在 BOM 和 Rule Designer 内执行更改。减号在数据源中执行更改,以及使用同步功能在 BOM 中执行更改。加号仅在数据库中执行更改。
编写性能。加号不需要填充数据,在运行时或编写时不会造成性能影响。加号数据填充和刷新按需执行,不会造成性能问题。减号数据实时填充。数据访问和过滤可能增加性能开销。
可使用缓存技术或工具。
对部署和执行的影响加号数据包含在 BOM 中,对值的更改会强制部署 ruleApp。加号数据包含在 BOM 中,对值的更改会强制部署 ruleApp。减号数据未全部包含在 BOM 中。当域发生更改时,规则执行将会失败。

数据源方法

引用数据或值列表是可共享、可重用的组件。任何架构都应支持这类数据的集中定义和管理。主数据管理 (MDM) 产品支持这种集中管理。MDM 提供了从每个地方访问数据的服务。不使用 MDM 时,可使用数据库或外部属性文件来持久化数据,也可以利用 ODM 规则存储库。引用数据可在决策表中定义,而 BOM 使用了特殊的动态域提供程序(参阅 引用数据实现)。此方法的优点在于,无需额外的工作来维护独立的数据源和数据访问层。但是,Java® 值提供程序的实现更加复杂,而且使用了 ODM 产品 API。外部数据库表是跨多个应用程序实现引用数据可重用性的最常见方法。此数据源类型适用于动态域或自定义值编辑器方法。数据可使用 JDBC 与其他应用程序轻松共享,或者最好使用 SOAP over HTTP 或 RESTful 服务公开一个数据访问层。在大多数情况下,数据源方法需要的开发工作和维护控制都是最多的。

XML 文档或基于 Microsoft® Excel® 的工作表等外部文件常常用于临时引用数据管理。此选项既适用于动态域,也适用于自定义值编辑器方法。可使用常见的基于 Office® 的工具来管理该数据,不需要特定的用户界面,业务用户可轻松地更新值。但是,数据一致性是一项维护挑战,长期的可持续架构通常无法忍受这一点。

表 2 评估了不同的数据源选项。

表 2. 引用数据源选项的对比
独立的数据库表基于文件(尤其是 Excel 文件)ODM 内的决策表
可重用性加号容易更改数据。受控的集中管理,可由多个应用程序轻松重用减号版本管理是一项巨大的挑战,共享和治理也是加号容易更改数据,采用与业务规则相同的方式和在相同的位置维护数据。
实现工作减号数据库表定义与自定义 UI 相结合,共同维护表内容。加号没有实现工作,因为该操作受 ODM 特性支持。减号需要利用 ODM API 的具体的实现工作。
维护工作减号要帮助业务用户维护引用数据,必须开发 UI。加号没有维护成本。加号没有维护成本。

编写性能和执行部署不会受数据源类型影响:值列表被定义为一个 BOM 域,所以可以将它们部署为 ruleApp 的一部分。选择最佳引用数据方法的一个关键因素是考虑谁将执行维护,具体来讲,考虑维护人员是否是维护规则的同一组人员。在这种情况下,在与 Decision Center 相同的用户界面中定义数据会很有用。最后,解决方案必须跟得上数据和规则的更改速度:二者需要同步完成。

规则执行方法

当在规则或 BOM 属性内声明引用数据时,无需执行额外的集成,因为运行时的规则包含已翻译的值。以下代码段是一个 ILog 规则语言 (IRL) 示例,它展示了为某个字符串执行的一项测试,其中的字符串常量由一个 BOM 域翻译工具自动设置。

When {
….
evaluate (ReferenceDataManager.inAdjustmentCodes(line.adjustmentCode)
…);
} then { …

作为最佳实践,这样一个工具的实现需要将数据保存在本地。出于明显的性能原因,在一个规则的条件或操作部分中执行远程调用是不可行的。基本的方法是使用 XOM Java 对象中的数据缓存技术,在执行规则前准备好所有数据。如果有缓存,则需要评估缓存更新策略:

  • 启动服务器和应用程序
  • 通过会话 API、MBean、消息,使用 WebSphere eXtreme Scale 等产品根据需要进行更新
  • 通过后台进程或其他智能的机制自动执行更新

一种替代方法是使用 ODM BOM2XOM (B2X) 映射层。例如,要检查一个技能代码是否属于一个技能代码组,可使用一个 B2X 映射来定义该技能代码域,如图 4 所示。

图 4. 一个域值 B2X 映射示例
一个域值 B2X 映射示例
一个域值 B2X 映射示例

引用数据实现

在本节中,我们将重点介绍动态域和自定义值编辑器实现,因为它们是比较复杂的集成。我们将考虑以下需求:

  • 所有引用数据都应在一个集中的数据源中存储和维护。
  • 数据包括不同的值列表,每个列表具有不同的变更管理需求:从很少到非常频繁。
  • 尽管可使用一个通用的 BOM 项目来支持多个规则项目,但一些引用数据可能是个别规则项目所独有的,它们由一个特定的用户组来维护。
  • 引用数据需要支持本地化;具体来讲,规则编写环境中挑选列表内显示的描述需要本地化。
  • 一些引用数据由规则作者维护,支持与规则相同的部署模型。

动态域

在动态域中,值存储在一个外部数据源中,通过执行一段名为域值提供程序的、基于 Java 的数据访问代码来动态设置。动态域仅在一个方面是动态的,那就是您可动态地同步这个域与定义的数据源。同步之后,这个域会在 BOM 中变为静态的,如果数据源中发生任何更改,则需要一次新的更新。要在 ODM 中实现动态域,需要实现值提供程序接口 IlrBOMDomainValueProvider。图 5 给出了动态域机制。

图 5. ODM 中的动态域机制
ODM 中的动态域机制
ODM 中的动态域机制

ilog.rules.shared.bom.IlrBOMDomainValueProvider 实现类是作为 BOM 类的 domainValueProvider 自定义属性来引用的,如图 6 所示。

图 6. 引用值提供程序的实现
引用值提供程序的实现
引用值提供程序的实现

有趣的是,BOM 类可以是虚拟的并映射到一个 java.lang.String;无需提供一个 XOM 类。在触发对相关域的同步请求时,会识别值提供程序。实现类需要解决如何链接到外部数据源以及如何加载和缓存数据的问题,而且应实现供规则编辑器和翻译工具使用的回调方法,比如 getBOM2XOMMapping(String name)getDisplayText(…)

当部署在 Rule Designer 中时,代码需要封装为 Eclipse 插件。可通过导入一个名为 ilog.rules.studio.samples.bomdomainpopulate 的插件来获得 BOM 填充示例。

ODM 拥有一组预定义的特性来支持动态域,比如一个从 Excel 文件加载域数据的值提供程序。这个工作表包含一列值、一列标签和一列 BOM 到 XOM 的映射。

自定义值编辑器

在以下情况下应考虑自定义值编辑器:需要更新引用数据而不想触发按需手动更新,值列表很大且没有必要让 BOM 过载,或者为了改善适用性(例如排序和过滤功能),或者列表是一个可配置的挑选列表(也就是说,挑选列表基于选择条件(比如特定的用户配置文件或特定的语言环境)来动态填充)。自定义值编辑器的实现应遵循以下原则:

  • 建议采用一种通用设计来处理不同的列表类型,而不实现多个值编辑器。这些域的数据可能来自不同的数据源、表模式包含值和标签列、本地化、生效日期和过期日期。
  • 可设计常见的适用性支持(比如过滤)并与所有值编辑器相集成。
  • 使用外部配置文件来定义数据源连接属性和任何其他属性。
  • 评估使用纯 JDBC 代码访问数据的方式、Java 持久性 API (JPA) 实现或 Web 服务协议。
  • 明确地将对数据的访问与 ODM 提供的不同封装和集成模式分开:Decision Center 和 Rule Designer Eclipse 插件。

下图给出了两种环境中的值编辑器的不同组件:

图 7. 自定义值编辑器设计原则
自定义值编辑器设计原则
自定义值编辑器设计原则

ODM Decision Center

Decision Center 支持为值提供程序和值编辑器提供几乎相同的工具。如下图所示,可以重用为 Rule Designer 开发的相同的数据访问层和逻辑,但使用不同 API 的实现。

图 8. ODM Decision Center 中的值编辑器组件
ODM Decision Center 中的值编辑器组件
ODM Decision Center 中的值编辑器组件

ODM Decision Center(或 Rule Team Server)支持两种重要的扩展,您可利用它们在 Decision Center 中实现引用数据管理:您可在用户界面中添加一个自定义选项卡,可使用一个 API 更新动态域。在 ODM Decision Center 内管理引用数据的典型方法是:添加一组 JSP 来实现数据源中的值的读取、添加和更新。JSP 显示为一个选项卡扩展,teamserver.war 与这些页面重新封装在一起。

可以仅向特定的用户角色公开这样一个选项卡或功能。拥有 “rtsConfigurator” 角色的规则编写者能够访问新的 Reference Data Management 选项卡,如图 9 所示。

图 9. Reference Data Management 选项卡
Reference Data Management 选项卡
Reference Data Management 选项卡

此方法需要的基本组件是一个 BOM 定义(它支持为不同的 BOM 域使用不同的值提供程序引用),访问数据源的代码,提供了每个值列表的值、代码和 B2X 映射的代码,以及一组支持最终用户界面的 JSP。

图 10 给出了 ODM Decision Center 的基本组件视图,它使您能够在单个中央前端中管理引用数据和业务规则。

图 10. 包含 BOM 链接的自定义 UI
包含 BOM 链接的自定义 UI
包含 BOM 链接的自定义 UI

图 11 给出了一种可能的用户界面布局,其中提供了三个按钮来加载一个值列表,添加一个新值或编辑一个现有值。domain name 字段定义值列表的名称,其中 domain type 可指定域的基本原始类型,比如字符串或小数。DomainList 表包含域名称和类型的定义,引用用于保存其他值的表名。例如,表 DM_DS_EXP_TYPE 包含一个开支类型域的定义。

图 11. 基本 UI、表模式和值提供程序
基本 UI、表模式和值提供程序
基本 UI、表模式和值提供程序

用户可在屏幕底部输入新值。依据选择的类型,列数(Name 和 Value)可能有所不同。映射器组件将值保存在一个数据库表中。如果业务用户定义一个未在当前数据库中指定的新域,那么您可以提供一种动态结构来支持添加新域和保存它。Submit 按钮调用 Decision Center API 来更新相应 BOM 类的域值。

图 12 显示了一个更复杂的用户界面的示例,它支持多种不同的数据类型,由于这些类型的数据性质和可维护性需求,它们可能需要不同的变形。

图 12. Reference Data Management 选项卡设计示例
Reference Data Management 选项卡设计示例
Reference Data Management 选项卡设计示例

借助这组功能,应用数据管理可支持一组丰富的特性,比如域值更新和规则词汇表之间的全面自定义,有效期和本地化等自定义属性,控制数据访问的安全性,以及多租户(也就是每个租户的数据分组和结构)。如图 11 和图 12 所示,Decision Center 支持添加新选项卡,这可能包括子选项卡,每个选项卡负责管理一组引用数据。该实现可利用 JSF 管理的 bean 将用户界面组件与数据访问明确分开。数据访问对象集成在托管的 bean 中。图 13 中的类图演示了这样一种设计。

图 13. 引用数据选项卡的 JSF 管理的 bean 设计
引用数据选项卡的 JSF 管理的 bean 设计
引用数据选项卡的 JSF 管理的 bean 设计

规则执行考虑因素

规则执行过程中访问数据的最佳做法是,在执行规则之前准备好所有数据;也就是说,在执行时将所有数据传入 Decision Server 中。这使规则引擎能够以一种无状态方式运行,这种方式最适合。类似地,规则执行过程中的应用数据处理也必须遵循相同的原则。这里的讨论重点是,该规则将会检查某个属性是否属于一个值列表。ReferenceDataManager 类(如下所示)缓存值列表,为每种值类型提供一个静态搜索操作(比如 adjustment)。

evaluate 
(ReferenceDataManager.getInstance().inAdjustmentCodes(line.adjustmentReasonCode)

为了避免任何实时数据访问,规则执行所需的所有引用数据都可通过数据访问对象 (DAO) 获取并缓存在一个简单 Java Map 对象中的 Decision Service 中。值列表的加载是在执行规则之前完成的,它们在 ReferenceDataManager 类中集中管理,这遵循单例模式 (singleton pattern),其中相同的 Java 对象会由多个并发执行的规则共享(在同一个 JVM 中的多个规则引擎中运行)。

组合事件处理

这里面临的一个挑战是在修改数据源时更新缓存。最简单的解决方案是让决策服务实现在启动时加载数据,在数据更改时强制重新启动它。显然,这样做可能无法满足更频繁的更新和高可用性的需求;因为 ODM 包含一个事件运行时引擎和一个 Event Designer,所以可利用这些技术来定义以下内容:

  • 事件运行时中一个计划的事件
  • 一个支持 <code,value> 定义的业务对象
  • Web 服务集成,用于远程访问中央引用数据管理器
  • RES 中的一个本地服务,可提供更新缓存操作

图 14 给出了一个同时使用 Event Server 和 Rule Server 的方法。

图 14. 计划的引用数据访问和更新
计划的引用数据访问和更新
计划的引用数据访问和更新

图 15 中的序列图演示了计划的数据访问和更新的关键活动,其中包括一个计划内的触发器事件和关联的操作。该事件每天执行一次数据访问和更新(例如在晚上)的计划触发事件,关联的操作用于通过 Web 服务调用加载引用数据,更新在 Event Server 中使用业务对象实现的引用数据,然后在 RES 中调用 RefData Update 操作,这些操作使用一个静态单例对象内存储的 Java 对象来实现。

图 15. 计划的引用数据更新的序列图
计划的引用数据更新的序列图
计划的引用数据更新的序列图

一定要注意的是,需要为环境中所有物理规则执行服务器执行对 Ref Data Create/Update Web 服务的调用。这是因为该 Web 服务会处理 Java 对象缓存,该缓存需要可用于 Rule Server 的每个 JVM。在这种情况下,该方法必须确定如何执行多个调用,这些分开的调用之间是否需要任何同步。图 16 演示了生产环境中的 Event Server 和 Rule Server 之间的实际 Web 服务调用。

图 16. 生产环境中的引用数据更新
生产环境中的引用数据更新
生产环境中的引用数据更新

利用 WebSphere eXtreme Scale

一种备用的引用数据管理解决方案是,利用 WebSphere eXtreme Scale 来管理引用数据缓存。eXtreme Scale 提供了一个 <key,value> 映射格式的数据网格,用它来存储所有跨多个服务器的数据,这在使用多个决策服务来处理规则时很重要。eXtreme Scale 有多种使用模式,但在我们的情形中,我们考虑使用内联缓存模式,在该模式下,决策服务和编写环境会使用键来加载数据条目。这种内联缓存模式应该能够支持引用数据访问的大部分需求,提供扩展规则处理架构的强大功能。网格拓扑结构使用分布式缓存进行调整,其中存储在网格中的数据分散在所有 JVM 中。

eXtreme Scale API 的使用非常简单,它可集成在决策服务 Java 实现中,如图 17 所示。ObjectMap 是用于存储引用数据映射的主要类,它非常适合值列表等非分层模型。

图 17. eXtreme Scale 与决策服务的集成
eXtreme Scale 与决策服务的集成
eXtreme Scale 与决策服务的集成

数据加载可在与决策服务相同的 JVM 中完成,或者在另一个网格容器 (ObjectGrid) 中使用任何 JDBC 代码远程地完成。BackingMap 包含已存储在网格中的缓存对象。ObjectMapBackingMap 通过一个网格会话进行关联。引用数据管理器使用对象映射和会话来访问不同的引用数据映射。当初始化单例对象时,对代码的访问首先通过网格目录来完成,然后通过网格,最后通过一个会话来访问所有已部署的映射。这个单例类在 ODM XOM 中定义,方法 inAdjustmentCodes 已在 BOM 中详细描述,如下面的代码段所述。

public class ReferenceDataManager {
    // Each reference list of values is a map
   ObjectMap adjustmentCodes;

    private static ReferenceDataManager instance = new ReferenceDataManager();
    ClientClusterContext ccc;
    ObjectGrid grid;
    Session session;
	
    private ReferenceDataManager (){
	 // Connect to the Catalog Server.  
	try {
		ccc = ObjectGridManagerFactory.getObjectGridManager().connect
("cataloghostname:2809", null, null);
	// Retrieve the ObjectGrid client connection and return it.
	grid = ObjectGridManagerFactory.getObjectGridManager().getObjectGrid(ccc, 
"refdatagrid");
	session = grid.getSession();
        // Get the ObjectMap(s)
	adjustmentCodes = session.getMap("AdjustmentCodeMap");
	// Add more map if needed …
	}
.. 

   public ReferenceCode searchAdjustmentCodes(String code) {
	ReferenceCode rc = null;
	try {
		rc = (ReferenceCode)adjustmentCodes.get(code);
	} catch (ObjectGridException e) {
		e.printStackTrace();
	}
	return rc;
   }
	
   public boolean inAdjustmentCodes(String code) {
	return (searchAdjustmentCodes(code) !=null);
   }

上述代码仅是一个示例,不应视为生产用途的代码。可通过外部化不同的字符串参数,执行更有效的异常管理来改进它。

结束语

IBM Operational Decision Manager 提供了一组很好的特性,能将域值定义为规则词汇表的一部分(从静态枚举的域到动态域),还提供了丰富的值编辑器。这些域在 BOM 定义中定义或使用值编辑器定义,并在规则中进行测试。在某些情况下,值列表包含在一个外部数据源中,规则条件会在一个列表中查找某个值。这种模式需要在开发流程中尽早进行评估,因为可能需要使用复杂的缓存和缓存管理用例来支持它。引用数据管理始终是业务规则应用程序开发的一个要素,所以如果未在分析和设计规则集期间考虑它,那么规则的持续维护将受到影响。


相关主题


评论

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=930339
ArticleTitle=使用 IBM Operational Decision Manager 管理业务规则应用程序中的引用数据的策略
publish-date=05202013