|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
[推荐] SOA 最佳实践:BPEL 指南 |
回复
|
|
|
第 1 部分:面向服务的方法在业务规则开发中的运用 作者:Kevin Geminiuc
在 SOA 最佳实践:BPEL 指南的第一部分中,您将了解如何通过在开发和管理业务规则时使用面向服务的方法来降低维护成本并提高组织灵活性。
许多组织正从面向对象的业务流程管理范例转移到面向服务的方法;实际上,服务正在成为应用程序开发的基本元素。同时,业务流程执行语言 (BPEL) 已经成为编排这些服务和管理业务流程的无缺陷执行的事实标准。这些趋势所产生的结果是,为更灵活、更经济高效地管理业务流程提供了一些良机。 大多数业务流程(贷款审批就是一个典型示例)包含多个决策点。在这些决策点处,将对某个条件进行评估。业务流程根据这些标准或业务规则更改它们的行为。实际上,这些业务规则对业务流程起到了推动作用。这些规则通常嵌入到业务流程本身或自定义 Java 代码的内部,这将导致在将来的某个时候出现若干问题: 业务规则比业务本身更改得更频繁,而更改和管理嵌入的业务规则是一个复杂问题,并超出了大多数分析员的能力范围。因此,随着业务规则的更改,程序员通常要消耗大量时间来执行该任务。 大多数组织都缺少中央规则信息库。因此,策略中任何涉及到组织范围的更改都无法运用到所有业务流程中。 业务流程无法重用规则。因此,IT 人员最终要为每个流程设计规则,这通常导致不一致性或冗余。 避免这些问题的最佳方法是使用规则引擎将业务流程与业务规则分离。在该方法中,规则公开为服务,而 BPEL 流程在到达决策点时通过查询该引擎来利用这些服务。该方法更为灵活 - 可以通过图形方式操作规则,而不是在编程语言中或在流程内部对规则进行编码。业务用户可以使用工具自行编写规则,并且无需 IT 人员的协助即可进行部署后的规则更改。由于大多数更新和功能增强是由业务用户执行的,因此可以显著减少维护成本。 规则引擎和 BPEL 是两种互补技术。Oracle BPEL 流程管理器提供了高级工具来显示、设计和管理 BPEL 流程,而第三方规则引擎使复杂的业务逻辑可以用类似英语的语法表示,并由非程序员领域专家对其进行编辑。 在“BPEL 指南”的第一部分中,我将根据我所在团队的自身经验来提供分离流程和规则的最佳实践。并通过代码示例提供一种开发方法,更改将 BPEL 与规则引擎集成的管理策略。最后,我将介绍该体系结构如何在不同的层中正确划分逻辑。 分离规则与流程 将规则引擎集成到流程管理框架中要求事先进行一定量的投资。在尝试进行此集成之前,将规则与流程分开是很重要的。因此,系统体系结构方面的一个主要决策是如何实现业务策略、业务流程和支持业务逻辑。实际上,架构师必须交流或设计最佳实践,以便设计人员在设计系统功能时知道应在何处应用每个相关技术 - BPEL、业务规则、Java/Web 服务。 如图 1 所示,业务逻辑被分布到三个不同的 IT 基础架构层中:业务流程、Web 服务和规则。我们将对它们进行依次介绍。
图 1 体系结构:分离规则与流程 业务流程层。该层负责管理业务流程的总体执行。这些使用 BPEL 实现的业务流程可以是长期运行的业务流程、事务业务流程以及持久业务流程。流程逻辑支持分布到 Web 服务/EJB 调用中的高级事务(“sagas”)以及嵌套的子流程事务。BPEL 引擎支持对工作流进行审计和检测,因此比较适合于 将不易变化的工作流步骤与易变的业务规则分开 实现行业流程 实现需要补偿的流程 支持流程的大型实例化 设计需要审计的流程 协调异构技术,如连接器、Web 服务和支持 Web 服务调用框架 (WSIF) 的逻辑 Web 服务层。Web 服务层将现有的应用程序层功能公开为服务。这样,多个业务流程便可以重用这些服务,从而实现面向服务体系结构 (SOA) 的承诺。 Web 服务实现功能逻辑和域逻辑。功能方法通常是无状态和中等粒度的。例如,Web 服务可能包含系统数据的实用程序方法、实体操作和查询方法。可以使用多种技术实现 Web 服务并隐藏实现平台之间的差别。因此,该层比较适合于: 为特定实体/域领域实现中等粒度的方法 集成原有的代码/第三方工具 封装应用程序层中的逻辑、自定义代码和实现 规则层。规则引擎通常是复杂逻辑(涉及实体之间的一些相互依赖性以及与顺序相关的逻辑计算)的发源地。从业务流程中以单独实体的形式提取业务规则可更好地对系统进行分离,从而提高可维护性。 规则引擎可以对规则集进行并行和按顺序的评估。此外,规则能够对输入数据和中间数据的值进行评估并确定是否应引发规则。与传统的 Java 过程代码相比,该模块设计提供了一个更简单、可维护性更高的解决方案。 此外,正如我在前面指出的,规则具备声明特性,并使业务分析员能够进行高级 GUI 编辑。现代规则引擎的执行速度非常快,并提供了内置的审计记录。规则层的典型特性包括 包含耦合和复杂的逻辑 支持使用并行执行进行高效的业务逻辑评估 包含基于多个业务规则评估构建的复杂返回结构 允许将域逻辑转换为简单规则 实现高度易变的业务策略 由于规则在 Web 服务层中公开为服务,因此可以在所有企业间应用程序中重用,从而简化了新应用程序和集成的开发。 开发和维护 为演示开发过程,我将使用称作 Eligibility Process 的业务流程示例。该流程用于评估家庭是否有资格加入特定的医疗保健项目。根据家庭的属性(收入、子女总数),它将该家庭指定给 Healthcare Program 1 或 Healthcare Program 2。在分析阶段,根据易变性和复杂性将逻辑分为不同类别的存储桶。正如在前一部分中所介绍的,规则通常对复杂的返回结构(需要多个业务验证以及频繁更改或影响组织大部分的策略)进行建模。而部门或组织流程则在业务流程层中建模。 典型的开发流程包含三个步骤: 在规则集中创建规则 将规则集公开为 Web 服务 从 BPEL 中调用规则集 Web 服务 开发阶段需要专门的角色(如规则开发人员、流程开发人员、业务分析员和 Web 服务开发人员)才能完成这些任务(请参阅图 2)。
图 2 开发和维护角色 1. 在规则集中创建规则。 在开发的最初阶段,规则开发人员在集成的图形开发环境(如 ILOG 的 JRules 业务规则管理系统)中创建初始规则。(有关 Oracle Fusion 中间件中业务规则功能的信息,请参阅边条。) Oracle Fusion 中间件规则引擎 该示例演示了如何将 ILOG 的规则引擎与 Oracle BPEL 流程管理器集成在一起,但请注意,Oracle Fusion 中间件的未来版本将把一个新的本机业务规则引擎与 Oracle BPEL 流程管理器集成在一起。 使用 Oracle BPEL Designer 中的 Decision Service 向导,用户可以将业务规则集成到 BPEL 项目中。该向导将能够浏览 Oracle Business Rules(Oracle 业务规则)以及第三方规则引擎的信息库。此外,用户能够将 BPEL 变量映射为规则信息库中的事实、插入新的事实并执行规则。然后,BPEL 引擎将针对规则引擎事实自动执行从基于 XML 的变量到基于 Java 的数据类型的任何格式转换。 部署后,业务用户将能够访问与业务流程相关的规则并进行更改,而不必重新部署流程。该方法将显著简化 BPEL 流程与规则引擎的集成,并增强体系结构的灵活性。 创建规则前,应设置规则信息库和对象模型。通过规则信息库可以在业务规则的生命周期内维护和管理业务规则。业务规则操作的问题域通过 ILOG JRules 以业务对象模型 (BOM) 的格式表示。BOM 通过表示模型的可执行版本的 Java 类或 XML 模式表示。XML 模式可以帮助确保数据的灵活性。详细地实现对象模型通常是开发人员的任务。 开发人员创建对象模型和规则信息库后,您需要决定哪些规则可以由分析员维护,以及哪些规则要用低级语言 (IRL) 开发。创建开发人员级规则后,开发人员与分析员协作标识剩余规则并在规则模板(可以由多个非技术方重用)中捕获它们。该方法简化并加快了规则的生成,同时减少了可能出现的人为错误。 为启动基于模板的规则创建流程,分析员需连接到规则信息库。当分析员从信息库中打开规则程序包时,他们将能够访问该程序包的 BOM。ILOG 支持通过它的业务应用程序语言 (BAL) 定义高级规则。分析员可以在此时编辑现有规则,也可以创建新规则。可以在维护期间通过模板(用于限制可以对规则进行的修改)修改规则。 规则编辑器有一个默认模板,使开发人员可以使用 IF–THEN 结构创建条件和操作。如图 3 所示,业务分析员创建了一个检查家庭子女总数的规则。如果该变量等于 2,则家庭有资格参加 Healthcare Program 1。规则在数据类型 eligibilityResult 中返回值 true。
图 3 创建一个检查家庭子女总数的规则 开发一个新规则后,可以使用 ILOG Rule Builder 工具内部的示例数据对其进行测试。Rule Builder 中的该调试器支持断点,使用户可以检查有效的内存数据并显示规则执行顺序。完成规则编辑和测试后,分析员将规则程序包导入到规则集中并部署回信息库。 以下代码示例显示了 Eligibility ruleset 的实现。 // Eligibility ruleset receives an account and calculates eligibility results for multiple programs ruleset eligibility { in Account account; out List eligibilityResultsList = new ArrayList(); } // calculate program 1 then program 2 eligibility flowtask Program1_TaskFlow { body = { Program1_Setup; Program1_Eligibility; Program2_Setup; Program2_Eligibility; } }; // Determine which rules are setup rules for program 1 ruletask Program1_Setup{ body = select(?rule) { if("Program1_Setup".getTask(?rule) ) return true; else return false; } } // Determine which rules are eligibility rules for program 1 ruletask Program1_Eligibility{ body = select(?rule) { if("Program1_Eligibility".getTask(?rule) ) return true; else return false; } } // Create an eligibility result (JAXB object) for program 1 rule Progam1.CreateEligibilityResult { property task = " Program1_Setup"; when { ?account:Account(); ?person:Person(); } then { bind ?result = new EligibilityResult (); ?result.setPersonId(?person.getPersonId()); ?result.setProgramType(ProgramEnum.PROGRAM1); ?result.setEligible(Boolean.FALSE); modify ?person { getEligibilityResults().add(?result); }; } }; // simple rule make person eligible if over 6 years old and returns // result back in finalResults map rule Program1.AgeQualification { property task = " Program1_Eligibility"; when { ?person:Person(?age:getAge().intValue();); evaluate(?age >= 6); } modify ?result {setEligible(Boolean.TRUE); }; finalResults.add(?result); } }; 2. 将规则集公开为 Web 服务。 JRules 等规则引擎提供了相应的工具来生成包装程序 Web 服务或会话 Bean,以包装新开发的规则集。Web 服务开发人员将创建一个包装程序,以将规则集公开为 Web 服务。 XML 是一个用于集成规则、EJB、BPEL 流程和 Web 服务的关键标准。BPEL 使用本机 XML 访问数据,而 Web 服务使用它来序列化数据(并将在 Doc/Literal 调用中原封不动地使用它)。XML 可以在规则中直接使用。通过编组,可以将 XML 直接转换为 JAXB 对象树。可以使用本机 Java 对象执行规则。 Web 服务应在它们相应的 WSDL 定义中导入 XML 模式。从 XML 模式中生成的 DTO 对象(如 JAXB)还可以帮助确保数据顺利转换,而不会出现转换错误。 Eligibility Web 服务提供从 XML 到 JAXB 的转换,然后调用 Eligibility Rules Delegate Session Bean。要隐藏调用 JRules 自定义库的复杂性,可以创建一个会话 fa?ade。该方法使实现规则引擎“不可知”;可以将系统轻松地移植到一个新的规则引擎提供程序。Eligibility Delegate Session Bean 对 Eligibility fa?ade Session Bean 进行 RMI 调用。该会话 bean 使用 ruleSession.executeRules("RuleApp/eligibility") 调用 RuleApp 程序包中的 Eligibility ruleset。 import ilog.rules.bres.session.IlrRuleExecutionResult; import ilog.rules.bres.session.IlrStatelessRuleSession; import ilog.rules.bres.session.ejb.IlrManagedRuleSessionProvider; import ilog.rules.bres.session.util.IlrRuleSessionHelper; . . . public List assessEligibility(AccountRoot account) { List eligibilityList = null; // get stateless rulesession instance IlrStatelessRuleSession ruleSession = null; try { ruleSession = IlrManagedRuleSessionProvider.getProvider() .createStatelessRuleSession(); } catch (ilog.rules.bres.session.IlrRuleSessionCreationException ce) { String msg = "Failed to retrieve RuleSession Provider"; throw new InfrastructureException(msg, ce); } // pass borrower and credit as "in" parameters of the stateless session. IlrRuleSessionHelper helper = new IlrRuleSessionHelper(false); helper.addParameter("account", account); try { // execute rules and handle results IlrRuleExecutionResult res = ruleSession.executeRules("/RuleApp/ eligibility", null, helper.getJavaClassResolver(this), helper.getParameters()); eligibilityList = (List)res.parametersOut.getHandle("finalResults").getValue(); } catch(Throwable t) {
String msg = "Failed to execute rule!"; throw new InfrastructureException(msg, t); } return eligibilityList; }3. 从 BPEL 调用规则集 Web 服务。 开发所有自定义系统组件后,开发人员应将系统与 BPEL 引擎集成。原有系统和新的自定义组件由 BPEL 流程编排。可以在此时解决兼容性、数据类型转换和 Web 服务协议方面的问题。流程开发人员和/或系统集成商将在 Oracle BPEL Process Designer 内部实现编排流。 例如,BPEL 将使用以下代码调用基础 Eligibility Web 服务。 维护阶段。 对于维护阶段(项目中的最长阶段)而言,将业务规则移出 Java 代码并移入规则引擎中将增强维护的可管理性。正如我在前面所介绍的,业务管理者可以在运行时使用图形界面修改规则,业务规则和 BPEL 流程可以相互独立地进行更改。 使用 Oracle BPEL 流程管理器执行 JRule 显然,规则、Web 服务和 BPEL 流程的设计和开发涉及多种不同的技术。在本部分中,我将介绍这些技术如何在运行时协同工作以执行 Eligibility Process。尽管该示例专门基于 Oracle BPEL 流程管理器和 ILOG JRule,但它可应用于许多其他环境。 规则引擎调用将出现在三个层中(请参阅图 4):BPEL 调用规则 Web 服务、规则 Web 服务调用规则引擎、规则引擎应用程序代码接收输入并返回结果。
图 4 规则引擎调用演示 在示例业务流程的上下文中,应用程序使用 XML 有效载荷调用 Eligibility process。该有效载荷包含有关帐户的信息(如家庭属性)。Eligibility process 反过来调用 Eligibility Web service。Eligibility Web service 提供从 XML 到 JAXB 的转换,然后调用 Eligibility Rules Delegate Session Bean。后者使用 RMI 与会话 session fa?ade 交互。Session fa?ade 激活规则引擎,后者随后计算 eligibility 结果并将这些结果返回给该流程。Eligibility Process 将评估返回的结果并将 Program 1 或 Program 2 指定给该帐户。在该示例中,我们提供了一个远程服务器来运行 eligibility 规则,也可以在本地托管该规则。(注意,最佳实践是不要将非流程服务与 BPEL 流程管理器放在同一位置,这样可以实现更好的可伸缩性。) 该示例有效演示了如何将业务逻辑划分为规则、BPEL 和 Web 服务: Eligibility BPEL Process 显式定义了必须根据接收的 Eligibility Results 数据执行的步骤。Eligibility BPEL Process 将基于 Eligibility Results 调用不同的分支。Program 1 和 2 分别执行不同的步骤,可以使用 BPEL Designer 轻松地修改这些步骤。 Eligibility Web 服务为 BPEL 流程管理器执行中等粒度的任务,BPEL 流程管理器封装有关如何发送对应关系以及将任务排队的机制。Web 服务作用于诸如数据库键(如 Account OID)这样的常见数据模型(可用于提取详细数据以执行所需任务)中的摘要数据。 Eligibility 规则既不修改原始数据,也不访问外部数据源。由于您拥有准确的规则数据输入/输出记录,因此规则引擎审计线索比较简单。 图 5 演示了通过 Web 服务将规则集成到 J2EE 平台的细节。规则被部署到独立的 ear (EligiblityRules.ear) 中并在规则引擎管理控制台中注册。余下的支持逻辑部署在另一个 ear (EligibilityRuleService.ear) 中,后者包含 EligibilityRules 将需要的 Account JAXB 对象的类以及用于调用规则的会话 fa?ade。会话 fa?ade 隐藏了调用 JRules 自定义库的细节,同时还可以使系统移植到一个新的规则引擎提供程序。
图 5 通过 Web 服务将规则集成到 J2EE 平台中 结论 在这篇 BPEL“指南”中,我介绍了用于在三个不同层(业务流程层、Web 服务层和规则层)中分布业务逻辑的策略。可以使用这些辅助技术最大限度地降低数据和逻辑之间的相关性。但是,为了获得充分的好处,设计师必须执行严格的分析以分解系统组件,并使用相应的技术来设计它们。开发过程涉及多种技术和各种角色。在参与开发过程之前,必须标识相应的资源。最终的体系结构是一个灵活的平台,业务用户可在该平台上处理多数业务更改,而无需 IT 人员的参与。 Kevin Geminiuc [kgeminiuc@yahoo.com] 目前为 Denver 的高级软件设计师。在过去的 15 年里,Kevin 曾先后担任过系统设计师、技术经理、开发人员和硬件工程师。Kevin 在技术方面的兴趣包括 SOA、RFID、AVL 和一般软件。
|
|
|
[编辑文章 2 次, 最后修改: Pioneer 于 06-6-5 下午5:20] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
第 2 部分:使用 BPEL 构建 Web 服务网络 |
引言回复
回复
|
|
|
作者:Yves Coene 和 The Hoa Nguyen
欧洲航天局使用 BPEL 作用域、BPEL 域和 Oracle BPEL 流程管理器 API 构建易于合作伙伴使用的 Web 服务网络的案例研究。 受不断成熟的 Web 服务标准的鼓舞,越来越多的组织正在协作环境中使用 Web 服务。BPEL 正快速成为为实现企业间协作而编排这些 Web 服务的平台。BPEL 为构建在线市场或协作网络的公司提供了引人瞩目的好处,即基于标准的方法和松散耦合的流程集成。 而 Web 服务提供的激动人心的新功能却隐藏着某些风险。在许多情况下,如果在设计时未解决某些技术和管理难题,则合作伙伴关系将会破裂或集成成本飙升: 合作伙伴必须事先进行充分的协商,约定根据特定标准开展业务。传输协议、交互目的、消息格式以及业务约束必须实现清晰地通信。 连接网络必须是一个简单的过程;协作网络主要通过不断壮大取得成功。 用户必须在运行时轻松地找到业务服务,否则将在很大程度上无法实现面向服务体系结构 (SOA) 这一承诺。(服务信息库在这方面很有用。)如果开发人员无法轻松地找到和重用服务,则这些服务本质上就算不存在。 合作伙伴应能够实时监控 Web 服务。最终用户应能跟踪特定订单的进度,并且贸易合作伙伴应能诊断业务流程中的特定瓶颈。 如果协作网络在托管环境中运行,这些难题将变得更为棘手。在该模型中,合作伙伴将他们原有应用程序提供的功能公开到 Web 服务中,并将此 Web 服务发布到集中的信息库中。主机负责编排复杂的业务流程,后者反过来利用合作伙伴的 Web 服务。 在 BPEL 指南的这一部分中,我将把欧洲航天局 (ESA) 项目(来自 Spacebel s.a. 的小组参与了该项目)作为一个案例分析,介绍与这些挑战相关的体系结构注意事项。此外,我还将介绍该项目如何利用 BPEL 作用域、BPEL 域和 Oracle BPEL 流程管理器 API 构建一个“易于合作伙伴使用的”协作网络。 ESA 网络概述 ESA 已着手制定一个战略性计划,旨在完全基于开放标准创建一个 BPEL 驱动的服务提供商协作网络。该网络称作服务支持环境 (SSE) 网络,它组合第三方的地球观测 (EO) 和地理信息系统 (GIS) 服务,提供增值的复合型服务。SSE 是一个不断壮大的网络,目前包括遍布 9 个不同国家/地区的 20 多个合作伙伴。 如图 1 所示,SSE 是一个支持 BPEL 的网络的简单实现。ESA 充当中介,它使用各种 Web 服务标准(如 SOAP、WSDL、WS-Addressing、WS-Inspection 等)为不同合作伙伴之间基于流程的协作提供支持。该网络在集中星型拓扑环境中运行:服务提供商使用 Oracle BPEL Designer 将不同类型的地球观测和 GIS 服务集中到一个信息库中,从而创建了一个不断扩大的服务目录。
图 1 SSE 体系结构 SSE 提供执行以下任务所必需的基础架构 承载和管理充当可用服务目录的中央信息库 在中央目录内部注册和搜索服务 在 Oracle BPEL 引擎内部执行短期和长期的业务流程 使合作伙伴能够使用 Oracle BPEL 流程管理器控制台监控 Web 服务的执行 最终用户通过浏览可用服务目录请求特定服务。SSE 根据请求调用相关的业务流程。该业务流程调用 Web 服务(运行在服务提供商处)来完成请求。 SSE 支持同步和异步的交互模型。ESA 广泛使用 Oracle BPEL 流程管理器 API 来为提供商和最终用户提供最大程度的灵活性和易用性体验。 设计 Web 服务网络 开放标准正在不断改变集成的规则。BPEL 提供了一个以流程为中心的跨企业集成方法,因此可以使用 BPEL 流程流定义合作伙伴集成。SOA 与 BPEL 的这一组合为构建松散耦合的协作网络提供了一个前所未有的良机。 集中星型(SSE 采用的方法)是一个广泛使用的网络拓扑,组织通过它与各种合作伙伴建立连接。网络也可以采用单向对等模型。这种情况下,每个合作伙伴都为 Web 服务安全性和供应提供了一个平台。 现在,我们来看网络设计的四个方面: 设置接口关系 简化合作伙伴支持 创建集中的服务注册表 为合作伙伴和最终用户提供自助监视功能 设置接口关系。协作网络设计从定义参与规则开始。这些规则指定在业务流程中交换的消息、这些消息的交换顺序以及该消息的物理属性。要正确通信,所有合作伙伴都必须能够回答以下问题。 交互的目的 — 是请求报价还是订单? 消息格式 - 消息是如何编码的? 词汇 — 应如何构造消息,以便其他各方可以理解和处理它们? 业务约束 - 应在多长时间内响应请求? 通信渠道 - 是否应把消息加密? 为帮助合作伙伴回答以上问题,ESA 公布了一个接口控制文档来定义这些术语。本文档正式确定了在多个 ESA 赞助的项目中建立、改进和验证的技术集成规则。基于消息的 SOAP(通过 HTTP 或 HTTPS 实现安全通信)是 SSE 服务器与服务提供商之间采用的通信协议。(对于本文档,我们将分析 WS-Security 的用法。)Web 服务定义语言 (WSDL) 是唯一一个绑定了所有实体的接口协定;服务提供商必须创建一个 WSDL 文件,用于描述它的 SOAP 接口并使其他合作伙伴可以访问该接口。WSDL 文件中包含的某些信息是固定的,但必须提供以下信息: 根据选定的交互模型(搜索、RFQ、订购)选择的操作 服务的物理位置 服务 XSD 模式的导入 为便于服务、一致性和消息转换的比较,ESA 要求使用 XSD 模式表示 XML 有效载荷。SSE 还要求使用主 XSLT 文档来确保表示层中的一致性。必须按如下所示在每个服务中导入模板样式表: ... xsl:apply-imports 使用从 SSE 样式表中导入的模板规则处理根节点。注册该服务时,服务提供商提供 XML 模式、WSDL 和 XSLT 文件的 URL。SSE 强制使用文档样式的 SOAP。该方法允许使用 XML 模式对输入服务和服务输出的数据进行详细的指定并验证传入和传出的消息。 ESA 采用的方法为打算构建一个合作伙伴数量有限的 Web 服务网络的公司提供了一个便捷解决方案。随着网络规模的增长,将需要引入新的消息格式、通信规则、安全性以及传输机制。 简化合作伙伴的参与。任何网络的壮大都离不开合作伙伴的轻松参与。下列因素将对此过程产生很大的影响。 与集线器的集成 - 合作伙伴如何创建和提交他们的 Web 服务?集线器能否支持不同的传输协议? 流程管理 - 不同合作伙伴流程之间是否有清晰的界限?合作伙伴能否修改它的业务流程而不影响整个网络的可靠性?能否使用元数据定义即时生成流程? SSE 通过降低对服务提供商的技术要求成功稳固了与其合作伙伴的联系。ESA 通过分发合作伙伴连接软件、划分开发平台以及自动代表合作伙伴生成流程流实现了该目标。 例如,为加快集成流程的速度,ESA 分发了 SSE Toolbox,这是一个在 SSE 与服务提供商的现有系统间充当接口的免费工具包。基于 Sun Java Web Services Developer Pack 的 SSE Toolbox 提供了一个支持各种后端集成机制(如 FTP、文件交换、JDBC、调用 Java API、HTTP 等)的 XML 脚本语言。它还自动生成注册服务所需的 WSDL 文件。 不同的合作伙伴将多个服务提供给中央信息库。开发和部署环境的划分使合作伙伴间的更改互不影响。SSE 通过在 Oracle BPEL 流程管理器中使用 BPEL 域有效地利用了划分功能。BPEL 域使开发人员或管理员能够将 Oracle BPEL 流程管理器的单个实例划分为多个虚拟 BPEL 沙箱。BPEL 域由一个 ID 标识,并由一个口令保护。当服务提供商在 SSE 上注册时,将调用 Oracle BPEL 流程管理器 API 自动创建一个 BPEL 域保存服务定义文件。 以下是一个 createDomain 方法示例: /** * Create new domain space for a service provider to hold her/his services workflow * definitions files in * * @param domainName The Id to identify the domain * @param password The password used to login to the corresponding domain * @exception RemoteException System communication error * @exception WorkflowException Thrown if any error happens on the server that prevent the delete * */ public void createDomain(String domainName, String password) throws RemoteException, WorkflowException{ if(ml.isDebugEnabled()) ml.debug("Enter createDomain(domain = " + domainName + " password = " + password); /** * check if the being created domain exist? */
try { Locator locator = new Locator(domainName, password); ml.info("Stop creating domain:" + domainName + " because it has already existed."); throw new WorkflowException("1019"); } catch (com.oracle.bpel.client.ServerException e) { ; } try { //obtain the domain admin password from the system configuration SSE.properties file String domainAdminPassword = SystemConfigurationInfo.getProperty(WorkflowConstant.BPEL_DOMAIN_ADMIN_PASSWORD); ServerAuth auth = ServerAuthFactory.authenticate( domainAdminPassword, "localhost" ); if(ml.isDebugEnabled()) ml.debug("obtain authentication ok"); // Create server object ... this is our service interface // Server server = new Server( auth ); // Domain id is "newDomain", the password is "myPassword" if(ml.isDebugEnabled()) ml.debug("create server instance ok"); // Map domainProperties = new HashMap(); domainProperties.put( Configuration.DATASOURCE_JNDI, SystemConfigurationInfo.getProperty (CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI)); domainProperties.put( Configuration.TX_DATASOURCE_JNDI, SystemConfigurationInfo.getProperty (CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI)); if(ml.isDebugEnabled()) ml.debug("create domain - ds jndi property key/value: " + Configuration.DATASOURCE_JNDI + "/" + SystemConfigurationInfo.getProperty (CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI)); if(ml.isDebugEnabled()) ml.debug("create domain - tx_ds jndi property key/value: " + Configuration.TX_DATASOURCE_JNDI + "/" + SystemConfigurationInfo.getProperty (CommonConstant.DEFAULT_BPELDOMAIN_DS_JNDI)); server.createDomain(domainName, password, domainProperties);
if(ml.isDebugEnabled()) ml.debug("Enter createDomain(domain = " + domainName + " password = " + password); } catch( com.oracle.bpel.client.ServerException se ){ ml.error(se.getMessage()); if(ml.isDebugEnabled()) se.printStackTrace(); throw new WorkflowException("1018", se.getCause()); } } 在下面 runBuildScript 方法的实现中,通过一个 Ant 构建脚本访问 Oracle bpelc 函数。runBuildScript 方法调用一个 Ant 项目文件,后者随后调用 bpelc 编译和部署服务提供商的 BPEL 流程。 /** * execute the ant script to build an Oracle BPEL process that implements the workflow. * The script also deploys the workflow to the service domains. * All input information is provided under the props at the input param. * @param props Contain all necessary properties used to build/deploy the workflow BPEL process * @throws WorkflowException */ private void runBuildScript(String buildFilename, Properties props) throws WorkflowException{ if(ml.isDebugEnabled())ml.debug("Enter runBuildScript(buildFileName = " + buildFilename + ", properties = ..."); try { Project project = new Project(); project.init(); File buildFile = new File(buildFilename); if (!buildFile.exists()) throw new WorkflowException("1015"); if(ml.isDebugEnabled()) ml.debug("ant build file:" + buildFile.getAbsolutePath()); ProjectHelper.configureProject(project, buildFile); //prepare logger for the project build PrintStream out = System.out; BuildLogger logger = new DefaultLogger(); logger.setMessageOutputLevel(Project.MSG_DEBUG); logger.setOutputPrintStream(out); logger.setErrorPrintStream(out); project.addBuildListener(logger); //set project properties Enumeration keys = props.keys(); while(keys.hasMoreElements()){ String key = keys.nextElement().toString(); project.setProperty(key, props.getProperty(key));
} // test //excute default target project.executeTarget(project.getDefaultTarget()); if(ml.isDebugEnabled())ml.debug("Exit runBuildScript(buildFileName = " + buildFilename + ", properties = ..."); } catch (Exception ex) { ml.error(ex.getMessage()); if(ml.isDebugEnabled()) ex.printStackTrace(); throw new WorkflowException("1002",ex.getCause()); } } 在 Web 服务网络设计中,应考虑使用 BPEL 域为所有相关各方划分流程设计和部署平台。以下是一些可能的应用: 将单个 Oracle BPEL 流程管理器实例划分为多开发人员环境。这种情况下,域 ID 通常标识拥有该域的开发人员。 将单个 Oracle BPEL 流程管理器实例划分为开发环境和 QA 环境。这种情况下,域 ID 可能为“test”和“QA”。 将单个 Oracle BPEL 流程管理器实例划分为一个可以由多个部门或合作伙伴使用的环境。这些情况下,域 ID 是部门或合作伙伴的名称。 创建中央服务信息库。定义了网络关系后,合作伙伴便可以免费加入并提供他们的服务。当然,发布和搜索这些服务的功能是 SOA 平台的一个基础功能。 在该流程中,合作伙伴将他们的 Web 服务发布到一个中央信息库,有关该服务的所有信息都在这里进行管理。这个中央框架提高了服务的可重用性,最大限度地降低了定位服务所需的工作量和时间。没有中央信息库将导致不一致和混乱。这反过来会降低网络的灵活性和开放性。 SSE 网络频繁使用中央 Web 服务信息库;合作伙伴使用 Web 服务检查语言 (WSIL) 发现可用服务。服务提供商可以通过选择相应的 WSDL 文件重用现有的 Web 服务(由网络中的其他提供商提供)。可以在 Oracle BPEL Designer 工具配置文件 UDDIProviderList.xml 中添加 WS-Inspection URL http://services.eoportal.org/inspection.wsil 来完成此任务,如下所示。 ESA SSE Portal wsil http://services.eoportal.org/inspection.wsil
位于服务提供商处的 Oracle BPEL Designer 连接到 SSE 服务器并使用 WS-Inspection 协议发现可用服务及其 WSDL 文件。连接到 WS-Inspection 服务器后,将显示所有可用服务列表,如图 2 中所示。
图 2 可用 SSE 服务列表 对于每个服务,将提供相应的 WSDL 文件和简短的文字描述。可以通过选择 WSDL 文件为该服务添加一个合作伙伴链接。构建流程流后,可以使用 BPEL 控制台将其部署在 SSE 门户上。(在它的下个版本中,SSE 将实现 UDDI 注册表与 Oracle BPEL 的集成。注册新服务时,还将在此 UDDI 注册表中自动注册该服务。该集成将简化使用外部工具的服务发现,目前仅当这些工具支持 WS-Inspection 时才能发现服务。) 尽管您不必建立服务信息库即可构建 SOA 并获得它的众多好处,但从长远来看,信息库是不可或缺的。如果服务的作用域只是一个项目,则架构师不用信息库也能处理。但大多数企业都拥有各种服务和合作伙伴,并且这些服务和合作伙伴的大部分都在不断变化。 提供自助式监视。在多方参与业务流程的协作网络中,对业务流程执行情况的监视非常关键,因此可以将围绕业务流程的关键性能指标与服务级协议相联系。(例如,加入网络的关键要求之一可能是确认两小时内的报价请求。)监视业务流程可以更好地获知特定业务流程实例执行的时间、出现延迟的原因以及如何为未来事务修复此问题。 应向合作伙伴和最终用户提供该级别的诊断。通过创建自助式环境,合作伙伴和最终用户可以跟踪他们的单个流程,从而减轻中央监视框架检测到的问题。 可以使用 Oracle BPEL 控制台监视和调试业务流程(参见图 3)。ESA 和服务提供商利用 BPEL 控制台跟踪正在运行和已经完成的 BPEL 流程实例数量、流程实例的平均持续时间(从而细分流程中消耗的时间)以及文本格式的流程实例审计线索,从而使合作伙伴可以查看中间结果。
图 3 使用 Oracle BPEL 控制台监视业务流程 此外,订购了特定服务的最终用户可以跟踪其订单的状态。可以使用 Oracle BPEL 流程管理器 API 在 BPEL 控制台的外部显示该信息。建议服务提供商在他们的 BPEL 流程中使用有意义的作用域名称;在运行时,门户使用 IInstanceHandle.getStatus() API 提取当前 BPEL“作用域”的名称向最终用户显示该进度的信息。 作用域 按层次结构组织,一个复杂的业务流程可以分为几个作用域。它们为活动提供了行为上下文。通过在 BPEL 流程中使用有意义的作用域名称,合作伙伴可以跟踪“短期”和“长期”业务流程的状态。 例如以下 getOrderSubstatus 方法的实现。该方法使 ESS 合作伙伴可以使用在 bpel 文件中执行的作用域的名称获取 BPEL 流程实例的当前状态。 * call the Oracle BPEL API to get current status of the workflow instance, corresponding to * the ordered supplied at the input * @param ordered The order identified * @param workflowId The workflow name (or Id) that is processing the order stage. * Normally, there are two stages of an order:send(process)rfq and send(process) order * @param domain The domain that the order workflow belongs to * @param password The password used to login to the workflow domain * @return the current status of the workflow instance - particularly, it is the name of the current * active scope in the workflow BPEL file. * @throws RemoteException * @throws WorkflowException */ public String getOrderSubstatus(String ordered, String workflowId, String domain, String password) throws RemoteException, WorkflowException { if(ml.isDebugEnabled()) ml.debug("Enter getOrderSubstatus(ordered = " + ordered + ", workflowId = " + workflowId + ", domain = " + domain + ", password = " + password); String status = ""; try { Locator locator = new Locator(domain, password); IinstanceHandle instance = locator.lookupInstance(ordered + "_" + workflowId); if( instance.isComplete() ) status = "Completed"; else status = instance.getStatus(); return status; } catch (com.oracle.bpel.client.ServerException e) { // TODO Auto-generated catch block ml.error(e.getMessage()); if(ml.isDebugEnabled()) e.printStackTrace(); throw new WorkflowException("1016", e.getCause()); } } 结论 ESA 在构建其整个协作网络时始终没忘其灵活性。接口关系的灵活定义简化了网络的采用并促进了网络的发展。BPEL 域的采用提供一个独立的工作区,从而为服务提供商提供了广泛的灵活性;服务提供商可以修改他们的业务流程且不会影响网络的稳定性。BPEL 作用域已经使 ESA 可以从细节上跟踪即时流程的状态。该网络还可代表服务供应提供商自动生成 BPEL 流程流。所有这些因素渐渐地使该网络更易于合作伙伴使用,并最大限度地降低了合作伙伴的前期投资。 但还有一些网络设计领域本文并未涉及,如分布式事务管理、安全性以及贸易合作伙伴管理。随着 B2B 网络规模的扩大,BPEL 可以在编排专用流程方面处于领先地位。例如,Oracle 集成 B2B 产品(可以与 Oracle BPEL 流程管理器交互操作)解决了公共流程编排、握手协议支持(RosettaNet、ebXML、EDI、HIPAA)、消息格式处理(MIME、SMIME、AS2、XMLDSig)和贸易合作伙伴管理(认可、服务级协议、合作伙伴协议)。 Yves Coene 当前在 Spacebel s.a.(位于布鲁塞尔)担任项目经理。他在航空软件项目(如 Ariane 5、International Space Station、F16 MLU)和欧洲航天局的各种其他项目方面具有 15 年的工作经验。自 2001 年以来,他和他的团队一直在意大利的 Frascati 负责 ESA 的 SSE 项目。 The Hoa Nguyen 当前在 Spacebel s.a.(位于布鲁塞尔)的 SDC 子公司担任高级软件工程师。他的主要兴趣是 J2EE、Web 服务以及使用 BPEL 进行工作流开发。自 2001 年以来,他一直是 Spacebel 的 SSE 项目小组的主管工程师之一,此外他还在 ESA 负责 SSE 软件发布以及 SSE 软件现场安装。
|
|
|
[编辑文章 2 次, 最后修改: Pioneer 于 06-6-2 下午4:22] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
|
|
Web 服务和面向服务体系结构 (SOA) 使业务流程可以通过与其他业务流程和应用程序进行交互而轻松扩展。BPEL 流程通过合作伙伴链接定义此交互。这些链接定义了接口(消息和操作)、传输协议,并且最重要的是定义了要使用的每个服务的位置。 在大多数基本流程设计中,合作伙伴链接是静态的;它们引用开发人员在设计时指定的一个外部流程。该方法适用于高度定向或高度限制的系统。而在大型系统中,业务流程更为复杂。它们与多个外部服务交互,并定义了多个合作伙伴链接,而且其中的某些合作伙伴链接在设计时可能是不可知的。因此,必须在业务流程内部构建所有可能的调出以及用于确定要使用的合作伙伴链接的逻辑,这将使该流程不必要地复杂化。此外,随着合作伙伴链接的增加,最终的流程变得越来越难以处理,这是因为对合作伙伴链接的任何更改都要求修改整个业务流程。 幸运地是,BPEL 语言支持合作伙伴链接的动态绑定 概念。动态绑定使开发人员可以通过配置或运行时的输入添加新服务。该方法不需要在设计时预计和管理所有父子关系。 在BPEL 指南的这一部分中,我将概述一个有效的策略,即让系统在运行时动态管理合作伙伴链接,从而使 BPEL 流程不受合作伙伴关系链接变化的影响。此外,我还将介绍如何按顺序或并行地动态调用多个 BPEL 流程。 动态绑定概述 与传统编程领域的面向对象的分析和设计相似,合作伙伴链接的动态绑定可以实现代码模块化以及流程之间的运行时绑定。该方法的好处包括: 通过将功能组件细分为工作单元支持面向小组的开发 不必修改和重新部署父流程即可创建和部署更多子流程组件 使用、维护和增强单个重叠流程的需要降低 父流程可以自动获知子流程的更改和增强 本质上而言,动态流程使系统可以适应在设计时不可知的条件。例如,可以根据数据内容确定流程 - 如果数据不充分,则可以在运行时调用外部数据源(如外部数据库)来确定流程。 使用动态流程还可以为在高级流程的开发与配置和维护之间存在职责划分的组织带来重要好处。开发小组可以负责了解 BPEL 实现以及流程组件创建的细节,随后,业务分析员或支持小组等领域专家便可以将这些组件组装到单个工作流中,而不必详细了解合作伙伴链接、命名空间、WSDL、XPATH 以及其他技术细节。 构建动态 BPEL 流程 正如我在前面所介绍的,合作伙伴链接描述业务流程或其他服务的接口。BPEL 流程使用合作伙伴链接中存储的信息调用这些外部服务。 合作伙伴链接使用 WSDL 中的 portTypes 定义构成服务接口的操作和消息类型。如图 1 所示,portTypes 还间接定义了用于与服务(绑定)和服务的位置(服务)进行通信的传输。
图 1 工作中的 portTypes 在静态 BPEL 流程中,合作伙伴链接信息在设计时定义。但在某些情况下,开发人员并不知道所有合作伙伴链接信息,或者需要在运行时更改所有合作伙伴链接信息以满足数据或其他动态要求。 来看一个贷款处理情景的示例。在该示例中,您需要根据输入数据(如地理区域、贷款额或信用记录)选择贷款提供商。该数据在运行时是不可知的,并且如果涉及很多可能的贷款提供商,则可能很难将该流程的模型构建为静态地管理您可使用的所有不同服务。 动态地选择提供商则解决了这个问题。WS-Addressing 标准提供了一个称作端点引用的机制,使您可以在 WSDL 中选择一个可用服务,甚至还可以在运行时定义新服务。业务流程静态地依赖于 portType 中定义的接口信息,而端点引用(将绑定映射到服务)使您可以动态重新定义服务位置。本质上而言,端点引用是 WSDL 中定义的静态服务元素的动态替换项。在很多情况下,只要服务全部与标准接口一致,流程设计者便可以不必决定要调用哪些服务。Oracle BPEL 流程管理器附带的 DynamicPartnerLink 示例为了解这些主题提供了一个不错的切入点。我们将逐步研究该示例;然后,您将了解如何从头构建一个动态流程。(注意:建议您在使用该示例之前熟悉一下标准 LoanFlow 教程。) 了解 DynamicPartnerLink 示例 DynamicPartnerLink 示例是了解合作伙伴链接和端点引用这两个基本概念的十分好的资源。它允许您从三个贷款服务提供商(United、Star 和 American)中指定一个,并根据流程输入动态调用相应的服务。 在本文中,您将使用 Oracle BPEL 流程管理器 10.1.2 的 GA 版本中提供的示例;您将在目录 [BPEL_HOME]\samples\references\DynamicPartnerLink 中找到它。我使用 10.1.2 版的补丁 1 开发并测试了本文介绍的代码。 注意:当您初次加载和部署 Dynamic Partner Link 示例时,请不要在 Oracle JDeveloper 可视化设计器中对代码进行任何修改,只按原样部署它即可。如果要进行并保存这样的更改,JDeveloper 将通过引入换行符基于它的标准 XML 布局重新格式化 BPEL 代码。JDeveloper 修改 数据内部的 和 标记,在 和 结束标记之前添加一个换行符。附加到这些元素内部的数据的换行符用于中断绑定。如有必要,可以删除服务和地址上位于结束标记之前的换行符来更正该问题。稍后,我将介绍另一个方法来填充不受 JDeveloper 所应用格式影响的端点引用。 从控制台启动该示例时,将要求您填写贷款流程演示的标准贷款应用程序数据(SSN、电子邮件等)以及“provider”域。在 provider 字符串中指定以下值之一:united、american 或 star。分别使用这三个值运行该示例,查看它的运行情况。该流程将动态调用相应的贷款提供商。也可以在 provider 字符串中使用某个其他值或根本不使用值来试用该示例。 要了解该动态流程如何工作,首先必须分析 DynamicPartnerLink.bpel 文件。该文件中第一个比较有意义的项是贷款服务合作伙伴链接: 该链接指定了一个通用贷款服务名称和类型 (services:LoanService),而没有定义特定的贷款服务(如 UnitedLoan)。LoanService 合作伙伴链接是在 LoanService.wsdl 文件中定义的;导入该文件的方法是将它添加到 bpel.xml 文件的 部分中,如下所示: LoanService.wsdl 在 LoanService.wsdl 文件中您将发现,每个可用的贷款供应商都在这个 WSDL 文件中定义为 ,如下所示。 <service name="StarLoan"> <port name="LoanServicePort" binding="tns:LoanServiceBinding"> <soap:address location="http://localhost:9700/orabpel/default/StarLoan"/> </port> </service>
<service name="UnitedLoan"> <port name="LoanServicePort" binding="tns:LoanServiceBinding"> <soap:address location="http://localhost:9700/orabpel/default/UnitedLoan"/> </port> </service>
<service name="AmericanLoan"> <port name="LoanServicePort" binding="tns:LoanServiceBinding"> <soap:address location="http://localhost:9700/orabpel/default/AmericanLoan"/> </port> </service> 必须应认识到,并不存在“真正”名为“LoanService”的服务。而 LoanService 只是一个模板,不过从中可以选择真正的贷款提供商服务(UnitedLoan、AmericanLoan、StarLoan)。只要真正的服务全都支持模板 WSDL 中定义的同一接口(相同的数据类型、消息、角色、端口和合作伙伴链接类型),该方法便会有效。由于此处的更改可能会彻底影响许多流程,因此必须仔细地定义该模板。 LoanService.wsdl 文件定义了所有服务选项,父流程可以从中选择要动态调用的选项。该模型要求在添加每个新服务时重新部署 WSDL 文件。与修改父流程以使每个新服务都包含新合作伙伴链接和路由逻辑相比,该方法有了很大的改进。(稍后,您还将了解如何将服务端点与 WSDL 文件解除关联。) 返回到 DynamicPartnerlink.bpel 文件,我们要了解的下一个特性是 partnerReference 变量: 该变量的类型为 EndpointReference。它包含一个命名空间 wsa,后者在该文件的顶部定义为 xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing" WS-Addressing 标准提供了 EndpointReference 类型的模式。可以使用 将此类变量指定到合作伙伴链接以便修改地址和服务信息,这样就可以在运行时修改合作伙伴链接了。 DynamicPartnerLink 流程基本上由一个切换组成。它检查调用方传入的“provider”字符串。然后,它将 EndpointReference xml 数据结构指定给 partnerReference 变量,该变量包含与您请求的服务相关的信息。切换后,将 partnerReference 变量指定给 LoanService 合作伙伴链接,随后将调用该合作伙伴链接。 下面是在输入字符串(服务提供商)为“united”时如何完成该任务: <assign> <copy> <from> <EndpointReference xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing"> <Address>http://localhost:9700/orabpel/default/UnitedLoan</Address> <ServiceName xmlns:ns1="http://services.otn.com">ns1:UnitedLoan</ServiceName> </EndpointReference> </from> <to variable="partnerReference"/> </copy> </assign>
<from> 与</from>标记之间的所有内容均为指定给 partnerReference 变量的文字 XML。将 partnerReference 变量指定给 LoanService 合作伙伴链接时,该数据将覆盖此合作伙伴链接中指定的地址和服务。 您已经了解了如何使用 LoanService 合作伙伴链接和和 LoanService.wsdl 调用在运行时选择的服务,下面就可以开始构建一个动态流程了。 创建一个动态 BPEL 流程 现在,我们从头创建一个动态 BPEL 流程。 1. 创建一个新的 BPEL 项目。 在 JDeveloper 中创建一个新的异步 BPEL 流程项目,并将它命名为“MyDL”。 2. 从 DynamicPartnerLink 示例中导入 LoanService.wsdl 文件。 将 LoanService.wsdl 文件从 DynamicPartnerLink 示例复制到 MyDL 项目的工作目录中(默认情况下为 [BPEL_HOME]\integration\jdev\jdev\mywork\Workspace1\MyDL)。(该方法不但可以节省您的时间,而且还免去了您创建自己的动态 WSDL 和子流程服务的麻烦。)然后,在 Applications Navigator 中右键单击 MyDL 项目,选择 Add to Project...。从该目录中选择 LoanService.wsdl 文件,然后单击 OK。 尚未将 LoanService.wsdl 文件添加到 bpel.xml 文件中。您将在该流程的后面部分中(即实现 EndpointReference 变量时)执行该操作。 3. 创建贷款服务合作伙伴链接模板。 右键单击某个泳道,选择 Create Partner Link...。按图 2 所示填写该对话框。要填写 WSDL File 位置,您将使用 Browse WSDL Files from Local File System 按钮(位于手电筒图标的左侧)从 MyDL 项目目录中选择 LoanService.wsdl 文件。单击 OK 创建合作伙伴链接。
图 2“Create Partner Link”对话框 4. 创建调用和接收动作来外调 DynamicLoanService 合作伙伴链接。 将 invoke 和 receive 动作分别从组件模板拖到流程(位于 receiveInput 和 callbackClient 动作之间)中。将一个箭头从 invoke 拖到 DynamicLoanService 合作伙伴链接并创建输入变量。对 receive 执行相同的操作。这些变量应分别命名为 loanInput 和 loanOutput。 5. 配置输入数据 loanInput。 通常,您将修改 MyDL.wsdl 文件来从用户那里获得贷款输入数据。此处为简单起见,您只需硬编码一个 assign 来填充 loanInput 变量。将 assign 置于 receiveInput 动作之后并创建一个将值“123456789”(这是一个字符串,而非数字,因此不要忘了为它加上引号)放入 loanInput 的 SSN 元素中的复制规则: 6. 创建 partnerReference 变量。 在 Structure 窗口中,展开 Variables 树,然后展开 Process 并选择 Variables 项(参见图 3)。
图 3 展开“Variables”树 右键单击 Variables 并选择 Create Variable...。将变量名设为“partnerReference”,并将类型设为“Element”。单击元素框旁边的手电筒图标显示类型选择器。在 Project WSDL Files → LoanService.wsdl → Inline Schemas → schema 下找到类型“EndpointReference”(参见图 4)。
图 4 选择“EndpointReference” 7. 设置 partnerReference 变量。 在 DynamicLoanService invoke 前面创建另一个 assign。使用此 assign 设置 partnerReference 变量。最初,您将它硬编码为 UnitedLoan 服务,但您将在下个部分中把它变为动态。 此处,您可以通过重新格式化 EndpointReference xml 数据避免在 DynamicPartnerLink 示例中遇到的问题。创建一个用这个空 EndpointReference 填充 partnerReference 变量的复制规则: 在复制规则的“from”块中,在输入以上信息之前确保选择类型“XML Fragment”。由于在把 partnerReference 变量复制到 DynamicLoanService 合作伙伴链接时将其视为单独的 XML 文档,因此执行此复制才能为 partnerReference 建立命名空间信息。否则,在试图将 partnerReference 变量指定给合作伙伴链接时将发生一个空指针异常。 现在,您可以使用标准复制规则填充 partnerReference 变量的 ServiceName 和 Address 元素。确保根据空白端点引用中的定义为服务指定同一命名空间 (ns1)。 应如下所示: <assign name="SetupPartnerlink"> <copy> <from> <EndpointReference xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing" xmlns:ns1="http://services.otn.com"> <Address/> <ServiceName/> </EndpointReference> </from> <to variable="partnerReference"/> </copy> <copy> <from expression="'ns1:UnitedLoan'"/> <to variable="partnerReference" query="/ns3:EndpointReference/ns3:ServiceName"/> </copy> <copy> <from expression="'http://localhost:9700/orabpel/default/UnitedLoan'"/> <to variable="partnerReference" query="/ns3:EndpointReference/ns3:Address"/> </copy> </assign> 还要注意的是,直到使用 partnerReference 变量时,才会把 LoanService.wsdl 文件添加到 bpel.xml 文件中(以便可以访问 EndpointReference 模式)。 8. 将 partnerReference 变量复制到 DynamicLoanService 合作伙伴链接中。 在 DynamicLoanService 的 SetupPartnerlink 动作和 之间创建一个新的 。创建一个新副本并对它进行设置(如图 5 所示)。
图 5 创建一个新的复制规则 完成这些步骤后,将创建一个动态 BPEL 流程。该流程已经把地址指定硬编码了。可以用运行时收集的信息替换第 7 步中的最后两个复制规则来修正此种情况。图 6 中显示了 BPEL 流程示意图。
图 6 新的 BPEL 流程 提高动态流程的效率 正如您在前一个示例中看到的,LoanService.wsdl 列出了在运行时动态调用的所有可用服务。可以通过在每次添加新服务时消除修改业务流程的需要来丰富此业务流程的动态机制。新服务在 WSDL 中定义,并重新部署 WSDL 以启用新服务。 您可以将此动态机制再提高一个层次:WSDL 驱动的方法要求在设计时就知道新服务的位置,但您可以使流程更独立于 WSDL。该方法不需要在每次添加服务时重新部署 WSDL。 在运行时消除地址相关性。 服务地址可能经常变化,但您可以使动态流程在运行时不受这些变化的影响。如果只指定一个服务名称而未指定地址,则将从 WSDL 中检索服务地址。为了进行演示,我们从模板复制规则的 XML 片段中删除地址的 stub ()。由于您要很快恢复此地址信息,因此在执行此操作之前备份 MyDL.bpel 文件。此外,从 SetupPartnerLink 语句中删除操作该地址的复制规则。SetupPartnerlink 现在应如下所示:
现在,再次部署并运行 MyDL 流程。尽管缺少地址,它仍可以成功地调用 UnitedLoan 子流程。可以通过在 BPEL 控制台中查看流程树视图来验证该动作。其结果是,可以通过只部署一个新的 WSDL(它将包含已修改的服务地址信息)来修改动态流程的行为。需要权衡的是,添加新服务将需要修改和重新部署 WSDL。 独立于 WSDL 服务。 在某些情况下,除了有许多要管理的服务以外,您可能还遇到这样的情况:服务地址经常变化,或要避免对 WSDL 文件进行频繁地更新。允许流程在运行时指定端点引用的地址即可解决该问题。 返回前一个版本的 MyDL.bpel 文件(该文件包含地址操作复制规则)。从模板 XML 片段和 ServiceName 复制规则中删除服务信息,而不是删除地址信息。 现在应如下所示: 运行该示例时,即使在未指定服务名称的情况下,此流程仍正确调用 UnitedLoan 服务。您可以创建只包含一个虚拟服务的 DynamicPartnerLink WSDL,并且即便某些服务不在 WSDL 中,只要在运行时知道这些服务的地址就可以调用它们。如果由于某种原因未指定地址,则它将使用 WSDL 中默认服务的地址。因此,一个好办法就是让该服务指向实际的 BPEL 流程(一个可能记录错误或发送通知的流程)。 构建异常处理框架时就可以使用该技巧。如果有多个提供给定服务的可用地址(如本地服务器和远程冗余服务器),则可以在对主服务器的调用失败时使用异常处理程序覆盖端点引用中的地址信息并重试服务调用切换到第二个地址。 调用多个动态流程。 在某些情况下,可能需要将单个数据集按顺序或并行传递给多个子流程。您可以使用一个或多个 while 循环实现此类行为。 我们来看一个简单的示例。贷款服务提供商的办公时间可能是按一周的日期安排的。该信息存储在数据库中。贷款请求于星期一到达,当查询数据库时,它返回一个可用贷款服务提供商(United 和 Star)列表。要处理此贷款,需要按顺序或并行调用 United 和 Star 子流程。数据库查询返回以下结果: <dbOutput> <part xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="response- headers">null</part> <part xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="DynamiclinksCollection"> <n:DynamiclinksCollection xmlns:n=http://xmlns.oracle.com/pcbpel/adapter/db/top/MyDynamicLink xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Dynamiclinks> <address>http://localhost:9700/orabpel/default/UnitedLoan</address> <day>monday</day> <uid>1</uid> </Dynamiclinks> <Dynamiclinks> <address>http://localhost:9700/orabpel/default/StarLoan</address> <day>united</day> <uid>4</uid> </Dynamiclinks> </n:DynamiclinksCollection> </part> </dbOutput> 为了按顺序调用这些服务,您应创建一个 while 循环。该 while 循环从集合中获得地址并对每个服务执行一个动态调用/接收。 <!-- first setup the counter variable "i" --> <assign name="CounterReset"> <copy> <from expression="1"/> <to variable="i"/> </copy> </assign>
<!-- while loop goes until all link collection notes are done --> <while name="LoanLoop" condition="bpws:getVariableData('i') <= count(bpws:getVariableData('dbOutput','DynamiclinksCollection', '/ns3:Dynamiclin ksCollection/Dynamiclinks'))"> <sequence name="Sequence_1">
<!-- reset the endpoint with the usual xml fragment --> <assign name="ClearEndpoint"> <copy> <from> <EndpointReference xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing" xmlns:ns1="http://services.otn.com"> <Address/> </EndpointReference> </from> <to variable="partnerReference"/> </copy> </assign>
<!-- set the address in the endpoint variable based on the current node --> <assign name="SetEndpoint"> <copy> <from variable="dbOutput" part="DynamiclinksCollection" query="/ns3:DynamiclinksCollection/Dynamiclinks [number(bpws:getVariableData('i'))]/address"/> <to variable="partnerReference" query="/wsa:EndpointReference/wsa:Address"/> </copy> </assign>
<!-- copy the endpoint variable into the partner link --> <assign name="DoPartnerlink"> <copy> <from variable="partnerReference"/> <to partnerLink="LoanService"/> </copy> </assign> <!-- invoke the partner link --> <invoke name="Invoke_2" partnerLink="LoanService" portType="ns2:LoanService" operation="initiate" inputVariable="loanInput"/>
<!-- be sure to increment your counter or you have an infinite loop --> <assign name="CounterIncrement"> <copy> <from expression="bpws:getVariableData('i')+1"/> <to variable="i"/> </copy> </assign> </sequence> </while>
在以上示例中,您调用了异步服务。但可以并行调用这些异步服务,方法是从 while 循环中删除 并为它提供一个自己的 while 循环。在运行 捕获每个调出流程的响应之前,这些响应将排队。receive 任务将按照响应的返回顺序收集这些响应。该方法将避免短时间运行的任务发出的响应排在长时间运行的任务发出的响应之后。 在收集了所有异步响应之前,建议不要在 while 循环外部继续运行。 结论 您在本文已经了解到,通过使用端点引用进行动态绑定,BPEL 流程可以变得更为灵活并快速适应不断变化的业务条件。通过将业务逻辑与合作伙伴地址分离,可以增强流程的自适应性和可移植性。 Sean Carey 是SPS Commerce(一家在托管 EDI 领域中处于领先地位的公司)的软件设计师。Sean 在关键任务电子商务实现方面具有 7 年多的工作经验,并在软件设计方面具有 15 年的行业经验。
|
|
|
[编辑文章 2 次, 最后修改: Pioneer 于 06-6-2 下午4:49] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
|
|
作者:Matjaz B. Juric
了解 BPEL 流程如何使用 WSIF 访问 Java 类和 EJB。
2005 年 10 月发布
在现实情况中,BPEL 业务流程通常必须连接到现有的应用程序或系统。 本文主要介绍与 J2EE 组件的连通性,如 Java 类、Enterprise Java Bean (EJB)、Java 消息服务 (JMS)、可以通过 Java Connector Architecture (JCA) 访问的 ERP 系统、JDBC 数据库或其他 Java 资源。
尽管可以将这些资源转换为 Web 服务,但该做法存在几个缺点: 调用 Web 服务操作的性能开销要比调用原生 Java 类大好几个数量级,并且比调用 EJB 或其他原生 Java 资源大一个数量级。 (参见边条。) Web 服务调用缺乏在事务执行期间传送语境这一重要功能。 相比之下,当直接使用 Java 资源时可以自动传送事务语境,前提是 Java 资源提供这样的支持(例如,EJB 和 JCA 便提供这样的支持)。 因此,更好的做法是原生地访问这些外部资源。 虽然原生连接 Java 资源并不是 BPEL 的一个标准特性,但 Oracle BPEL 流程管理器提供了一个实现此目的的解决方案,即 Web 服务调用框架 (WSIF),它不需要修改或扩展 BPEL 代码。 此功能极大地扩展了 BPEL 的应用范围并使之适用于企业应用集成 (EAI)。
在 BPEL 指南的这一部分中,您将了解 BPEL 流程如何使用 WSIF 访问 Web 服务以外的资源。
了解 WSIF SOAP 与 WSIF 绑定之间的性能差异和事务差异 调用 Java 资源通常比调用 Web 服务速度快。 尤其是在使用普通 Java 类时,方法调用的性能要高出几个数量级。 Java 类加载到应用服务器流程中,BPEL 流程可以直接访问它们的方法。
使用 EJB 时,您通常可以选择使用本地接口或远程接口。 本地接口与普通 Java 类的性能几乎相同。 不同之处在于 EJB 容器会有一些开销。 而如果使用远程 EJB 接口,性能损失会更大(但根据我的评测,这一性能损失仍低于使用 Web 服务的性能损失,稍后我将对此加以说明)。
可以通过 RMI-IIOP 访问 EJB 远程接口,RMI-IIOP 需要客户端上有 stub 并使用服务器端上的框架。 远程方法调用在到达 EJB 之前必须经过几个层,这需要一定的时间。 因此,在使用远程接口时,应使用粗粒度方法并熟悉其他影响性能的 J2EE 模式。 请注意,如果将 EJB 部署在同一应用服务器中,则某些应用服务器将优化与这些 EJB 的通信。
对于 Web 服务,这种情况从性能角度而言将更为复杂。 通常,与 Web 服务的通信相当于与 EJB 远程接口的通信。 与 EJB 不同的是,Web 服务使用 SOAP,它的效率不如二进制 IIOP。 因此,调用方和接收方需要更多与构造和分析 SOAP 消息以及 XML 串行化相关的处理开销。 我做的测试表明,调用 Web 服务要比调用会话 bean 慢大约 5 到 9 倍。
使用 WSIF 调用 Java 资源还在事务方面具有优势。 Java 资源(如 EJB 和 JCA)通过 JTA(使用 JTS)支持事务。 JTS 基于 CORBA 对象事务服务,后者为基于 X/Open DTP 标准的分布式事务提供支持。 通过 JTA 支持事务的 Java 资源(EJB、JCA 等)可以使用 2PC(两阶段提交)协议参与分布式事务。
WSIF 支持使用 XA 接口(由 JTS 自动公开)在相关 Java 资源之间自动传送事务语境。 这意味着,如果您通过 WSIF 在 BPEL 流程中使用多个支持事务的资源(例如,两个 EJB),则将在资源之间自动传播事务语境。 如果出现异常,则整个事务将自动自动回滚,而不必在 BPEL 流程中定义补偿处理程序。
如果没有支持 WSIF 的 Java 资源,或者如果只使用 Web 服务或先将 Java 资源转换为 Web 服务,则将无法利用此特性。 而且,您必须为每个 Web 服务手动定义补偿处理程序。 这对任务关键的流程非常重要,并且简化了它们的设计与开发。
设想一个购买图书的业务流程。 此异步流程包含三个 Web 服务: 一个图书等级 Web 服务(返回从 0 到 5(最好)的图书等级)和用于两个相同书店服务的 Web 服务(返回图书价格)。 该流程选择较低的价格,然后完成购买。 本示例定义了故障处理程序,并将该流程分成多个作用域(参见 1_BuyBook\BuyBook.bpel)。
假设为了获取图书等级,您倾向于使用一个 Java 类、EJB(会话 bean)、可以通过 JCA 访问的企业信息系统中的服务或一个类似的 Java 资源。 要使用 Oracle BPEL 流程管理器将这些资源(可能还包括存在绑定的任何其他资源)整合到 BPEL 流程中,您只需修改服务绑定 (WSDL) 而非 BPEL 流程本身。 因此,要使用 Java 类替换图书等级 Web 服务,只需修改此 Web 服务的 WSDL(稍后将对其进行详细介绍)。
WSIF(最初由 IBM alphaWorks 在它的 Web 服务工具包中开发的一种 Apache 技术)是实现该方法的基本技术。 即使它不是通过 SOAP 通信的 Web 服务,它仍然可以使您在 WSDL 中描述 Web 服务,从而扩展了 Web 服务模型。 WSIF 还使您可以将这样的服务映射到实际的实现和协议。
换言之,您可以将 BPEL 流程中使用的任何合作伙伴 Web 服务的抽象描述绑定到相应的资源,而该资源可以使用某个受支持的 WSIF 绑定进行通信。 Oracle BPEL 流程管理器 10.1.2 使用的 WSIF 支持 Java 类、EJB、JCA、HTTP GET 和 POST 以及套接字;您还可以定义自定义 WSIF 绑定,并可以使用几乎 BPEL 中的任何资源。
该方法使 BPEL 对 EAI 和 B2B 都非常有用。 企业信息系统通常由许多不同的软件部分组成,如可以通过 JCA、EJB 访问的原有应用程序、在不同平台上开发的 Web 服务等。 要集成所有这些东西,必须使用不同的协议。 例如,如果软件移植到不同的服务器,或已升级为使用一种新技术,则必须升级集成代码,除非使用 WSIF。
WSIF 还提供其他重要好处: 通过 WSIF 调用服务可以维护原生协议的性能。 因此,在调用 Java 资源、原生 Java 类、EJB 或任何其他资源时,不必补偿 Web 服务的性能损失。 WSIF 支持使用 Java 事务 API (JTA) 在所涉及的支持事务的 Java 资源之间自动传送事务语境。 这样,Java 资源便可以参与分布式事务。 为了解 WSIF 的工作方式,您将在此处修改图书购买 BPEL 流程并调用 Java 类,然后调用 EJB。 注意,使用 WSIF,您只需修改服务的 WSDL 而非 BPEL 代码。 通过修改 WSDL,您将把调用绑定到 Java 资源而非 Web 服务。
首先,我们将重点介绍如何使用 Java 类代替图书等级 Web 服务。 要替换该 Web 服务,您需要创建一个与该 Web 服务具有相同接口的 Java 类;这将需要基于 WSDL 协定开发一个 Java 类。 另一种可能是使 WSDL 适应现有的 Java 类(或其他资源,如 EJB)。 第一种方法更合适,因为它是所谓的协定优先方法。 这样,服务的接口将适应 BPEL 流程的需要,而不是反过来。
Java 到 XML 的绑定
要从 BPEL 中调用 Java 资源,您需要使用 BPEL 变量中的数据,这些变量以输入参数的形式发送到 Java 资源并从 Java 中将数据返回给 BPEL。 BPEL 变量是 XML,而 Java 变量却不是;因此,您需要在 XML 和 Java 之间建立映射。
要从 Java 中处理 XML 数据,有多种方法可供选择: 通过 DOM(文档对象模型)API 手动处理 XML。 这样,相应 Java 方法的输入和输出参数的类型将为 W3C DOM API for Java 中的 Element。 使用 DOM 方法直接操作 XML。 使用自动化的 Java 到 XML 的绑定。 Java 到 XML 的绑定实现了 XML 模式类型到 Java 类型的自动转换。 为此,需要生成一些接口和一组 Java 类。通过这些接口和 Java 类就可以操作 XML 了。 这样就将 XML 隐藏起来了,但您可以通过接口(如 JavaBean)使用它。 这里有两种方法可供选用: Oracle BPEL 流程管理器通过使用 XML fa ades 支持默认的 Java 到 XML 的绑定。 使用自定义 Java 串行化程序。 Oracle 已经提供了自定义的串行化程序,它们支持 JAXB (Java API for XML Binding)、XML Bean 和 Axis Bean。 您还可以编写自己的串行化程序(稍后将对其进行详细介绍)。 . 我们先来了解一下 XML fa ades。
XML Fa ades。 XML fa ades 是 Oracle BPEL 流程管理器提供的用于 WSIF 的原始 Java 到 XML 的绑定,并且是该产品的有机组成部分。 XML fa ades 是一组 Java 接口和类。通过这些接口和类,您可以以相对简单的方式使用 get/set 方法访问和修改 BPEL 变量中存储的 XML 数据。 这种方式不要求您直接操作 XML — 此外,XML 隐藏在 fa ade 之后,您可以通过常规 Java 接口操作数据(一个称作 XML 串行化的概念)。 XML fa ades 的设计思想是通过与内置类型的映射为基本数据类型提供支持并从 XML 模式中为复杂类型生成 Java 类。
以下显示了 XML 模式和 Java 类型之间基本数据类型的自动映射:
XML 模式类型 Java 类型 ·xs:string · java.lang.String · char · java.lang.Character xs:int, xs:integer · int · java.lang.Integer · java.math.BigInteger xs:long · long · java.lang.Long xs:short · short · java.lang.Short xs:float · float · java.lang.Float xs:double · double · java.lang.Double · java.math.BigDecimal xs:byte · byte · java.lang.Byte xs:Boolean · boolean · java.lang.Boolean dateTime java.util.Calendar date java.util.Date
您可以看到,可以将大多数简单类型映射到基元类型或对象类型。 这样的映射很有用,它可以使映射适应 Java 代码中所用的实际类型。 除简单类型外,您还需要一种映射复杂类型的方法 — 无论是 WSDL 的 <types> 部分中定义的类型还是外部 XML 模式 (XSD) 文件中定义的类型。 例如,在图书等级 Web 服务 WSDL 中,您将看到一个将 BookDscType 类型的 BookRatingRequestMessage 作为输入的操作。 BookDscType 复杂 XML 类型用于 BookRatingRequestMessage 和相应的 BookRatingRequest BPEL 变量:
<xs:schema elementFormDefault="qualified" targetNamespace="http://oracle.com/service/bookrating/">
<xs:complexType name="BookDscType"> <xs:sequence> <xs:element name="Title" type="xs:string" /> <xs:element name="ISSN" type="xs:string" /> <xs:element name="Publisher" type="xs:string" /> <xs:element name="Authors" type="xs:string" /> </xs:sequence> </xs:complexType>
</xs:schema>
针对这个复杂 XML 类型的 XML fa?ade 提供了一个接口和一个类。通过它们您可以使用 Java getter 方法访问各个元素(title、ISSN、publisher、authors)。 XML fa?ade 还允许您使用 setter 方法修改元素数据。
该变量的 XML fa?ade 由提供以下方法的接口 (IBookDscType) 和类 (BookDscType) 组成: getTitle() 和 setTitle() getISSN() 和 setISSN() getPublisher() 和 setPublisher() getAuthors() 和 setAuthors() 还有一个工厂类 (BookDscTypeFactory),通过它您可以使用 createFacade() 方法创建 IBookDscType。 XML fa?ade 使代码更简单并更易于维护;对于包含许多成员字段的大型变量尤其如此。
Oracle BPEL 流程管理器提供了一个称作 schemac 的模式编译器实用程序。 使用此实用程序,您可以生成 XML fa?ades。 要为 BookRating.wsdl 生成 XML fa?ade,使用以下命令行: Z:\WSIF\2_JavaBindingClass>schemac BookRating.wsdl ---------------------------------------------------- Oracle XML Schema Processor Version 10.1.2.0.0 http://otn.oracle.com/bpel Copyright (c) 2002-2004 - Oracle (type schemac -help for help) ----------------------------------------------------
schemac> parsing schema file 'BookRating.wsdl' ... schemac> Loaded schemas from wsdl located at BookRating.wsdl schemac> generating XML business document ... schemac> compiling XML business documents ... Schemac completed successfully.
Z:\WSIF\2_JavaBindingClass>
要从 Java 资源中使用这些类,需要将它们编译到以下目录(BPEL 服务器可以在该目录中访问它们)。
C:\OraBPELPM_1\integration\orabpel\system\classes
schemac 实用程序有几个选项。 可以使用 -d 开关定义存储生成的 fa?ade 类的目录。 要查看 fa?ade 源代码,使用 -trace 选项。 schemac 实用程序还可以用于在 Java 类的外部生成 XML 模式。 这对于使服务接口适应现有的 Java 资源很有用。 必须使用 -R 开关并提供不带扩展名的 Java 类名。
开发 Java 类。 要用 Java 类替换图书等级 Web 服务而不修改 BPEL,需要一个与原始的图书等级 Web 服务具有相同接口(协定)的 Java 类。 这意味着 Java 类必须提供具有相同功能的操作,并且这些操作必须接受相同的参数并返回相同的结果类型 - 但操作名不必相同。
看看原始 WSDL 您将发现,图书等级 Web 服务提供了一个名为 BookRating 的操作,该操作接受一个输入消息并提供一个输出消息,因此是同步的:
<portType name="BookRatingPT"> <operation name="BookRating"> <input message="tns:BookRatingRequestMessage" /> <output message="tns:BookRatingResponseMessage" /> </operation> </portType>
The signatures of both messages are as follows: <message name="BookRatingRequestMessage"> <part name="book" type="tns:BookDscType" /> </message>
<message name="BookRatingResponseMessage"> <part name="rating" type="xs:int" /> </message>
该操作的输入参数的类型为 BookDscType。 要将 BookDscType 映射到 Java,使用相应的 XML fa?ade,即您在前面使用 schemac 工具生成的 XML fa?ade。 该操作的返回类型为 BookRatingResponseMessage 消息,其类型为 xs:int。xs:int 类型映射 java.lang.Integer。 (它还可以映射到 int 或 java.math.BigInteger,但您在此处使用 java.lang.Integer。)
您现在就准备好为图书等级 Web 服务编写 Java 等价类了。 调用新的 Java 类 BookRatingJava,该类将包含一个名为 getBookRating 的方法。 该方法的主体将超简单 - 您将向服务器控制台打印一个通知并返回等级 4。(例如,在实际例子中,您可以根据数据库中的数据计算图书等级。) 此代码如下所示。 注意如何使用 getTitle() 和 getISSN() 方法分别访问图书标题和 ISSN: package com.oracle.rating;
import com.oracle.service.bookrating.*;
public class BookRatingJava {
public Integer getBookRating (BookDscType book) {
System.out.println("Book rating for "+book.getTitle()+" ("+book.getISSN()+"): 4.");
return new Integer(4);
} }
在此处添加控制台输出是为了确认该流程实际上调用了 Java 类而非 Web 服务。
在 WSDL 中定义 WSIF 绑定。要“说服”BPEL 流程用 Java 类代替 Web 服务,必须定义到 Java 类的 WSIF 绑定。 您将在图书等级 WSDL(您将在其中添加绑定部分)中执行此操作。
每个 WSIF 绑定由两部分组成。 首先,必须定义实际绑定,其中您将指定: 所使用的绑定类型(Java 类、EJB、JCA 等) 类型映射,其中指定 XML 类型到目标类型(对于 Java 资源为 Java 类型)的映射。 必须为所有复杂类型定义映射;简单类型根据前面提供的表自动进行映射。 操作映射,其中必须为每个 WSDL 操作(在 <portType> 标记之下定义)指定目标资源中的相应操作(例如,Java 类的方法名)。 其次,必须指定将使用的服务。 此处请指定资源的确切名称。 如果为 Java 类,请指定它的全名(包括程序包名称)。
在实际情况中,某个资源(如 Java 类或 EJB)可能没有 WSDL。 此时必须执行以下步骤: 定义 Java 到 XML 的绑定,在其中选择如何映射输入参数并将值返回给 XML。 可以使用 XML fa?ades,并通过将 schemac 工具与 a?“R 开关(将根据 Java 类生成 XML 模式)结合使用来简化工作。 定义每个操作的签名以及相应的输入和输出消息。 在本文的后面部分中,您还将了解如何处理故障。 添加 WSIF 绑定。 添加 <partnerLinkType> 声明以便从 BPEL 流程中使用 WSDL。 尤其是在前两个步骤中,您可以使用工具或向导将资源自动转换为 Web 服务。 这些工具可用于大多数环境。 当然,实际上并不将资源转换为 Web 服务,但可以使用生成的 WSDL(需要额外的修改)。
针对 Java 类的 WSIF 绑定。 下面我们将为图书等级 Java 类定义 WSIF 绑定。 首先在 WSDL 文档的根元素(<definitions> 标记)中定义两个由 WSIF 提供程序使用的命名空间。 格式命名空间用于定义类型映射,java 命名空间用于定义操作映射以及 Java 类的全名:
<?xml version="1.0" encoding="utf-8" ?> <definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://oracle.com/service/bookrating/" targetNamespace="http://oracle.com/service/bookrating/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/" xmlns:java="http://schemas.xmlsoap.org/wsdl/java/" > ...
接下来,添加绑定部分。 该部分通常位于端口类型声明之后、合作伙伴链接类型之前。 下面为 BookRatingPT 端口类型定义 Java 绑定: 定义从 XML 到 Java 的类型映射。 输入参数 XML 类型 BookDscType 映射为 com.oracle.service.bookrating.BookDscType Java 类。 请注意,不必为输出 XML xs:int 类型提供映射,这是因为它自动映射为 java.lang.Integer。 此外还要定义,将 WSDL 操作 BookRating 映射为 Java 方法 getBookRating()。 请注意,WSDL 操作的名称和 Java 类的方法名不必相同,但输入参数和返回参数的类型必须相同:
... <binding name="JavaBinding" type="tns:BookRatingPT">
<java:binding/>
<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="tns:BookDscType" formatType="com.oracle.service.bookrating.BookDscType" />
</format:typeMapping>
<operation name="BookRating">
<java:operation methodName="getBookRating"/>
<input/> <output/> </operation>
</binding> ...
然后,指定所使用的服务。 定义该服务由 Java 类提供。 图书等级服务将使用 com.oracle.rating.BookRatingJava Java 类:
... <service name="BookRating">
<port name="JavaPort" binding="tns:JavaBinding">
<java:address className="com.oracle.rating.BookRatingJava"/>
</port>
</service>
图书等级 WSDL 的其他部分(包括合作伙伴链接类型)未更改。
测试该示例。 您现在就可以测试该示例并确认 BPEL 流程将使用 Java 类代替原始的 Web 服务了。 注意,您只修改了 WSDL;您并未对 BPEL 流程代码进行任何更改。
您将使用原始的 BPEL 代码和同一合作伙伴链接,并使用通常用于调用 Web 服务的 <invoke> 活动调用 BookRatingJava Java 类。 再次调用 BPEL 代码以调用图书等级服务:
... <!-- Synchronously invoke the Book Rating Web Service --> <scope name="BookRatingInvoke">
<faultHandlers>
<catchAll> <!-- If book rating is not available assign 0 --> <assign> <copy> <from expression="number(0)"/> <to variable="BookRatingResponse" part="rating"/> </copy> </assign> </catchAll>
</faultHandlers>
<invoke partnerLink="BookRating" portType="bkr:BookRatingPT" operation="BookRating" inputVariable="BookRatingRequest" outputVariable="BookRatingResponse" />
</scope> ...
在测试该示例之前,必须执行几个“簿记”活动。 首先,必须确保 BPEL 流程将使用已修改的 WSDL。 为此,修改 bpel.xml 文件,指定应从当前目录而非 Web 服务本身中提取 BookRating.wsdl 文件:
<?xml version="1.0" encoding="UTF-8" ?> <BPELSuitcase> <BPELProcess src="BuyBook.bpel" id="BuyBookJavaBinding"> <partnerLinkBindings> <partnerLinkBinding name="Client"> <property name="wsdlLocation"> BuyBook.wsdl </property> </partnerLinkBinding> <partnerLinkBinding name="BookRating"> <property name="wsdlLocation"> BookRating.wsdl </property> </partnerLinkBinding> <partnerLinkBinding name="BookStore1"> <property name="wsdlLocation"> http://localhost:9700/orabpel/default/BookStore1/BookStore1?wsdl</property> </partnerLinkBinding> <partnerLinkBinding name="BookStore2"> <property name="wsdlLocation"> http://localhost:9700/orabpel/default/BookStore2/BookStore2?wsdl</property> </partnerLinkBinding> </partnerLinkBindings> </BPELProcess> </BPELSuitcase>
然后,使用 schemac 实用程序生成 XML fa?ade 并编译 BookRatingJava 类。 必须将 XML fa?ade 和 Java 类部署到 C:\OraBPELPM_1\integration\bpelpm\orabpel\system\classes 目录,BPEL 服务器可以在该目录中找到并使用它们。 最简单的方法是修改 build.xml。build.xml 应调用 scemac 编译器、javac 编译器和 bpelc 编译器:
<?xml version="1.0"?> <project name="BuyBookJavaBinding" default="all" basedir="."> <property name="deploy" value="default"/> <property name="rev" value="1.0"/>
<target name="CompileJava"> <schemac input="${basedir}/BookRating.wsdl" out="${home}/system/classes"/> <javac srcdir="${basedir}/src" destdir="${home}/system/classes"/> </target>
<target name="main"> <bpelc home="${home}" rev="${rev}" deploy="${deploy}"/> </target>
<target name="all" depends="CompileJava, main"/>
</project>
启动 obant 实用程序后,将获得以下输出:
Z:\WSIF\2_JavaBindingClass>obant
Z:\WSIF\2_JavaBindingClass>SETLOCAL Buildfile:build.xml
CompileJava: [schemac] schemac> parsing schema file 'Z:\WSIF\2_JavaBindingClass/BookRating. wsdl' ... [schemac] schemac> Loaded schemas from wsdl located at Z:\WSIF\2_JavaBindingCl ass/BookRating.wsdl [schemac] schemac> generating XML business document ... [schemac] schemac> compiling XML business documents ... [javac] Compiling 1 source file to C:\OraBPELPM_1\integration\orabpel\system \classes
main: [bpelc] validating "Z:\WSIF\2_JavaBindingClass\BuyBook.bpel" ... [bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain s\default\deploy
all:
BUILD SUCCESSFUL Total time: 17 seconds
Z:\WSIF\2_JavaBindingClass>ENDLOCAL
Z:\WSIF\2_JavaBindingClass>
然后,使用 BPEL 控制台启动该流程。 在可视化流窗口中,可以观察该流程的执行情况。 注意,BPEL 中已经使用了 <invoke> 活动,且图书等级为 4,而原始图书等级 Web 服务返回 5:
为了绝对确保 BPEL 流程管理器已经调用了 Java 类,BPEL 流程管理器控制台窗口将显示以下输出:
05/10/19 19:35:36 Book rating for Business Process Execution Language (1-904811- 18-3): 4.
异常处理
从 BPEL 中调用 Java 资源时,我们需要通过某种方法将 Java 异常传送给 BPEL。 通过 WSIF,可以将 Java 异常映射为 WSDL 故障并使用 BPEL 故障处理程序处理它们。 异常串行化程序负责映射。 Oracle BPEL 流程管理器提供了一个默认的异常串行化程序,您也可以编写自己的自定义串行化程序。
为演示如何将 Java 异常传送给 BPEL,我们将扩展该示例。 首先,使用默认序列化程序,然后使用自定义串行化程序扩展该示例。 执行以下步骤: 在 Java 中定义一个用户异常。 修改 BookRatingJava Java 类以抛出异常。 在 WSDL 中定义相应的故障。 这包括故障消息的 XML 模式类型定义、故障消息以及将 <fault> 消息添加到 WSDL <operation> 描述。 为异常定义 WSIF 绑定。 在 Java 中定义用户异常。 首先,定义一个用户异常,指示已知等级的图书不存在。 您将把该异常命名为 BookDoesNotExistException。 以下代码显示了 Java 中的异常:
package com.oracle.rating;
public class BookDoesNotExistException extends Exception { String detailDesc; String bookTitle;
public BookDoesNotExistException(String message, String detailDesc, String bookTitle) { super(message); this.detailDesc = detailDesc; this.bookTitle = bookTitle; }
public String getDetailDesc() { return detailDesc; }
public String getBookTitle() { return bookTitle; } }
抛出 Java 异常。 然后,修改 BookRatingJava Java 类。 如果图书的 ISSN 等于 999,则将抛出异常:
package com.oracle.rating;
import com.oracle.service.bookrating.*;
public class BookRatingJavaUserException {
public Integer getBookRating (BookDscType book) throws BookDoesNotExistException {
if (book.getISSN().equals("999")) throw(new BookDoesNotExistException("Book does not exist", "Book (ISSN="+book.getISSN()+") does not exist", book.getTitle()));
System.out.println("Book rating for "+book.getTitle()+" ("+book.getISSN()+"): 4.");
return new Integer(4);
} }
在 WSDL 中定义故障。 在下个步骤中,您将在 WSDL 中定义相应的故障。 将把 Java 异常传送给此故障。 由于您将使用默认的异常串行化程序,因此必须使用一个包含以下两个元素的特定复杂类型: faultstring 和 detail。 您将把该复杂类型添加到图书等级 WSDL 的 <types> 部分:
<xs:complexType name="BookDoesNotExistExceptionType"> <xs:sequence> <xs:element name="faultstring" type="xs:string" /> <xs:element name="detail" type="xs:string" /> </xs:sequence> </xs:complexType>
然后,定义相应的消息:
<message name="BookDoesNotExistException"> <part name="exception" type="tns:BookDoesNotExistExceptionType" /> </message>
最后,将故障消息添加到 BookRating 操作签名:
<portType name="BookRatingPT"> <operation name="BookRating"> <input message="tns:BookRatingRequestMessage" /> <output message="tns:BookRatingResponseMessage" /> <fault name="BookDoesNotExistException" message="tns:BookDoesNotExistException" /> </operation> </portType>
默认的异常串行化程序将创建 fault 元素并使用 Exception.getMessage() 返回的内容填充 faultstring,使用 Exception.toString() 返回的内容填充 detail 元素。
为异常定义 WSIF 绑定。 现在,就可以将异常添加到 WSIF 绑定了。 必须为 BookDoesNotExistExceptionType XML 类型定义类型映射,在本文的示例中,该类型将映射为相应的 Java 异常类,即 com.oracle.rating.BookDoesNotExistException。 还必须将故障消息名 (BookDoesNotExistException) 添加到操作映射部分:
<binding name="JavaBinding" type="tns:BookRatingPT"> <java:binding/> <format:typeMapping encoding="Java" style="Java"> <format:typeMap typeName="tns:BookDscType" formatType="com.oracle.service.bookrating.BookDscType" /> <format:typeMap typeName="tns:BookDoesNotExistExceptionType" formatType="com.oracle.rating.BookDoesNotExistException" /> </format:typeMapping> <operation name="BookRating"> <java:operation methodName="getBookRating"/> <input/> <output/> <fault name="BookDoesNotExistException"/> </operation> </binding>
要使该示例可以正常运行,必须编译 Java 类并将它们部署到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录(BPEL 服务器可以在该目录中访问它们)。 最简单的方法是对该示例使用 obant 实用程序:
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>obant
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>SETLOCAL Buildfile:build.xml
CompileJava: [schemac] schemac> parsing schema file 'Z:\WSIF\3_JavaBindingUserExceptionDefa ultSerializer/BookRating.wsdl' ... [schemac] schemac> Loaded schemas from wsdl located at Z:\WSIF\3_JavaBindingUs erExceptionDefaultSerializer/BookRating.wsdl [schemac] schemac> generating XML business document ... [schemac] schemac> compiling XML business documents ... [javac] Compiling 2 source files to C:\OraBPELPM_1\integration\orabpel\syste m\classes
main: [bpelc] validating "Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer\BuyB ook.bpel" ... [bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain s\default\deploy
all:
BUILD SUCCESSFUL Total time: 18 seconds
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>ENDLOCAL
Z:\WSIF\3_JavaBindingUserExceptionDefaultSerializer>
从 BPEL 控制台启动该示例并输入 ISSN 999 后,您将获得以下输出:
自定义异常串行化程序。 如果对 WSDL 故障的结构(由 faultstring 和 detail 元素组成)不满意,并希望对 Java 异常到 WSDL 故障的映射进行更多的控制,可以使用自定义异常串行化程序。 自定义异常串行化程序是一个 Java 类,用于将异常及其属性映射为用于 WSDL 故障的复杂类型。 要了解如何开发自定义串行化程序,执行以下步骤: 定义一个用于 WSDL 故障消息的自定义复杂类型。 编写一个自定义异常串行化程序,将 Java 异常传送给 WSDL 故障。 注册自定义异常串行化程序。 首先,定义 XML 模式自定义复杂类型来表示将包含所有三个异常属性(消息、详细描述和书名)的 Java 异常。 您将在图书等级 WSDL 的 <types> 部分中用该类型替换默认的复杂类型:
<xs:complexType name="BookDoesNotExistExceptionType"> <xs:sequence> <xs:element name="message" type="xs:string" /> <xs:element name="detailDesc" type="xs:string" /> <xs:element name="bookTitle" type="xs:string" /> </xs:sequence> </xs:complexType>
自定义异常串行化程序是一个 Java 类,它定义了 Java 异常如何映射为 WSDL 故障复杂类型。 异常串行化程序必须将 Java 异常属性映射为异常消息的相应 XML 元素并必须实现以下接口:
public interface IExceptionSerializer {
public Element serialize(Throwable ex, String messageName, String namespaceURI); }
对于该示例,您将把自定义异常串行化程序命名为 BookDoesNotExistExceptionSerializer 并扩展现有的 ExceptionSerializer 类。 使用 DOM API,我们将把 Java 异常的三个属性(消息、详细描述、书名)映射为上面提供的 XML 模式类型 (BookDoesNotExistExceptionType):
package com.oracle.rating;
import org.w3c.dom.Element;
import com.collaxa.xml.XMLHelper; import com.oracle.bpel.xml.util.ExceptionSerializer; import com.oracle.bpel.xml.util.IExceptionSerializer;
public class BookDoesNotExistExceptionSerializer extends ExceptionSerializer implements IExceptionSerializer {
public Element serialize(Throwable ex, String messageName, String namespaceURI) { if(ex instanceof BookDoesNotExistException) { BookDoesNotExistException brEx = (BookDoesNotExistException)ex; Element exceptionElement = XMLHelper.createRootElement(messageName, namespaceURI,"tns"); Element messageElement = XMLHelper.createElement("message","tns",namespaceURI); messageElement.setNodeValue(brEx.getMessage()); exceptionElement.appendChild(messageElement); Element detailElement = XMLHelper.createElement("detailDesc","tns",namespaceURI); detailElement.setNodeValue(brEx.getDetailDesc()); exceptionElement.appendChild(detailElement); Element bookElement = XMLHelper.createElement("bookTitle","tns",namespaceURI); bookElement.setNodeValue(brEx.getBookTitle()); exceptionElement.appendChild(bookElement);
return exceptionElement;
} return super.serialize(ex, messageName, namespaceURI); }
}
最后一步是在 Oracle BPEL 流程管理器中注册自定义异常串行化程序。 该步骤将指示 BPEL 流程管理器用您的自定义串行化程序代替默认的串行化程序。 为此,在 bpel.xml 部署描述符中定义 exceptionSerializer 属性:
<partnerLinkBinding name="BookRating"> <property name="wsdlLocation"> BookRating.wsdl </property> <property name="exceptionSerializer"> com.oracle.rating.BookDoesNotExistExceptionSerializer </property> </partnerLinkBinding>
与前一个示例一样,必须编译 Java 类并将它们部署到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录。 使用 obant 实用程序:
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>obant
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>SETLOCAL Buildfile:build.xml
CompileJava: [schemac] schemac> parsing schema file 'Z:\WSIF\3_JavaBindingUserExceptionCust omSerializer/BookRating.wsdl' ... [schemac] schemac> Loaded schemas from wsdl located at Z:\WSIF\3_JavaBindingUs erExceptionCustomSerializer/BookRating.wsdl [schemac] schemac> generating XML business document ... [schemac] schemac> compiling XML business documents ... [javac] Compiling 3 source files to C:\OraBPELPM_1\integration\orabpel\syste m\classes
main: [bpelc] validating "Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer\BuyBo ok.bpel" ... [bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain s\default\deploy
all:
BUILD SUCCESSFUL Total time: 21 seconds
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>ENDLOCAL
Z:\WSIF\3_JavaBindingUserExceptionCustomSerializer>
从 BPEL 控制台启动该示例并输入 ISSN 999 后,您将获得以下输出: 注意不同的故障结构:
自定义 Java 串行化程序。 自定义 Java 串行化程序是一个实现 IJavaSerializer 接口的类。 它必须提供以下两个方法的实现: serialize 和 deserialize。
public interface IJavaSerializer { public Element serialize(Object obj, Class type, String name, String namespaceURI, String prefix, Map classMap) throws Exception; public Object deserialize(Element el, Class type) throws Exception; }
与自定义异常串行化程序相似,必须将编译后的类部署到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录,并在 bpel.xml 部署描述符中定义 javaSerializer 属性:
<partnerLinkBinding name="helper"> <property name="wsdlLocation">HelperService.wsdl</property> <property name="javaSerializer">com.oracle.bpel.xml.util.MyCustomSerializer</property> </partnerLinkBinding>
Oracle 提供了三个现成的自定义串行化程序: Java API for XML Bindings (JAXB)、XML Bean 和 Axis Bean。
JAXB 是 Java Web Services Developer Pack 的一部分,并提供了一个在概念上与 XML fa?ade 相似的方法,但在几个细节方面存在差异。 要将 JAXB 串行化与 Oracle BPEL 流程管理器结合使用,执行以下步骤: 将位于 JWSDP 安装目录(例如,c:\jwsdp-1.5\jaxb\lib)的 JAXB JAR 文件添加到 obsetenv.bat 文件(位于 C:\OraBPELPM_1\integration\orabpel\bin 中)中的环境变量 BASE_OB_CLASSPATH 以及位于 C:\OraBPELPM_1\integration\orabpel\system\appserver\oc4j\j2ee\home\confi 中的 application.xml 文件中。 将 JAXBSerializer.class(参阅示例代码下载)复制到 C:\OraBPELPM_1\integration\orabpel\system\classes\com\oracle\bpel\xml\util 目录。 将 JAXB 编译器 (xjc) 生成的 Java 类复制到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录。 还必须定义 BPEL 项目将使用的串行化程序。 请在 bpel.xml 文件中执行该操作,其中必须定义 javaSerializer 属性:
<partnerLinkBinding name="helper"> <property name="wsdlLocation">HelperService.wsdl</property> <property name="javaSerializer">com.oracle.bpel.xml.util.JAXBSerializer</property> </partnerLinkBinding>
XML Bean 是 Java 到 XML 绑定的另一种方法,最先由 BEA(它将该项目捐赠给 Apache 社区)开发。 与 XML fa?ades 和 JAXB 不同,XML Bean 提供了一个并不对 Java 开发人员完全隐藏 XML 的方法。 相反,它为 Java 接口提供了 getter/setter 方法以及其他方法(带 x 后缀),您可以在需要时通过它们直接操作 XML。 XML Bean 还可以识别 XML Infoset - 当将 XML 转换为 Java 对象时,开发人员可以使用整个 XML Infoset。
与 JAXB 相似,必须执行几个配置步骤才能使用 XML Bean: 将 XML Beans JAR 文件(BEA Weblogic 中的 xbean.jar)添加到 obsetenv.bat 文件(位于 C:\OraBPELPM_1\integration\orabpel\bin 中)中的环境变量 BASE_OB_CLASSPATH 以及 C:\OraBPELPM_1\integration\orabpel\system\appserver\oc4j\j2ee\home\config 中的 application.xml 文件中。 将 XMLBeansSerializer.class(参见示例代码下载)复制到 C:\OraBPELPM_1\integration\orabpel\system\classes\com\oracle\bpel\xml\util 目录。 将 XML Bean 编译器生成的 Java 类复制到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录。 在与 ANT 实用程序 (obant) 一起使用的 build.xml 文件中将路径设置为 xbean.jar。 还必须定义 BPEL 项目应使用 bpel.xml 文件中的 XML Bean 串行化程序:
<partnerLinkBinding name="xmlBeansService"> <property name="wsdlLocation">XMLBeansService.wsdl</property> <property name="javaSerializer"> com.oracle.bpel.xml.util.XMLBeanJavaSerializer </property> </partnerLinkBinding>
第三个用于 Java 到 XML 绑定的著名方法是 Axis Bean。您同样可以将它们用于 Oracle BPEL 流程管理器。
与前两个示例相似,必须执行几个配置步骤才能使用 Axis Bean: 将 Axis Bean JAR 文件(从 Axis 1.2 版开始为 axis.jar)添加到 obsetenv.bat 文件(位于 C:\OraBPELPM_1\integration\orabpel\bin 中)中的环境变量 BASE_OB_CLASSPATH 以及 C:\OraBPELPM_1\integration\orabpel\system\appserver\oc4j\j2ee\home\config 中的 application.xml 文件中。 将 AxisSerializer.zip 中的串行化程序类(参阅示例代码下载)复制到 C:\OraBPELPM_1\integration\orabpel\system\classes\ 目录。 将 Axis Bean 生成的 Java 类复制到 C:\OraBPELPM_1\integration\orabpel\system\classes 目录。 还必须定义 BPEL 项目应使用 bpel.xml 文件中的 Axis Bean 串行化程序:
<partnerLinkBinding name="AxisBeansService"> <property name="wsdlLocation">AxisBeansService.wsdl</property> <property name="javaSerializer"> com.oracle.bpel.xml.util.AxisJavaSerializer </property> </partnerLinkBinding>
用于 EJB 的 WSIF 绑定
现在,您知道了如何通过 WSIF 绑定使用 Java 类代替 Web 服务。 同样,您可以使用 EJB,尤其是无状态会话 bean。 为演示 WSIF EJB 绑定,我们将扩展该示例。 您将在 BPEL 流程中增加一个活动;在调用图书等级服务后,将调用出版商等级服务。 通过 WSIF 绑定,您将使用会话 bean 代替 Web 服务。 假设此会话 bean 已经存在。 为实现此目的,您将执行几个步骤: 为会话 bean 定义 WSDL。 将合作伙伴链接类型添加到 WSDL。 补充 BPEL 流程以调用出版商等级服务。 将 WSIF 绑定添加到 EJB。 用于会话 Bean 的 WSDL。 我们将使用的会话 bean 包含以下远程组件接口:
package com.oracle.ratingSB;
import java.rmi.RemoteException; import javax.ejb.EJBObject;
public interface PubRating extends EJBObject { public int getAvgPubRating (String name) throws RemoteException;
}
您可以看到,它提供了一个名为 getAvgPubRating 的方法,该方法接受一个字符串作为输入并返回一个整数。 在此,您将不显示主接口、实现类以及部署描述符(参见示例代码)。
现在定义相应的 WSDL 文档。该文档非常简单,它定义了两个消息(PubRatingRequestMessage 和 PubRatingResponseMessage)。 它们在操作 PubRating 中分别用作输入和输出。 该操作在 PubRatingPT 端口类型中声明:
<?xml version="1.0"?> <definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://oracle.com/service/pubrating/" targetNamespace="http://oracle.com/service/pubrating/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/" xmlns:ejb="http://schemas.xmlsoap.org/wsdl/ejb/" >
<message name="PubRatingRequestMessage"> <part name="name" type="xs:string" /> </message>
<message name="PubRatingResponseMessage"> <part name="rating" type="xs:int" /> </message>
<portType name="PubRatingPT"> <operation name="PubRating"> <input name="PubRatingRequest" message="tns:PubRatingRequestMessage" /> <output name="PubRatingResponse" message="tns:PubRatingResponseMessage" /> </operation> </portType> </definitions>
添加合作伙伴链接类型。 要使用 WSDL,必须添加合作伙伴链接类型。 该操作是同步的;因此,您只需要一个角色:
<plnk:partnerLinkType name="PubRatingLT"> <plnk:role name="PubRatingService"> <plnk:portType name="tns:PubRatingPT" /> </plnk:role> </plnk:partnerLinkType>
补充 BPEL 流程。 现在,您准备好补充 BPEL 流程来调用出版商等级服务了。 首先,定义一个新的合作伙伴链接:
<partnerLink name="PubRating" partnerLinkType="pbr:PubRatingLT" partnerRole="PubRatingService"/>
然后,将与出版商等级服务的交互作为一个新的作用域添加到图书等级作用域之后。 请注意,您在此只向 BPEL 中添加新功能:
<scope name="RetrievePublisherRating">
<variables> <variable name="PubRatingRequest" messageType="pbr:PubRatingRequestMessage"/> <variable name="PubRatingResponse" messageType="pbr:PubRatingResponseMessage"/> </variables>
<faultHandlers>
<catchAll>
<sequence> <assign> <copy> <from expression="string('Unable to retrieve publisher rating')" /> <to variable="Fault" part="error" /> </copy> </assign>
<invoke partnerLink="Client" portType="buy:ClientCallbackPT" operation="ClientCallbackFault" inputVariable="Fault" /> </sequence>
</catchAll>
</faultHandlers>
<sequence>
<assign> <copy> <from variable="BookPurchase" part="book" query="/book/bkr:Publisher"/> <to variable="PubRatingRequest" part="name"/> </copy> </assign>
<invoke partnerLink="PubRating" portType="pbr:PubRatingPT" operation="PubRating" inputVariable="PubRatingRequest" outputVariable="PubRatingResponse" />
</sequence>
</scope>
添加用于 EJB 的 WSIF 绑定。 WSIF EJB 绑定类似于 Java 类绑定,它们主要的差别在于您必须指定与 WSDL 操作到 EJB 方法的映射相关的细节。
下面显示了出版商等级服务 WSDL 文件中的 WSIF EJB 绑定片段。 您首先定义了类型映射,然后指定了要用于 PubRating 操作的方法 (getAvgPubRating())。 请注意,您已经为参数 (name) 和返回 (rating) 指定了消息部分名称。 您还指定了输入和输出消息名(分别为 PubRatingRequest 和 PubRatingResponse):
<binding name="EJBBinding" type="tns:PubRatingPT"> <ejb:binding/> <format:typeMapping encoding="Java" style="Java"> <format:typeMap typeName="xs:string" formatType="java.lang.String" /> <format:typeMap typeName="xs:int" formatType="int" /> </format:typeMapping> <operation name="PubRating"> <ejb:operation methodName="getAvgPubRating" parameterOrder="name" interface="remote" returnPart="rating" /> <input name="PubRatingRequest"/> <output name="PubRatingResponse"/> </operation> </binding>
在服务绑定中,必须指定 EJB 的其他详细信息,如 JNDI 名、JNDI 提供程序 URL 以及初始语境工厂。 JNDI 提供程序 URL 对每个部署都是特定的。 在本示例中为 ormi://localhost/SessionBean。 可以使用 obant 实用程序在部署时将 [jndiProviderURL] 替换为实际地址(有关详细信息,请查看 build.xml 文件):
<service name="PubRatingPT"> <port name="EJBPort" binding="tns:EJBBinding"> <ejb:address className="com.oracle.ratingSB.PubRatingHome" jndiName="ejb/session/PubRating" initialContextFactory="com.evermind.server.rmi.RMIInitialContextFactory" jndiProviderURL="[jndiProviderURL]"/> </port> </service>
现在,您基本上准备好部署该示例并对它进行测试了。 别忘了将 wsdlLocation 属性添加到 bpel.xml 部署描述符:
<partnerLinkBinding name="PubRating"> <property name="wsdlLocation">PubRatingBinded.wsdl</property> </partnerLinkBinding>
请注意,可以使用此部署描述符添加 EJB 所需的其他属性,如如果 EJB 需要身份验证和授权,则添加 java.naming.security.principal 和 java.naming.security.credentials:
<partnerLinkBinding name="PubRating"> <property name="wsdlLocation">PubRatingBinded.wsdl</property> <property name="java.naming.security.principal">admin</property> <property name="java.naming.security.credentials">welcome</property> </partnerLinkBinding>
要测试该示例,首先必须部署会话 bean,然后部署 BPEL 流程。 再次使用 obant,它将自动执行该过程:
Z:\WSIF\4_JavaBindingEJB>obant
Z:\WSIF\4_JavaBindingEJB>SETLOCAL Buildfile:build.xml
deploySessionBean:
build_ear:
deployIas:
deployOc4j: [java] Notification ==> Application Deployer for SessionBean STARTS [ 2005- 10-19T19:47:00.891CEST ] [java] Notification ==> Undeploy previous deployment [java] Notification ==> Copy the archive to C:\OraBPELPM_1\integration\orab pel\system\appserver\oc4j\j2ee\home\applications\SessionBean.ear [java] Notification ==> Unpack SessionBean.ear begins... [java] Notification ==> Unpack SessionBean.ear ends... [java] Notification ==> Initialize SessionBean.ear begins... [java] Notification ==> Initialize SessionBean.ear ends... [java] Notification ==> Application Deployer for SessionBean COMPLETES [ 20 05-10-19T19:47:19.470CEST ]
bindingWsdl: [copy] Copying 1 file to Z:\WSIF\4_JavaBindingEJB
setJndiUrlOrclej2ee:
setJndiUrlIas:
setJndiUrlOc4j: [echo] Replacing token [jndiProviderURL] by ormi://virtualxp/SessionBean in Z:\WSIF\4_JavaBindingEJB/PubRatingBinded.wsdl
main: [bpelc] validating "Z:\WSIF\4_JavaBindingEJB\BuyBook.bpel" ... [bpelc] BPEL suitcase deployed to: C:\OraBPELPM_1\integration\orabpel\domain s\default\deploy
all:
BUILD SUCCESSFUL Total time: 28 seconds
Z:\WSIF\4_JavaBindingEJB>ENDLOCAL
Z:\WSIF\4_JavaBindingEJB>
从控制台中启动 BPEL 流程后,您将看到已经调用了出版商等级服务:
要绝对确保已经调用了 EJB,请查看 BPEL 服务器控制台窗口;您应看到以下输出:
05/10/19 19:50:51 Tutalii: C:\OraBPELPM_1\integration\orabpel\lib\orabpel.jar ar chive 05/10/19 19:50:54 Avg. publisher rating for Packt Publishing: 5.
从 JDeveloper 中生成 WSIF 绑定
手动编写 WSIF 绑定会非常复杂;因此,Oracle JDeveloper 10.1.3(编写本文时的早期试用版中提供)提供了一个为现有 Java 资源(如 Java 类和 EJB)自动生成 WSDL 和 WSIF 的向导。 这显著降低了从 BPEL 中调用 Java 资源的工作量并使 BPEL 更适用于集成。
如果基于 Java 类或 EJB,则必须启动该向导来创建 Java Web 服务。 以下屏幕截图适用于 Java 类示例:
选择符合 Java EE 1.4 的 JAX-RPC Web 服务类型。 然后,选择要使用的 Java 类或无状态会话 bean。 选中 WSIF 绑定选项(以生成 WSIF 绑定)。 然后,选择 SOAP 消息格式,您可以在其中使用 Document/Wrapped、Document/Literal、RPC/Literal 或 RPC/Encoded 表示形式。 然后,在 XML 类型以及它们的 Java 等价类和相应的串行化程序之间指定自定义映射。 指定 Web 服务使用的命名空间。 最后,选择应通过 WSDL 公开的方法: 该向导提供了其他步骤,您可以在这些步骤中指定可选的类加载程序、JAX-RPC 处理程序类、服务状态(有状态)以及服务使用的其他类。 大多数情况下,您不必指定它们,因此可以按 Finish 按钮完成该向导,并查看所生成的 WSDL,其中您将找到与手动编写的 WSIF 绑定类似的 WSIF 绑定。 有关该向导的详细信息,请参考 JDeveloper 文档。 结论 您已经在本文提供的各个示例中了解到,WSIF 提供了类似 EAI 的功能以及以简单、灵活的方式配置 BPEL 流程的合作伙伴服务的灵活性。 显而易见,WSIF 将 BPEL 的可用范围扩展到现有资源并使 BPEL 成为一种对 SOA 而言更为重要的技术。
Matjaz B. Juric 拥有计算机与信息科学的博士学位。他是 用于 Web 服务的业务流程执行语言 一书 (Packt Publishing) 的作者。 他还是 J2EE Design Patterns Applied、Professional J2EE EAI、Professional EJB 和 NET Serialization Handbook 的联合作者,并曾编写过 Web Services Journal、Java Developer's Journal 以及其他出版物。
|
|
|
[编辑文章 1 次, 最后修改: Pioneer 于 06-6-2 下午4:59] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
第 5 部分:将 BPEL 添加到企业集成混合环境 |
引言回复
回复
|
|
|
作者:Praveen Chandran 和 Arun Poduval
利用 Oracle BPEL 流程管理器的编排功能实现对传统 EAI 中间件起到补充作用的基于标准的业务流程集成。
2005 年 11 月发表 大多数企业都拥有一个迥然不同的应用程序基础架构,其中包含由多个供应商提供的、在不同平台上运行以及使用完全不同的技术创建的各种应用程序。为了解决这些集成难题,TIBCO、webMethods、Vitria 以及 SeeBeyonda 等公司在过去的十年里相继推出了传统的企业应用程序集成 (EAI) 产品。在过去的几年里,许多企业在这些 EAI 解决方案上进行了大量的投资。因此,EAI 领域中的业务集成通常锁定到单个供应商,并且集成组件被紧密耦合在一起。 这些专用集成链接的维护成本为企业带来了沉重的负担。而专门技能的必不可少加重了成本和稳定性方面的问题。此外,对于保护 EAI 中的大量投资的企业而言,破坏并替换现有的 EAI 解决方案并不是一个可取的方法。 BPEL 提供了一个基于标准、与平台无关的解决方案,从而解决了所有这些问题。松散耦合的 BPEL 流程消除了供应商锁定、降低了集成成本并提供了互操作性;此外,它还增加了一个完善的安全性、异常管理和日志记录层。最重要的是,公司可以利用他们的现有基础架构,使其充分发挥效用,并使用 BPEL 对其进行编排。 在“BPEL 指南”的这个部分中,将介绍一个体系结构蓝图,其内容有关利用 Oracle BPEL 流程管理器开发新集成解决方案以及与现有集成解决方案进行连接。其中包含一个案例分析,在该案例分析中,必须将编排好的 Web 服务与基于 TIBCO BusinessWorks 和 webMethods 的现有异构 EAI 解决方案集成在一起。 此外,由于任何完整的业务流程实施都离不开精心设计的错误管理、安全性和记录框架,因此我将介绍 BPEL 作用域和补偿处理程序如何增强此流程的强健性和容错性,以及如何保护 BPEL 流程和相关的服务。 案例研究背景知识 EAI 是使现有应用程序充分发挥效用的强大推动力;可以将现有的中间件流程公开为 Web 服务,然后通过 BPEL 对该 Web 服务进行编排。 下图演示了一个使用 Oracle BPEL 流程管理器编排现有 EAI 接口以及集成新应用程序的通用方法。该方法假设中间件可以将业务流程公开为 Web 服务,并假设应用服务器本身具备 Web 服务接口。 图 1 EAI 中的 Oracle BPEL 流程管理器(完整示意图) 对涉及两个传统 EAI 中间件产品的特定案例研究进行的分析演示了 BPEL 如何在集成两个产品方面起到重要作用。 在许多企业中,在一个客户“记录系统”中进行的更改不会填充到维护客户数据的其他系统。来看这样一个情形:由于各种业务原因,某个企业最终使用两个来自不同供应商的中间件产品,如与 TIBCO BusinessWorks 集成的 Siebel CRM 以及与 webMethods 集成的 SAP R/3(请参见图 2)。 图 2 客户详细信息管理模块和中间件接口 在该模型中,SAP 与 Siebel 系统之间不一致的客户数据可能对客户服务级别产生负面影响,并降低部门和企业收入。而通过通用的客户详细信息管理模块(该模块与 TIBCO 和 webMethods 集成之间建立了多个接口点)可以维护一致性。例如,当 Siebel 收到客户数据时,它将检查该客户是新客户还是现有客户,然后将新数据添加到 SAP 或更新两个应用程序中的现有客户数据。 可以使用现有的中间件工具(TIBCO 和 webMethods)实现此集成,但这样做只会增加专用集成的规模以及出现供应商锁定。这种情况为使应用程序充分发挥效用从而实现一个基于标准、与供应商无关的解决方案提供了良机。 要在 EAI 中实现基于标准的接口,首先是将流程公开为 Web 服务。大多数中间件平台可以通过 Web 服务进行相互通信,但当必须将一组接口服务与相应的业务逻辑粘合在一起时,情况将变得复杂。 可以使用其他中间件流程甚至复杂的 Java 代码来编排 Web 服务。但该流程必须提供以下功能: 并行的 Web 服务调用 异步的 Web 服务调用 服务之间的松散耦合和可移植性 使用基于标准的接口公开整个编排 编排监控如图 3 所示,基于标准的预制编排解决方案(基于 BPEL)可以解决这些问题。 图 3 具有 Web 服务接口的客户详细信息管理模块 将 BPEL 引入到此情形中具有以下潜在的好处: BPEL 支持松散耦合的 Web 服务编排。 可以通过简单的 XML 标记表示业务逻辑(甚至并行流!)。 可以使用简单的 assign (copy 规则)和 invoke 语句在服务之间轻松地传送数据。 可以从其他编排、中间件工具或 Web 应用程序中以独立 Web 服务组件的形式调用客户详细信息管理模块。 可以通过简单的 GUI(如 Oracle BPEL 流程管理器提供的 GUI)管理流程。大多数中间件工具可以将它们的业务流程公开为 Web 服务,这使得将现有集成与 BPEL 编排连接在一起变得更容易。实际上,您可以对相关的所有中间件服务接口使用通用消息格式。 现在,我们来看一下如何使用 Oracle BPEL 流程管理器在 SAP 和 Siebel 之间实现此客户数据同步。 实施客户详细信息管理模块 BPEL 在 SAP 与 Siebel 之间的客户数据同步流程自动化方面起到了帮助作用。实施此 BPEL 流程所涉及的步骤包括: 将 TIBCO 和 webMethods 流程公开为 Web 服务。 使用 BPEL 流程编排 Web 服务。 将异常管理功能添加到 BPEL 流程。 保护 Oracle BPEL 流程管理器、应用程序适配器和 EAI 工具之间的通信。 集中记录和通知流程。第 1 步:将 TIBCO 和 webMethods 流程公开为 Web 服务。客户信息以规范格式表示并包含 SAP 和 Siebel 所需的字段。如果在 TIBCO 和 webMethods 之间传递此一般格式,则这些平台将把规范格式相应地转换为 Siebel 和 SAP 客户记录。 以下是将 BusinessWorks 流程公开为 Web 服务所采取的步骤: 分析由 BusinessWorks 流程提供的功能,以确定它能否作为集成情形中的独立组件。 确定流程输入和输出。 如果 input 和 output 比较复杂,请使用 W3C XML 模式 (XSD) 定义它们。还可以使用 XSD 定义自定义故障模式。 使用 WSDL 模板创建 WSDL,并定义 input 和 output 消息格式(如果需要,将它们与预定义的 XSD 关联)。还可以导入现有的 WSDL。 配置 HTTP Connection 资源。 将 SOAP Event Source 用作第一个活动,随后是业务逻辑,然后使用 SOAP Send Reply 将流程公开为服务。 将 HTTP Connection 资源与 Event Source 关联。 将 WSDL 和 Send Reply 与 Event Source 关联。 处理可能的异常,并使用 SOAP Send Fault 将异常发送至服务客户端。 如果计算机名为 mymachine,则用于 HTTP Connection 资源的端口为 8000;如果流程名为 SOAPService ,则可以使用 URL http://mymachine:8000/SOAPService 访问服务。 从 Event Source 活动的 WSDL 选项卡中获取服务的最终 WSDL。以下是如何使用 webMethods 执行同一操作: 确定 webMethods 流服务能否成为集成情形中的独立组件。 如果要在未经任何验证的情况下从 webMethods 环境的外部调用此 Web 服务,请在 Permissions 选项卡中指定“Execute ACL to Anonymous”。 在 webMethods Developer 中选择 Flow Service,然后从 Tools 菜单中单击 Generate WSDL。 生成 WSDL 文档时,请指定协议 (SOAP-RPC/SOAP-MSG/HTTP-GET/HTTP-POST) 和传输机制 (HTTP/HTTPS)。 定义 WSDL 文档的目标命名空间。 在 Host 域中输入托管 webMethods 集成服务器的计算机的 IP 地址或名称。 在 Port 域中,输入端口号以连接到当前的集成服务器。 将 WSDL 文档保存到本地文件系统。可以在生成的 WSDL 文档中找到服务端点。注意:webMethods 集成服务器根据特定的错误条件发送预定义的 SOAP 故障。如果必须发送自定义 SOAP 故障,则应使用自定义 SOAP 处理器。还应使用包装程序服务或自定义 SOAP 处理器将服务公开为文档/文字 Web 服务。 现在,假设您拥有以下三个 TIBCO Web 服务(使用 TIBCO BusinessWorks 流程和 TIBCO Adapter for Siebel 实现)。 Siebel Add Siebel Update Siebel Query同样,您使用 webMethods 集成服务器和 webMethods SAP R/3 Adapter 部署了以下 webMethods Web 服务。 SAP Add SAP Update该解决方案体系结构可以归纳如下: 图 4 解决方案体系结构 如上所示,BPEL 流程通过 EAI 工具中转前端调用中心与后端 SAP 和 Siebel CRM 应用程序之间的转换。 以下是一些将中间件流程公开为 Web 服务的最佳实践: 尽可能遵守 WS-I 标准。 尝试在具有文字编码的“文档”样式中公开服务。如果该方法不可用,请使用具有文字编码的“rpc”样式。尽管两者均为 WS-I 推荐的方法,但您将发现文档样式更为简单(至少在您为 BPEL assign 活动创建 copy 规则时是这样)— 使用 rpc 样式,所有模式元素全部作为单独的消息部分出现,而使用文档样式,整个消息在一个部分中传送。可以使用单个 copy 规则复制整个模式,从而降低开发工作量,并在最终的 WSDL 文档中验证样式和编码。 避免使用 SOAP 编码;WSDL 的 SOAP Action 属性是一个空字符串。 确保中间件使用 WSDL 1.1 描述 Web 服务的接口。 使用 SOAP 的 HTTP 绑定。 确保所有用于描述此模式的 XSD 都符合 W3C 建议的 XML 模式规范。例如,全局元素声明不应使用对其他全局元素的引用;即,使用 type 属性而不是 ref 属性。 第 2 步:编排 Web 服务。将中间件流程公开为 Web 服务后,可以使用 Oracle BPEL 流程管理器(具有强大的、基于 GUI 的 BPEL 创作接口)对它们进行编排。 我们曾在前面提到过,客户详细信息管理模块的一个重要方面是它同步 SAP 与 Siebel 之间的客户数据。该流程是在 BPEL 设计器中以可视化方式创建的,如下所示。 图 5 使用 Oracle BPEL 流程管理器编排客户详细信息模块 以下是此流程概要: receive 活动接受客户详细信息(企业模式)。 通过 assign 和 invoke(Siebel Query 服务)活动将详细信息传递给 Siebel。 通过 pick 活动,使用 Siebel Query 结果确定客户是现有客户还是新客户。 如果客户是新客户,则调用并行执行,并通过 flow 活动在 Siebel 和 SAP 中添加该客户;否则,另一个并行流将在这两个应用程序中更新客户详细信息。 如果 SAP 中不存在客户详细信息,则 Siebel Query 将从 Siebel 中获取这些字段。该 SAP 字段以及其他要更新的字段可能通过一组 assign copy 规则传递给 SAP Update。 通过使用显式 reply 活动返回 Customer Update/Addition 的最终状态。如您所见,业务流程的两侧是用于添加和更新 Siebel 和 SAP 数据的 Web 服务。这些在第 1 步中设计的 Web 服务从内部调用 EAI 流程。 此 BPEL 流程满足了客户管理的业务需要,但它仍无法处理异常。例如,如果在 Siebel 中成功添加了客户,但在 SAP 中添加失败,情况将会怎样?为解决此问题,您需要在业务流程中启用异常管理。 第 3 步:添加异常管理功能。通过异常管理,BPEL 流程可以处理错误消息或由外部 Web 服务返回的其他异常,并可以生成错误消息以响应业务或运行时故障。 下表包含了为使客户管理 BPEL 流程更牢靠而需要处理的异常。
编号 情形 解决方案 1 Siebel Query 失败 终止流程,然后重试 2 Siebel Add 失败;SAP Add 成功 进行补偿以删除 SAP 记录,然后重试 3 Siebel Add 成功;SAP Add 失败 正常流;重试 4 Siebel Add 失败;SAP Add 失败 正常流;重试 5 Siebel Update 成功;SAP Update 失败 正常流;重试 6 Siebel Update 失败;SAP Update 成功 进行补偿以回滚 SAP 记录,然后重试 7 Siebel Update 失败;SAP Update 失败 正常流;重试 除了情形 1、2 和 6(如下所示)以外,无需对其他情形进行显式处理即可保持数据一致。 必须跟踪 Web 服务的状态以捕获异常并采取相应的操作。在介绍如何处理情形 1、2 和 6 之前,我们先了解一下如何跟踪特定 Web 服务的状态。 整个 BPEL 流程具有以下回复模式属性: Siebel_Add_Status Siebel_Update_Status SAP_Add_Status SAP_Update_Status 所有这些属性均可以包含值 Failed、Success 或 NA,BPEL 流程可以在各个位置设置这些值。要设置 Failed 状态,流程可以捕获由目标 Web 服务引发的 SOAP 故障(对每个 invoke 活动使用捕获处理程序)。当发生任何故障时,调用客户详细信息管理模块的客户端可以重新发送详细信息。 下面,我们将了解一下异常的管理方法: 情形 1 如果 Siebel 查询本身失败,应终止流程,且调用客户端可以重试。 情形 2 当客户详细信息插入在 Siebel 中失败,但在 SAP 中成功时(它们是同时发生的),数据将无法保持一致性。此外,在进行重试时,可能会出现以下问题: 如果尝试调用 BPEL 流程以将客户详细信息插入到 Siebel 中,则客户详细信息可能在 SAP 中重复。 如果尝试调用 BPEL 流程以更新客户详细信息,则 Siebel 中的更新将失败,这是因为 Siebel 中没有相应的记录。要处理以上情况,必须在尝试之前使用另一个具有 BPEL 补偿处理程序和作用域的 webMethods Web 服务删除 SAP 客户记录。 作用域和补偿活动是重要的 BPEL 开发工具。作用域是其他活动的容器和上下文;作用域活动类似于编程语言中的 {}block。作用域通过对功能结构进行分组简化了 BPEL 流,并提供了故障、事件和补偿处理程序以及数据变量和关联集。 Oracle BPEL 流程管理器提供了两个补偿处理结构: 补偿处理程序 — 该处理程序是实现回滚的业务逻辑。可以为流程和作用域定义处理程序。 补偿活动 — 该活动对已经成功完成的内部作用域活动调用补偿处理程序,并且只能从故障处理程序或另一个补偿处理程序的内部调用它。异常是通过捕获处理程序在作用域级捕获的。捕获处理程序反过来使用补偿活动调用内部作用域的补偿处理程序。补偿处理程序将执行所需的回滚。 返回到本文的示例,假设 BPEL 流程有两个作用域:一个内部作用域和一个外部作用域。SAP Add 和 Siebel Add 服务的调用活动源自外部作用域,但只有 SAP Add 源自内部作用域。补偿处理程序可以与内部作用域关联,且补偿处理程序调用 SAP Delete 服务的活动。 必须将捕获块与外部作用域关联,以便可以捕获由 BusinessWorks Web 服务发送的 SiebelAddfault。每当发生 SiebelAddfault 时,补偿活动将补偿内部作用域并删除 SAP 客户记录。请注意,仅当内部作用域中的所有活动全部成功时,补偿才会成功。 图 6 显示了经过修改的、具备作用域和补偿处理程序的 BPEL 流程。 图 6 用于删除 SAP 客户记录的补偿逻辑 情形 6 如果 Siebel 更新失败而 SAP 更新成功,则事务也会失败。这将导致数据不一致;因此,必须使用补偿逻辑回滚 SAP 中发生的事务。补偿处理程序与 SAP Update 服务关联,并将调用 SAP Rollback 服务。对 BPEL 流程的修改将遵守上面给出的指南。 显式调用补偿活动这一功能是 BPEL 的错误处理框架的基础。与传统的 EAI 补偿机制不同,BPEL 提供了一个标准化的回滚处理方法。 创建了 BPEL 流程以编排 TIBCO 和 webMethods Web 服务后,让我们来了解一下如何使 BPEL、适配器与 EAI 工具之间的通信更安全。 第 4 步:安全的业务通信。可以在两个层次实现安全性:出站(调用安全的 TIBCO 和 webMethods 服务)和入站(保护 BPEL 流程)。 出站安全性 需要保护 TIBCO 和 webMethods 服务以防止未授权的访问。Oracle BPEL 流程管理器支持用于调用外部服务的 HTTP 基本身份验证和 WS-Security 身份验证。本示例着重演示如何使用 HTTP 身份验证保护 TIBCO 和 webMethods 服务与机制,以从 BPEL 流程中调用它们。 在 TIBCO BusinessWorks 和 webMethods 集成服务器中部署的 Web 服务支持 HTTP 基本身份验证。设计 TIBCO Web 服务时,请选中 SOAP 事件源活动的 Transport Details 选项卡上的 Use Basic Authentication 复选框。使用 TIBCO Administrator 部署 Web 服务时,可以设置不同用户/角色的服务访问级别。使用 webMethods Developer 设计 Web 服务时,可以设置不同操作的 ACL(访问控制列表)。 如果在部署 TIBCO 和 webMethods 服务时使用基本身份验证,服务将在每次调用时进行此验证,并且应由 BPEL 流程传递证书。可以通过设置两个合作伙伴链接属性完成该任务:httpUsername 和 httpPassword。可以按如下所示静态设置这两个属性。 图 7 设置 httpUsername 和 httpPassword 要动态传递证书,请使用 copy 规则。 此外,还可以使用 WS-Security 保护 TIBCO 和 webMethods 服务。BPEL 流程可以将 WS-Security 身份验证标头传递给 WS-Security 保护的 Web 服务。您需要在服务的 WSDL 文档中定义该服务支持的 WS-Security 标头。然后,可以将这些标头字段作为 BPEL 流程中的变量(就像消息主体数据元素一样)进行处理。可以在 HotelShopFlow 示例(可以从 OTN 下载 )中找到有关 WS-Security 身份验证的更多详细信息。 入站安全性 可以使用 HTTP 身份验证防止未授权用户调用 BPEL 流程;还可以为不同的 BPEL 流程设置不同的证书。 要实现此安全性,必须在应用服务器级别启用 HTTP 基本身份验证。随后,可以在 BPEL 流程中提取证书并以合作伙伴链接属性的形式传递给 TIBCO 和 webMethods Web 服务。 有关 BPEL 安全性的更多详细信息,请收听 OTN 上的 “保护 BPEL 流程与服务” 网络研讨会。 第 5 步:集中记录和错误处理。尽管业务流程现在比较安全和强健,但在其中构建记录和通知功能同样重要。构建一个集中的记录和错误处理框架将使应用程序更强健,增强可重用性并降低开发成本。可以从 BPEL 流程和中间件中使用 Web 服务构建这样的框架。通过 Oracle BPEL 流程管理器,您可以使用文件适配器将记录添加到该服务中,并要求在出现错误时发送电子邮件通知。 可以将以下示例模式用于此框架: 模式元素 说明 ROLE ERROR、DEBUG、WARNING 以及 INFO 等角色 CODE 错误代码 DESCRIPTION 错误描述 SOURCE 错误源 EMAIL 必须将通知发送到的电子邮件 ID 可以将该 BPEL 流程公开为异步单向 Web 服务,这将使该服务的客户端继续运行,而不会出现任何延迟。下面显示了集中的记录和通知流程 LogNotify。 图 8 使用 Oracle BPEL 流程管理器的记录和错误处理框架 如图 8 所示,LogNotify 流程执行以下操作: 接收要记录的来自外部流程的信息 调用 Log Service ,以将该数据写入日志文件。为此,Log Service 将利用文件适配器。 如果记录成功,该流程将完成。此外,如果 ROLE 字段包含 ERROR,则该服务将通过电子邮件通知相关用户。从收到的原始消息中检索电子邮件信息(参见示例模式)。 如果通知失败,将通知错误记录到文件后,该流程将结束。主 BPEL 流程中的每个调用活动可以具有单独的 try-catch 块。中间件流程发送的 SOAP 故障(甚至可能包含最终应用程序引发的异常)在 catch 块中处理,并发送到通用记录和错误处理框架。 图 9 显示了如何在 Siebel Add 失败时调用 LogNotify 流程。 图 9 从客户详细信息管理模块中调用记录和错误处理框架 结论 集成市场充斥着强大的 EAI 产品,许多集成都是通过这些产品完成的。BPEL 是使这些现有的 EAI 解决方案充分发挥效用的唯一选择。通过将现有中间件流程公开为 Web 服务并使用 Oracle BPEL 流程管理器对其进行编排,企业可以开始着手制定 SOA 方面的决策。 Praveen Chandran 就职于 Infosys Technologies Ltd.,负责 EAI 方面的工作,并专注于 TIBCO、Vitria 和 Web Services/BPEL 等平台和技术。 Arun Poduval 也就职于 Infosys Technologies Ltd.,负责 EAI 方面的工作,并转注于类似技术。
|
|
|
[编辑文章 1 次, 最后修改: Pioneer 于 06-6-2 下午4:58] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
第 6 部分:构建富互联网应用程序以监控工作流和流程 |
引言回复
回复
|
|
|
作者:Doug Todd
通过扩展 Oracle BPEL 流程管理器 API 创建实时工作流和高级流程活动监控仪表板。
为了提高运营效率,越来越多的企业正在将其关键业务流程进行自动化。但是,即使流程实现了自动化,也会因为以下两个重要原因而需要手动交互:使流程前进到下一步(工作流)以及为最终用户提供实时流程可见性(流程监控)。 来看一个开立新银行帐户的业务流程。首先,客户提供必需的详细信息(姓名、地址、SSN、起存额)以开立帐户。该流程启动后,客户将需要跟踪请求的状态并响应银行发出的任何其他查询。该流程需要工作流来实现客户参与,并需要流程监控以便客户可以跟踪请求状态。 Oracle BPEL 流程管理器简化了基本的工作流功能和流程活动监控。但同样重要的是,通过扩展其丰富的 API 接口以便与流程、实例和工作流交互,可以构建一个支持高级工作流和流程活动监控的富互联网应用程序 (RIA)。该高级工作流功能可以使用户和流程之间实现无延时的通信,而高级流程活动监控可以将实时流程状态信息传输给工作流,以便采取相应的操作。 在“BPEL 指南”的这个部分中,我将介绍一个需要实时工作流和高级流程活动监控功能的简单业务情形。然后,您将了解基于 Macromedia Flash 的 RIA 的体系结构(它利用 BPEL 流程管理器 API 满足这些目标),然后了解 RIA 如何初始化流程并集成工作流。您还将学习到如何以可视化方式描绘可用的流程路径,以及当前实例实际采用的流程路径。(该功能对于回顾检查流程非常重要。)最后,还将向您简要介绍如何使用 API 接口跟踪审计线索。 RIA 背景知识 RIA 融合了 Web 应用程序与传统的桌面应用程序,它通常是使用 JavaScript、Flash、Java Applet、XML 用户界面标记语言 (XUL)、可扩展应用程序标记语言 (XAML)、JavaServer Faces 以及 Swinglets 等“交互式”技术构建的,并经常使用异步 XML 和 JavaScript (AJAX) 方法。RIA 可以潜在地提高联机应用程序的可用性和效率,还有开发人员的生产效率。根据 Gartner Research,截止到 2010 年,至少 60% 的新应用程序开发项目将包含某种 RIA 技术。 本文的示例包含一个 BPEL 工作流界面和流程监控控制台,用于为最终用户提供一个统一的、功能丰富的仪表板。请注意,必须将该应用程序与 Oracle BPEL 控制台或真正的业务活动监控 (BAM) 加以区分;尽管存在某种程度的功能重叠,但 RIA 的目标用户群与后两个应用程序的目标用户群截然不同。BPEL 控制台更适合于调试、部署和维护流程实例的管理员和开发人员,而 BAM 适合于要度量关键性能指标 (KPI) 然后采取措施改进流程的流程所有者(管理人员、LOB 经理等)和 IT 经理。而本文描述的示例 RIA 应用程序是针对以下最终用户而设计的:要跟踪特定业务交互的状态并且不关心 KPI 或流程改进的客户、合作伙伴或供应商。 示例流程 示例业务流程“新帐户请求”是一个多企业流程,用于为金融服务中介、其金融合作伙伴(保险公司及其财务顾问)、共同基金公司和结算所创建帐户。本文将着重介绍该流程的前两个步骤。 该流程接受客户的 SSN,然后从数据库中提取并显示客户信息(名称、地址)。 客户验证该数据、添加存款帐户,然后单击 Submit。显而易见,客户将需要一个工作流界面来输入 SSN、验证姓名和地址并输入存款帐户。此外,他们需要能够以可视化方式监控请求的进度。 在下个部分中,我将概述有关构建此应用程序的开发方面的问题。稍后,您将看到新帐户业务流程如何使用此应用程序执行。 构建应用程序 正如前面所介绍的,您将出于以下两个主要目的设计该应用程序: 提供一个丰富的统一用户界面,以便用户跟踪流程状态并在需要时提供输入(RIA 前端) 提供高级流程监控(BPEL 流程管理器 API 后端) RIA 前端。RIA 用户界面是应用程序的“外观”;它运行并管理新帐户业务流程。该表示层是使用 Macromedia Flex 技术和 ActionScript 脚本语言构建的。它接受用户输入,并将其传递给 BPEL 流程。它还显示流程的当前状态。 下面的图 1 显示了新帐户业务流程的 RIA 前端。 图 1 新帐户流程的 RIA 前端 下面,我们将了解它的四个主要组件及其重要功能: 工作流栏: 工作流栏 (Workflow Bar) 使用户可以在业务级别查看新帐户流程中的工作流步骤。工作流栏中的每个步骤都在 BPEL 面板中进行了分解。 BPEL 面板:BPEL 面板 (BPEL Panel) 提供了新帐户流程中每个步骤的分解视图。该面板动态读取给定流程实例的流程模型和实例审计线索,以将可用的流程路径与当前实例实际采用的路径相结合。该面板还轮询审计线索以确定哪个操作已经挂起,并以可视化方式描述当前流程此时此刻所处的位置。可以单击以前执行的流程的任何节点以查看它们相应的有效载荷。该功能为操作和合规经理提供了对当前流程的过去、当前以及潜在的未来状态的实时可见性。 工作流表单:工作流表单 (Workflow Forms) 对应于新帐户 BPEL 流程中的工作流步骤。该 Flex“视图系列”与业务流程的审计线索通信,并更改视图系列表单以匹配 BPEL 流程的环境。 区域:区域 (Zones) 提供警报和反馈以帮助工作流和流程活动用户执行他们相应的作业(此处不予介绍)。 这些面板提供了卓越的可用性体验并与 BPEL API 交互。下面,我们将了解利用哪些后端 API 函数执行 RIA 前端。 BPEL 流程管理器 API 后端。BPELService 类简化了 RIA 前端与 BPEL 流程管理器 API 中的流程活动监控功能之间的交互。如图 2 所示以及随后的表中的描述,BPELService 将 BPEL 流程管理器 API 中的五个接口用于流程、流程实例和任务,以实现管理和监控支持工作流的流程活动。 图 2 UI 到 BPELService 功能的映射 接口 使 用户能够... IDeliveryService 从 BPEL 流程域上部署的流程中调用实例 IBPELProcessHandle 浏览 BPEL 流程域上部署的 BPEL 流程 IInstanceHandle 对 活动实例执行操作 ITask 与 流程域中已经实例化的任务交互 IWorklistService 搜索 并完成已经从流程域中实例化的任务 您已经了解了 RIA 和 BPELService 的基本组件,下面将介绍它们如何协同提供丰富的最终用户体验。 运行新帐户流程 如前所述,首先向客户显示工作流面板中的输入屏幕以输入 SSN。当用户单击 Submit 时,将使用 ActionScript 创建一个“新帐户应用程序”XML 文档,并通过 Flex 的远程对象体系结构将其传递给 BPELService 服务器端 Java 类。(这使 Flex 能够直接与 BPELService 等 Java 对象进行通信。)Java 组件使用 IDeliveryService 接口的实例初始化 BPEL 流程。随后,如下所示,initiateProcess Java 方法将新创建的业务流程实例的实例引用 ID 返回给 Flex 客户端。随后的操作中使用此引用 ID 将相应的业务流程实例作为目标。 /** * This function initiates an instance of a BPEL PM process based on the * process name.The function sets the function id and the reference id for * future use. * * @param xmlRequest * is the initiating request message for the process * @param strBusinessProcess * the business process name * @return the initiating response message for the process */ public String initiateProcess(Document xmlRequest, String strBusinessProcess) {
System.out.println("Initiate" + strBusinessProcess); /* * This interface allows users to invoke instances from processes * deployed on a BPEL process domain. */ IDeliveryService deliveryService = getDeliveryService(); /* * Construct the normalized message and send to Oracle BPEL process * manager */ NormalizedMessage nm = new NormalizedMessage(); nm.addPart(PAYLOAD, xmlRequest.getDocumentElement());
NormalizedMessage responseNm = null; try { responseNm = deliveryService.request(strBusinessProcess, PROCESS, nm); } catch (Exception e){ e.printStackTrace(); throw new RuntimeException("Could not initialize process."); } Map payload = responseNm.getPayload(); Document xmlResponse = getXMLDoc(XMLHelper .elementToString((Element) payload.get(PAYLOAD))); /* * Sets the Instance reference ID for interagating active BPEL * instances. */ setInstanceReferenceId(strBusinessProcess, xmlResponse);
return XMLHelper.elementToString(xmlResponse.getDocumentElement()); } 启用工作流。 如图 3 所示,通过 BPEL 流程从外部系统检索客户数据并将其显示在工作流面板中。然后,用户验证数据,输入存款额,之后单击 OK。 图 3 验证客户数据和输入存款额 工作流功能基于 BPEL 流程管理器提供的 ITask 和 IWorklistService 接口。RIA 将 IWorklistService 中的任务与完成给定任务所需的工作流屏幕相关联。当发生相应的表单验证时,用户界面对 completeTask 方法进行远程对象调用(如下所示),以将 UI 中捕获的数据发送至 BPEL 流程进行进一步的处理。 /** * This function gets the use input from workflow zone, relates it to a task * and completes the task.The function uses instance reference id for * identifying process instance. */
public String completeTask(String strInstanceReferenceID, String strActivityLabel, Document payload) { System.out.println("completeTask-" + strInstanceReferenceID + "-" + strActivityLabel); String strStatus = "OK"; try { IWorklistService worklist = getWorklist(); // get task reference ITask task = getTask(strInstanceReferenceID, strActivityLabel);
// set task payload task.setAttachment(payload.getDocumentElement());
worklist.completeTask(task);
} catch (Exception e){ e.printStackTrace(); strStatus = ERROR_STRING; } return strStatus; } 以上代码将任务特定的数据置于 ITask 接口提供的任务附件中。该接口不但将相关的数据发送回 BPEL 流程,而且还将该数据置于 BPEL 流程审计线索中。 下面,我将介绍 RIA 应用程序的另一个重要方面:流程监控。 监控流程活动 以上介绍的前两个步骤(初始化流程并启用工作流)中,流程状态通过 IProcessHandle 和 IInstanceHandle API 接口以可视化方式进行了更新。 Oracle BPEL 控制台提供了一个基于 Web 的界面,用于部署、管理和调试 BPEL 流程。它是一个使用 JSP 页面和 servlet(调用 BPEL 流程管理器 API)设计的管理工具。因此,您可以轻松地使用 API 开发您自己的 RIA 控制台,以提供一个业务级别的流程监控界面。 该控制台为特定的流程实例提供了可视反馈,甚至还提供了指向与流程中给定步骤关联的审计线索数据的链接。而 RIA 控制台的主要优势在于它能够执行实际分析与计划分析。该控制台显示流程在其执行过程中可能采取的所有可能的步骤;它还显示在执行过程中实际采用的路径。用户可以单击任何流程节点来检索 BPEL 有效荷载,并在对话框中显示该有效荷载信息。 由于提供了以可视化方式描绘的理想与实际流程路径以及在有效荷载级别进行下钻这一功能,最终用户可以自行分析流程并标识故障点,而无需 IT 人员的参与。图 4 描绘了实际与理想流程路径分析的示例;“实际”路径用绿色标记。 图 4 实际与理想的流程路径分析 下面,我们将介绍如何显示流程以实现此分析,以及如何检索审计线索数据并在 RIA 应用程序中以可视化方式描绘它。 显示流程 Flex BPEL 面板组件调用 IProcessHandle 接口来检索整个业务模型的 XML 表示。BPEL 面板使用 IInstanceHandle 接口收集当前实例审计线索的 XML 表示。随后,BPEL 面板将比较并合并这两个 XML 表示,以创建一个可以描述整个模型以及所采用路径的用户界面。 Flex 尤其擅长于通过它的原生 XML 功能执行此类操作。Flex 可以使用 Flex repeater 控件与 ActionScript 的组合轻松地合并两个 XML 表示。组合使用时,它们能够将 XML 转换为数组,然后利用固有的数组处理功能简化 XML 的合并。 由于流程模型 XML 包含所有可能的节点,因此它实际上充当了 BPEL 面板的基础。在流程模型的每个步骤中,都将比较流程模型 ID 与审计线索模型 ID。当流程与审计的 ID 匹配时,该节点的结果将从审计模型复制到流程模型。确定采用哪个路径与查询模型中哪些节点具有与其关联的实例数据一样简单。 以下代码片段显示了 getProcessModel 和 getInstanceAuditTrail 方法。 getProcessModel 方法 /** * This function gets the debugger XML model of a given BPEL process. * * The function returns the xml model. * * * @param strProcessID * the business process name. * @return the xml process model. */ public String getProcessModel(String strProcessID) { System.out.println("getProcessModel - " + strProcessID); String strProcessModel = ""; try { IBPELProcessHandle process = getLocator().lookupProcess( strProcessID); // Returns the debugger XML model of this BPEL process. strProcessModel = process.getProcessModel(); } catch (Exception e){ e.printStackTrace(); strProcessModel = ERROR_STRING; } return strProcessModel; } getInstanceAuditTrail 方法 /** * This function gets the XML audit trail of a given BPEL process. * * The function returns the xml model. * * * @param strProcessID * the business process name. * @return the xml process model. */ public String getInstanceAuditTrail(String strInstanceReferenceID) { System.out.println("getInstanceAuditTrail - " + strInstanceReferenceID); String strResponse = ""; try { IInstanceHandle instance = getInstance(strInstanceReferenceID); // Returns the XML representation of the audit trail of this // instance. strResponse = instance.getAuditTrail(); } catch (Exception e){ e.printStackTrace(); strResponse = ERROR_STRING; } return strResponse; }查看审计线索数据 审计线索数据可用于已经执行的每个流程节点。该功能类似于 BPEL 控制台中相应的功能。通过 Flex 用户界面,可以访问在用户界面中选择的流程节点的详细信息数据(请参见图 5)。 图 5 查看有效载荷信息 可以使用以下 ActionScript 2.0 代码提取审计线索数据: bpelObject.bpelDetails = eventData.event.details.data; Flex 界面通过跟踪审计线索中的活动来轮询当前业务流程状态的更改,从而以可视化方式描绘业务流程中哪个步骤已经挂起。检测到更改时,Flex 应用程序将使用远程调用请求一个新的当前实例跟踪来检索审计线索。随后,使用此实例跟踪在与每个 BPEL 流程用户任务关联的输入屏幕上显示数据。Flex 客户端输入屏幕使用活动关联 ID 与相应的 BPEL 流程步骤关联。 结论 业务流程的价值在于它能够提供优秀的流程性能可视化描绘并支持任务集成。从美学角度而言,本文描述的应用程序对于最终用户极具吸引力。 正如我所演示的,RIA 可以提供一个松散耦合的表示层方法来提交新的 SOA 应用程序。通过组合 RIA 前端与 SOA 后端,企业可以降低互联网应用程序的管理和部署成本。 Doug Todd 是 Enterra Solutions(位于 Yardley, Pa)的 CTO。他曾就职于多家大公司,并在系统体系结构、应用程序体系结构、系统集成以及应用程序集成方面具有 20 多年的工作经验。Todd 负责 Enterra 的总体 IT 战略和战术实施、企业信息体系结构以及技术产品供应。
|
|
|
[编辑文章 1 次, 最后修改: Pioneer 于 06-6-5 下午5:18] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
|
|
作者:Jerry Thomas
通过 XQuery 将数据库中存储的参数转换为 BPEL XML 定义文件来即时生成 BPEL 流程。 在本指南的第 3 部分中,您学习了如何使用端点引用操作合作伙伴链接,以实现动态的 BPEL 流程。该方法对于构建不受合作伙伴关系更改影响的流程确实很有用。但在许多流程中,除合作伙伴链接以外的各种其他变量也可能需要动态更改。 假设某个公司设计了一个用于管理企业房地产和设备的工作场所管理解决方案,帮助客户回答以下类型的问题: 不同业务部门的空间使用情况如何?业务单元如何最有效地共享空间? 房地产租赁何时到期?通过了解公司的发展规划,怎样重新商议租赁事项? 如何进行最佳的规划和决策,将业务部门搬迁到其他楼层或扩大到街道对面的建筑中? 工作场所管理解决方案实现了业务流程的自动化,如跟踪办公室隔间是否被占用,如果该空间在三个月内保持闲置状态,则取消它与业务部门的关联。由于公司针对不同的客户部署此流程,因此必须根据客户的业务需要调整该流程 - 某个公司可能倾向于在将隔间与业务部门分离之前向物业经理发送电子邮件,而另一家公司可能倾向于等待更长一段时间,然后再采取行动。 这种情况下,为每个客户从头创建一个业务流程将需要花费大量的时间、金钱和资源。而且创建可重用的业务流程将需要深入了解 BPEL 结构。 相比之下,自适应业务流程可以根据特定企业不断变化的需要进行快速的定制,更快实现自动化、降低开发成本并缩短投放市场的时间。在该方法中,您将隐藏 BPEL 的复杂性,并使分析人员能够建立尽可能贴近“实际生活”的业务流程模型。 但该流程需要自定义业务流程设计器,利用它分析人员可以不用考虑 BPEL 的复杂性,从而专注于业务流表示。该自定义设计器将流程定义存储到数据库中。每当需要更新该流程时,业务分析人员便可以使用自定义设计器相应地更新该流程。 实际上,一旦将流程定义加载到数据库中以后,便可以在数据库中“即时”构建 BPEL 流程。随后,可以动态部署这个新构建的业务流程。 Oracle BPEL 流程管理器是该方法的理想工具;它能与第三方设计器很好地融为一体,并能够动态部署 BPEL 流程。例如,我所在的公司 CenterStone Software 便利用该方法提供一个解决方案,以快速实现工作场所业务流程的自动化并管理企业房地产和设备。我们的 eCenterOne 应用程序使用 Oracle BPEL,使物业经理能够快速开发和部署自定义业务流程。 在本文中,我将介绍自定义 BPEL 设计器如何将流程定义存储到数据库中。了解用于存储定义的数据库模式后,您将使用 XQuery 和Saxon XQuery 分析器从示例业务流程中实时创建一个 BPEL 文件。最后,您将学习如何使用 Ant 脚本动态部署该流程。 方法 正如我在前面介绍的,即时构建流程有许多优势。图 1 显示了实时创建的业务流程的整个生命周期。 图 1 业务流程生命周期 构建实时流程分为几个步骤:分析人员使用自定义设计器以图形方式建立业务流程模型。 自定义设计器将流程定义存储到数据库中。 BPEL Generator 读取并验证流程定义。然后,它利用数据库表示以及用于部署的相关文件生成 BPEL XML 文件。 BPEL 流程动态部署到 Oracle BPEL 流程管理器服务器上。我们将通过以下业务案例来完成每个步骤。 业务案例 来看一下前面介绍的房地产管理业务流程。该“隔间管理”业务流程涉及以下活动: 当办公室隔间被占用时启动业务流程(空间的 EmployeeCount 字段设置为 0)。 等待三个月(如果空间的 EmployeeCount 设置为 > 0,则退出该流)。 向物业经理发送电子邮件,表明该空间不再由其原来的业务部门控制。 更新该空间,将其与原属业务部门脱钩。创建流程。创建流程是即时构建流程的第一步。通常,使用 Oracle Designer 或 Eclipse Designer 建立流程模型并且自动生成 BPEL 文件。 在我们的方法中,您将使用自定义设计器替换传统的 IDE。您将在数据库内部存储定义,而不是直接创建 BPEL 文件。 图 2 显示了如何在设计器中建立示例业务流程模型。 图 2 自定义流程设计器中的隔间管理业务流程 正如我在前面介绍的,Oracle BPEL 流程管理器引擎具备与提供的任何设计器/工具(后者可以生成有效的 BPEL 文件)集成的独特功能。 将定义存储到数据库中。创建业务流程后,下一步是将定义存储在数据库内部。数据库模式必须具备充分的灵活性以存储复杂的流程,并可以使用多个 BPEL 结构(如 flow、pick、invoke 和 scope)重新创建 BPEL 流程。 假设您设计了一个包含业务流程设计信息(对应于自定义设计器提供的实际视图)的数据模型。当业务分析人员使用设计器创建业务流程时,定义业务流程结构的信息将保存到数据库。注意,Oracle BPEL 流程管理器在部署(稍后将对其进行详细介绍)前不起作用。 图 3 包含用于将流程设计持久保存在数据库中的数据模型的高级 UML 视图。 图 3 用于存储隔间管理流程定义的简化数据模式
WorkflowProcess 对象存储流程设计;它包含参数和节点,用于定义流程中的活动的序列和类型。各种 WorkflowNode 对象是设计器支持的不同类型的流程活动的设计时产物。注意,它们并不是 BPEL 结构,而是随后映射到通常多个 BPEL 活动的自定义结构。使用自定义设计器部署后,CubeManagement 流程详细信息将按如下所示存储到数据库中。
WorkflowProcess 表
Name ID
CubeManagement 1
WorkflowParameter 表
WorkflowProcess_ID Name Type
1 CubeParam Space
WorkflowNode 表
WorkflowProcess_ID NodeId NextNode Type E-mail Parameter_ID UpdateField UpdateValue WaitTime 1 1 2 Start 1 2 3 Wait 3 months 1 3 4 Message max@big.com 1 4 5 Update 1 businessUnit null: 1 5 Null End
BPEL Generator 读取这些表以动态生成 BPEL 文件。下个部分介绍了该过程。
动态部署 BPEL
生成 BPEL 的过程中最复杂的任务涉及从数据库中读取流程设计并为流程生成 BPEL“包”。在该示例中,您将利用 XQuery 生成 BPEL。
XQuery 是一种强大、方便的 XML 数据处理语言。它不仅可以处理 XML 格式的文件,还可以处理结构(具有指定树和属性的嵌套结构)类似于 XML 的数据库数据。
以下文件(构成 Oracle BPEL 流程管理器的 BPEL 流程包)是动态生成的。
BPEL 文件: 该 XML 文件是实际的业务流程;它遵循 BPEL 规范。
WSDL 文件: Web 服务 WSDL 文件描述了两个接口:
Oracle BPEL 流程管理器中托管的 BPEL 流程公开的接口 。该接口非常简单,包含一个用于启动流程实例的调用和一个回调接口。 eCenterOne 公开的接口。为了简单起见,该工具也包含一个接口,可用于处理从 Oracle BPEL 流程管理器中运行的流程发出的对服务器的任何调用以及关联的回调。
bpel.xml: 一个部署描述符 XML 文件,用于向 Oracle BPEL 流程管理器描述 BPEL 流程。 它保存流程设置,其中包含特定于 Oracle BPEL 流程管理器的信息 以及以下信息。
指定 eCenterOne Web 服务 位置的位置信息 指定 当对 eCenterOne 的调用失败时应如何执行重试的信息 (重试)。
Ant build.xml: 使用 Oracle BPEL 流程管理器的 bpelc Ant 任务部署 BPEL 流程。(稍后将对此进行详细介绍。)
下面,我们将主要介绍如何动态生成 BPEL 文件。该过程涉及迭代数据库中存储的节点并为每个节点生成相应的 BPEL 活动: 迭代数据库。 生成 BPEL 是在 Java 代码中实施的,此代码读取工作流流程的每个 WorkflowNode 并创建一个由要处理的所有节点组成的列表。 为每个节点创建 BPEL 活动。 向包含在 <scope 活动中的一些 BPEL 活动中生成该列表中的每个工作流节点。因此,如果对 BPEL 活动的处理需要使用 BPEL 参数,则此参数只在该作用域中可见(不存在变量名冲突等问题)。必须为每个节点创建 XQuery 模板以生成一个相应的 BPEL XML 标记。XQuery 处理器将处理 XQuery 模板以构建包含节点和实例信息的 BPEL 并返回结果。 创建 BPEL 文件。 调用流程组合每个节点的 BPEL 活动并创建一个表示整个流程的主 BPEL 文件。为每个 WorkflowNode 生成的 <scope 块可以通过该方法相互添加。 <process> <scope> <!a?” start workflow node related activities -!> </scope> <scope> <!a?” wait workflow node related activities -!> </scope> <scope> <!a?” mail workflow node related activities -!> </scope> <scope> <!a?” update workflow node related activities -!> </scope> </process>
下面我们将更详细地分析第 2 步。每个节点都相当于一系列 BPEL 活动。这些信息全都存储在 XQuery 模板文件中。每个节点都有一个 XQuery 模板,其中包含该特定节点的所有 BPEL 结构。您已经创建了与隔间管理流程中的五个节点相对应的 start.xq、wait.xq、message.xq、update.xq 和 stop.xq。
下表描述了为示例流程中的 start、wait、message、update 和 stop 节点生成的 BPEL 活动。
隔间管理流程中的节点 等价的 BPEL 结构
Start <sequence> <receive> <assign> <scope> <variables> <sequence> <assign> <invoke> Wait <scope> <variables> <sequence> <assign> <invoke> <pick> 消息 <scope> <variables> <sequence> <assign> <invoke> update <scope> <variables> <sequence> <assign> <invoke> End <scope> <variables> <sequence> <assign> <invoke> <terminate>
注意如何向 BPEL 活动的层次结构中生成每个流程节点。例如,用于生成 message 活动的 BPEL 如下所示。它存储在 XQuery 文件 message.xq 中。
declare namespace ent = "http://www.centerstonesoft.com/schema/entity"; declare variable $nodeKey as xs:string external;
<scope> <!-- generation for Message activity --> <variables>
<!-- Define variables input, output and error variables--> <variable name="emailRequest" messageType="services:EntityAsyncMsgWSRequestMessage" <variable name="emailResponse" messageType="services:EntityAsyncMsgWSResultMessage" <variable name="fault" messageType="services:EntityFaultMessage" </variables>
<!--Begin the BPEL activities --> <sequence>
<!--This is the first assign activity.It configures the input variable with <!-- identification of node ($nodekey) and function to be called --> <!-- by the external webService (bpelSendEmail). -->
<assign> <copy> <from> <ent:EntityCollectionElem xmlns:ent="http://www.centerstonesoft.com/schema/entity" > <ent:Header <ent:entityName <ent:EntityElem> <ent:entityKey>{ $nodeKey }</ent:entityKey> <ent:method > <ent:methodName>bpelSendEmail</ent:methodName> <ent:parameter> <ent:PropName>thread</ent:PropName> <ent:Type>string</ent:Type> <ent:Value </ent:parameter> </ent:method> </ent:EntityElem> </ent:EntityCollectionElem> </from> <to variable="emailRequest" part="payload" </copy> </assign>
<!--Second and third assign activity configure the input variable --> <!--with identification of actual process instance -->
<assign> <copy> <from variable="input" part="parameters" query="//ent:Header" <to variable="emailRequest" part="payload" query="//ent:Header" </copy> </assign> <assign> <copy> <from variable="threadKey" part="value" <to variable="emailRequest" part="payload" query="//ent:parameter[ent:PropName = 'thread']/ent:Value" </copy> </assign>
<!--After configuring input variable with node, instance and function to be called, invoke the external service --> <invoke name="invoke" partnerLink="EntityAsyncMsgWSLink" portType="services:EntityAsyncMsgWS" operation="invoke" inputVariable="emailRequest"
<!--Check response from external service.If response indicates fault, throw exception. --> <!--If no response is received for 10 days, throw exception --> <pick name="deadlined_receive" >
<!--Set output variable if return result from external webservice is OK--> <onMessage partnerLink="EntityAsyncMsgWSLink" portType="services:EntityAsyncMsgWSCallback" operation="onResult" variable="emailResponse"> <empty </onMessage>
<!--On fault, check the fault code and throw appropriate exception-->
<onMessage operation="onFault" partnerLink="EntityAsyncMsgWSLink" portType="services:EntityAsyncMsgWSCallback" variable="fault"> <switch> <case condition="bpws:getVariableData('fault', 'value', '/EntityFault/faultcode') = 'MailException' "> <throw faultName="ent:MailException" faultVariable="fault" </case> <otherwise> <throw faultName="ent:SystemException" faultVariable="fault" </otherwise> </switch> </onMessage>
<!--If no response for 10 days, throw exception--> <onAlarm for="'P10D'"> <throw faultName="ent:SystemException" </onAlarm> </pick> </sequence> </scope>
查看该 XQuery 模板后,您将了解文档如何生成一个包含 message 流程节点实施的 <scope> 活动。<scope> 活动从 <variables> 部分开始,其中为请求以及正常响应或故障响应定义了变量。variables 部分之后是 <sequence>,其中使用 <assign> 语句序列生成请求。第一个 <assign> 写入该请求的样板;在该 <assign> 中,XQuery 参数 nodeKey 用于将节点标识传递给外部 Web 服务。
注意,nodeKey 是生成时间信息。第一个 <assign> 活动之后的两个 <assign> 活动处理运行时信息。第二个 <assign> 复制用于启动流程的初始请求中的标头信息。该标头信息标识 eCenterOne 和 Oracle BPEL 流程管理器流程实例 ID 以及该流程用于的客户。第三个 <assign> 活动复制流程的线程 ID。(正如前面指出的,该流程中的其他节点也存在类似的 XQuery 模板。)
XQuery 处理。下面,我们将简要了解一下 XQuery 处理器如何处理所有这些模板以及如何组合它们以构成一个 BPEL 文件。
下面的 generateActivity() 接受要为其生成 BPEL 活动的节点列表。对于每个节点,它将使用函数 XQuery.newXQueryFromResource 找到正确的 XQuery 模板。随后,Saxon 处理器将处理该 XQuery 模板并生成一个 XML 字符串。如果节点包含子节点,则将在 while 循环中以递归方式对其进行处理。
/** * Recursively generates an activity including any child activities. * @param activity the node that is being generated, the value is null for the top-level * process node * @return typically the root element of the generated XML document * @throws EntityException */ protected String generateActivity(WorkflowNode activity) throws EntityException { //Find the next node in the list to be processed BpelActivityType activityType = getBpeBpelActivityType(activity); //Get the parameters to be passed to node HashMap params = calculateParameters(activity, activityType); try { //Get corresponding XQuery file for the node XQuery q = XQuery.newXQueryFromResource("bpelgen/" + activityType.getQuery()); //Call the Saxon XQuery Processor to run the query. XQueryResult result = q.run(null, params, null); //Convert the result into a string String parentXml = result.serializeString(); if (logger.isDebugEnabled()) { logger.debug("Generated for parent '" + activityType.getName() + "' is \n" + parentXml); } //If there are child nodes, recursively invoke generate activity if (_process.hasChildren(activity)) { //Call java relational class Iterator it = _process.getChildrenIterator(activity); //Recursively call generateActivity for child nodes.For a??Cube Management Processa??, these will be //start, wait, message, update & end while (it.hasNext()) { WorkflowNode childActivity = (WorkflowNode) it.next(); String childXml = generateActivity(childActivity); // now use Saxon XSLT to add the document generated for the children to the result document // Get the Transformer used for this transformation Transformer transformer = getPrependTransformer(); transformer.setParameter("inserted", DomUtils.getDocument(new ByteArrayInputStream(childXml.getBytes()))); StreamResult saveResult = new StreamResult(new ByteArrayOutputStream()); try { StreamSource src = new StreamSource(new ByteArrayInputStream(parentXml.getBytes())); // Transform the XML Source transformer.transform(src, saveResult); } finally { transformer.clearParameters(); } parentXml = ((ByteArrayOutputStream)saveResult.getOutputStream()).toString(); if (logger.isDebugEnabled()) { BpelActivityType childType = getBpeBpelActivityType(childActivity); logger.debug("Preprocessed for parent '" + activityType.getName() + "' and child '" + childType.getName() + "' is \n" + parentXml); } } } // remove the <insert-here> node Transformer transformer = getRemovePrependTransformer(); StreamResult saveResult = new StreamResult(new ByteArrayOutputStream()); StreamSource src = new StreamSource(new ByteArrayInputStream(parentXml.getBytes())); transformer.transform(src, saveResult); parentXml = ((ByteArrayOutputStream)saveResult.getOutputStream()).toString(); if (logger.isDebugEnabled()) { logger.debug("Generated for '"+activityType.getName()+"' is \n" + parentXml); } return parentXml; } catch (SAXException ex) { throw new EntityException("Failed to run transform "+activityType.getQuery(), ex); } catch (TransformerException ex) { throw new EntityException("Failed to run transform "+activityType.getQuery(), ex); } catch (IOException ex) { throw new EntityException("Failed to load query "+activityType.getQuery(), ex); } }
generateActivity() 方法以字符串格式生成最终的 BPEL 文件。随后,另一个 Java 程序将它写入文件。可以下载示例代码文件中的所有 XQuery 模板以及隔间管理流程的 BPEL 文件。
使用 Ant 进行动态部署。最后一步是使用 Oracle BPEL 流程管理器部署工具编译和部署 BPEL 流程。对于部署,需要生成以下简单的 Ant build.xml 文件,然后执行它(对它支持的参数化 XML 文件再次使用 XQuery)。 <?xml version="1.0" encoding="UTF-8" ?> <project default="main" basedir="C:/DOCUME~1/jerry/LOCALS~1/Temp/cs_bpelgen_simple24369" name="BpelDeploy"> <target name="main"> <bpelc keepGenerated="true" deploy="jt_dev" rev="1.0" home="c:\orabpel" </target> </project>
最后一步是从应用服务器中以编程方式执行 Ant。为此,可以使用 Ant 任务 Execute(位于 org.apache.tools.ant.taskdefs 中)中的代码。该类为以编程方式执行命令行流程并处理正常和错误返回提供了行业级别的支持。
以下代码片段描述了如何使用 Ant Execute 任务中的代码实施 BPEL 流程部署。 String args[] = new String[1]; args[0] = "c:/orabpelpm/integration/orabpel/bin/obant.bat";
Execute exe = new Execute(); exe.setCommandline(args); exe.setWorkingDirectory(_deploydir); int retval = exe.execute(); if ( retval != 0 ) { throw new ExecuteException("process failed to deploy");
在此代码片段中,Execute 类用于直接执行 Oracle BPEL 流程管理器命令行文件 obant。该批处理文件正确地设置 Windows 环境,然后对如上所示的 build.xml 文件调用 Ant。
该文件中的非零返回代码通常是由于 BPEL 编译器返回的错误引起的。但这些错误并不常见并且通常是由于流程实施中的某个内部错误引起的。
结论
CenterStone Software 使物业经理可以使用自定义设计器快速自定义业务流程。这些流程随后动态转换为 BPEL 并部署到 Oracle BPEL 服务器中。凡是在很大程度上依赖业务用户设计组织流程的企业都应好好考虑一下该方法。自定义设计器方法不但使用户不受 BPEL 复杂性的影响,而且还提供了一个独特的平台来即时生成自适应 BPEL 流程。这使企业可以快速实现 SOA 的好处。
Jerry Thomas [ jthomas@centerstonesoft.com ] 是 Centerstone Software (帮助世界上许多最大型的企业更高效地自动化和管理他们的房地产、设备、员工、资产、租赁和工作场所操作)的首席设计师。Thomas 专注于 CenterStone 的企业工作场所管理产品和 Web 服务、BPEL 以及系统基础架构。在加入 CenterStone 之前,Thomas 曾担任顾问并在 Riverton、ONTOS 以及 Hewlett-Packard 的开发部门担任要职。
|
|
|
[编辑文章 3 次, 最后修改: Pioneer 于 06-6-5 下午5:45] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
第8部分:使用 BPEL 将 PeopleSoft CRM 与 Oracle 电子商务套件集成 |
引言回复
回复
|
|
|
作者:Lawrence Pravin
使用 BPEL 将 PeopleSoft 8.9 CRM 与 Oracle 应用程序 11i 集成的分步方法 许多企业都具有许多跨不同部门、地理位置或分支机构的异类应用程序组合。尽管可以使用多个 ERP 系统来满足业务单元的要求,但它们实际上会导致数据碎片。集成这些系统比较复杂,并且通常采用专用方式进行处理;尽管如此,公司仍投入了大量的资源来集成遍布多个 ERP 系统的信息,以便作出更好的业务决策。 BPEL 提供了一个以流程为中心的标准方法来集成不同的系统。Oracle 的 BPEL 流程管理器是 Oracle 融合中间件(用于提供面向服务的体系结构 (SOA))中的一个重要工具,它支持 Microsoft、IBM、SAP 以及 BEA 所支持的行业标准 BPEL 规范,并且被广泛认为是一个用于降低集成项目的成本、复杂性和不灵活性的企业蓝图。 在 BPEL 指南的这一部分中,我将介绍一种使用 BPEL 将 PeopleSoft 8.9 CRM 与 Oracle 应用程序集成的方法。具体而言,通过一个示例业务情景,您将了解如何配置 PeopleSoft 以将它的模块公开为 Web 服务,以及如何配置 Oracle BPEL 流程管理器以便与 Oracle 应用程序交互。 实用情景 在一个典型的订单管理业务情景中,订单被输入到 CRM 系统中,并通过后端 ERP 履行订单。在本示例中,我们将 PeopleSoft 用作前端应用程序来管理营销、销售和服务操作,并将 Oracle 电子商务套件用作 ERP(订单管理、库存和财务)。此处考虑的业务流程是一个报价-订单流程。 本业务流程的一部分 — 报价和订单输入 — 在 CRM 系统中执行,而订单履行在 ERP 系统中执行。要优化内部操作,需要将整个跨应用程序的报价-订单业务流程自动化。 以下是此业务流程集成中提供的功能(参见图 1): PeopleSoft 中的销售订单创建 在 PeopleSoft 中,可以通过将报价转换为销售订单或直接通过 Order Capture 屏幕创建销售订单。 提交时,系统将检查所需信息并将状态更改为 OPEN;否则,状态将为 HOLD。 此销售订单流程将调用订单信息并将该信息提交给集成流程。随后将调用 BPEL 流程管理器。 BPEL 流程管理器将消息数据转换为 Oracle ERP 订单管理模块所要求的格式。 销售订单创建过程发生在 Oracle ERP 应用程序中,并把订单确认传播给 PeopleSoft。 Oracle ERP 中的 ATP 检查 在订单创建流程中,销售人员可能想要检查材料的可用性以确定交货日期。 PeopleSoft CRM 将同步调用 ERP 应用程序,使用商品/产品可用性查询组件获取现有的可用数量。 BPEL 流程管理器将此 ATP 检查请求传给 Oracle ERP。 Oracle ERP 将检查库存中特定商品的可用数量。它将相关的可用性详细信息返回给 BPEL 流程管理器。 BPEL 流程管理器将此 ATP 响应信息传递给 PeopleSoft CRM。根据该操作,将向客户承诺实际的交货日期。 将订单状态更新从 Oracle ERP 传播给 PeopleSoft CRM 将销售订单传播给 ERP 应用程序后,将在 ERP 中下订单,将确认发送给 BPEL 流程,并随后传播给 PeopleSoft CRM 系统(订单状态将在该系统中更改为“In Process”)。 Oracle ERP 将不断传播订单状态的更改。ERP 中的此状态映射到 CRM 中的等价状态。
图 1 下面我们将着重介绍订单创建步骤。 该设计时 viewlet 演示了实际的配置和执行过程。有关该流程中其他步骤的详细信息,请参考 Oracle 应用程序集成指南 。 解决方案概述 至此,您了解了实用的业务流程,下面我们将了解如何在体系结构级别实现它。图 2 提供了一般使用 Oracle BPEL 流程管理器作集成平台集成 PeopleSoft CRM 与 Oracle 应用程序所需的组件。
图 2 企业集成点 (EIPS) 是使 PeopleSoft 应用程序能够与第三方系统和其他 PeopleSoft 软件无缝工作的 Web 服务连接。在 PeopleSoft CRM 中提交订单时,PeopleSoft 中的 EIP 将它转换为 XML 格式。随后,将该订单 XML 传递给附加的 PeopleCode 方法 (WSDL_ORDER)。(PeopleCode 是用于实施业务规则或执行其他自定义的 PeopleSoft 编程语言。)WSDL_ORDER 将把收到的订单 XML 转换为 SOAP XML 并将该请求发送给 PeopleSoft 远程节点。远程节点 是与在 BPEL 流程管理器中配置的 Web 服务握手的节点。 可以通过使用 Web 服务调用框架 (WSIF) 绑定(BPEL 流程管理器为其提供了强有力的支持)将远程节点映射到 WSDL 来调用 Web 服务。在收到此 SOAP XML 时,PeopleSoft 节点将根据为该节点导入和配置的 WSDL 来调用 Web 服务。此 Web 服务在 BPEL 流程管理器中调用和执行。 BPEL 流程管理器将订单数据作为 SOAP XML 处理并将它发送给 Oracle 应用程序;它在内部利用 Oracle 应用程序 (OA) 适配器 与 11i 通信。OA 适配器是一个纯 JCA 1.5 资源适配器,用于从电子商务套件中发送和接收消息。Oracle 应用程序通过此适配器将某个提供的 API 和表公开给外部应用程序。 Oracle 应用程序处理订单并发送确认;BPEL 流程管理器接收该响应并将它转发给 PeopleSoft 节点。随后,该节点将响应请求 Web 服务的 PeopleCode。后者将检索 XML 数据并将它提交给 PeopleSoft 中配置的组件接口。组件接口 是公开 PeopleSoft 组件以便从其他应用程序(用 Java 或 PeopleCode 编写)中进行同步访问的接口。 它是订单数据从 PeopleSoft 发送到 Oracle 应用程序并返回的高级流。在下一个部分中,您将了解如何将 PeopleSoft CRM 模块公开为 Web 服务、如何构建一个 BPEL 流程以及如何配置 OA 适配器。 将 PeopleSoft CRM 与 Oracle ERP 集成 在 PeopleSoft CRM 中提交订单后,需要将订单信息传递给 Oracle 应用程序。该流程有三个主要步骤。 在 Oracle BPEL 流程管理器中设计业务流程。 配置 Oracle 应用程序适配器。 配置 PeopleSoft。 下面我们仔细了解其中的每个步骤: 第 1 步:设计 BPEL 流程 在该步骤中,您将使用 BPEL Designer 创建一个流程。BPEL 流程管理器将从 PeopleSoft 接收包含销售订单信息的 SOAP XML 并将它转换为 OA 适配器的 XML 格式。(为调用 API 创建合作伙伴链接时,OA 适配器将自动生成模式。)随后,将调用和转换 OA 适配器链接,并将订单 XML 提交给 Oracle 应用程序。Oracle API 将处理订单并在输出确认 XML 中返回订单号。 BPEL 流程管理器处理远程故障和绑定故障。当连接不可用时,它将重试五次,然后抛出异常。当发生绑定异常时,将处理绑定故障。 下面是一个为 BPEL 流程管理器设计的集成业务流程的典型示例。 (单击图像可放大) 该流程中的重要活动包括: 选择 Applications > New Application Workspace > New Project > BPEL Process Project。 导入模式以定义 BPEL 流程的输入和输出变量。 从结构窗口中,选择 project schemas > import Schema。 输入输入模式名称 (createorder.xsd)。 从结构窗口中,选择 Message Types。 选择 CreateOrderRequestMessage 并映射 createorder.xsd 的 CreateOrderIn 根元素。 选择 CreateOrderResponseMessage 并映射 createorder.xsd 的 CreateOrderOut 根元素。 从结构窗口中,选择 Variables。 确认将 InputVariable 映射到 CreateOrderRequestMessage。 确认将 OutputVariable 映射到 CreateOrderResponseMessage。 为 OA 适配器创建合作伙伴链接。 从组件面板中为 CreateOrder 流程添加一个合作伙伴链接活动并将它命名为“CreateOrderPL”。 单击 Define Adapter Service 并执行以下步骤。 为合作伙伴链接配置 BPEL 流程管理器和 OA 适配器(稍后将对其进行详细介绍)。 添加 Invoke 活动来调用 OA 适配器。 将 invoke 活动拖放到该流程并双击它。 将合作伙伴链接映射到 CreateOrderPL 并创建输入和输出变量。 在 invoke 活动上添加一个 transform 活动,将 PeopleSoft 输出 XML 转换为 Oracle 应用程序输入 XML。 双击 transform 活动。选择 inputVariable 作为源变量,选择 invokeCreateOrderInputVariable 作为目标变量,然后单击创建映射图标,如下所示。 映射源模式和目标模式,如下所示。 在 invoke 活动下添加另一个 transform 活动,将 Oracle 应用程序输出 XML 转换为 PeopleSoft 输入 XML。 双击 transform 活动。选择 invokeCreateOrderOutputVariable 作为源变量,选择 outputVariable 作为目标变量,然后单击创建映射图标。 映射源模式和目标模式,如下所示。 以下文件(全部包含在 示例代码下载 中)将在 BPEL Designer 中重新创建上述流程。 Bpel.xml 部署描述符文件,用于定义此 BPEL 流程流所调用服务的 WSDL 文件的位置 CreateOrder.xsd PeopleSoft 应用程序提交的输入 XML 的模式 CreateOrder.bpel 包含流程流、合作伙伴链接、数据变量和必要的故障处理程序的流程源文件。 CreateOrder.wsdl WSDL 客户端接口,用于定义该 BPEL 流程流的输入和输出消息、支持的客户端接口和操作以及其他特性。该功能使 BPEL 流程流可以作为服务调用。 您现在已经完成了该 BPEL 流程的设计。接下来,我们将详细介绍 PeopleSoft 端的配置。 第 2 步:配置 OA 适配器 OA 适配器在托管模式下部署在 Oracle Containers for J2EE 中。可以使用它从电子商务套件中发送和接收消息。以下是配置适配器所涉及的步骤。 定义一个适配器服务并选择 Oracle Applications Adapter。 输入服务名。该名称将用作选定 API/表的 Web 服务。 选择一个在项目中定义的连接。如果没有可用的 DB 连接,单击 New 并按照向导执行操作。 选择 Oracle 应用程序数据的 Table/Views/APIs 接口。 搜索并选择要从 BPEL 流程中调用的 PROC_ORDERENTRY_ARRAY API。 注意:在本示例中,由于 BPEL 流程管理器将不支持 oracle 记录类型,因此 PROC_ORDERENTRY_ARRAY 是为 PROCESS_ORDER 预先提供的 API 编写的包装器 API。您将改用包装器过程中的对象类型(类似于 PROCESS_ORDER 中使用的记录类型)。此接口负责处理 Oracle 应用程序中的销售订单。 将把该 API 添加到适配器服务中。 将把 Oracle 应用程序合作伙伴链接添加到 BPEL 流程,并创建 APPS_PROC_ORDERENTRY_ARRAY.xsd。 适配器服务将为 PROC_ORDERENTERY_ARRAY API 创建一个 WSDL 文件,它的作用类似于 Web 服务并使用 WSIF 绑定到了 ERP。 示例代码下载中的以下文件将帮助您在 BPEL Designer 中配置 OA 适配器。
Proc_orderentry_array.sql 用于调用 OA 提供的 Process_Order API 的自定义包装器 API
Create_ObjectScript.sql 包含 PROC_ORDERENTERY_ARRAY 自定义 API 中使用的对象创建脚本
CreateOrder.bpel 包含流程流、合作伙伴链接、数据变量和必要的故障处理程序的流程源文件。
CreateOrder.wsdl WSDL 客户端接口,用于定义该 BPEL 流程流的输入和输出消息、支持的客户端接口和操作以及其他特性。该功能使 BPEL 流程流可以作为服务调用。
至此,已经完成了 BPEL 流程的设计和 OA 适配器的配置。接下来(以及最后),我们将配置 PeopleSoft。
第 3 步:配置 PeopleSoft 现在您已经创建了 BPEL 流程,下面我们将了解配置 PeopleSoft 的流程(分四个步骤)。
在第 1 步中,将 BPEL 流程 WSDL 导入到 PeopleSoft 中。然后,您将使用导入的 WSDL 配置节点。该节点将最终与 BPEL 流程进行通信。 在第 2 步中,配置销售订单 EIP,以便在每次创建新的销售订单时调用该节点。 最后,在节点将订单信息发送给 BPEL 流程之前,您需要把它转换为 SOAP XML。因此,在第 3 步和第 4 步中,您将编写一个小 PeopleCode 函数来执行该转换并与节点建立关系。 下面我们将详细介绍其中的每个步骤。
1. 配置 PeopleSoft 节点以便与 BPEL 流程进行交互 在该步骤中,您将配置一个节点来与 BPEL 流程交互。您将定义请求和响应消息以及这些消息将通过的通道。
首先,使用 URL 选项将 CreateOrder.wsdl(先前创建的)导入到 PeopleSoft 中。这将 CreateOrder 标识为流程(在 PeopleSoft 中创建订单时将调用该流程)。将 WSDL 导入到 PeopleSoft 中时,集成代理程序将把它添加到 WSDL 信息库中。
要导入 CreateOrder.wsdl,选择 PeopleTools > Integration Broker > Web Services > Import WSDL。
您现在可以使用 WSDL Repository 页访问 WSDL 信息库中的 WSDL。 将 CreateOrder WSDL 导入到 PeopleSoft 中后,必须配置一个远程节点以便与 BPEL 流程通信。要定义此通信,必须添加相应的请求消息、响应消息 和消息通道。 创建新的远程节点: 选择 Create a New Node Definition 按纽。 在 Node Name 域中,为新节点定义输入 BPEL_CREATEORDER。 在 Node Description 域中,输入描述性的节点名称。 从 Authentication 下拉列表中,选择一个验证方法。有效选项为 None (Default)、Certificate 或 Password。 (可选)在 Password 域中,输入口令。 (可选)在 Confirm Password 域中,重新输入口令。 单击 Next 按钮前进到 WSDL Operation Wizard 的下一页,在该页中为服务选择请求消息和响应消息。请求和响应消息是在 PeopleSoft 中创建的用于表示 SOAP Request 和 Response 消息的非结构化消息。 创建一个新的请求或响应消息: 在相应部分中选择 Create a New Message 选项。 要创建一个新的请求消息,在 Request Message 部分中选择该选项。在 message name 域中输入 BPEL_ORDER_REQ。 要创建一个新的响应消息,在 Response Message 部分中选择该选项。在 message name 域中输入 BPEL_ORDER_RES。 新创建消息的消息版本默认为 VERSION_1。PeopleSoft 集成代理程序使用该值填充 Message Version 域。 PeopleSoft 集成代理程序自动将新消息分配给新消息通道。在向导配置的结尾,将使用新消息在节点上创建输出同步事务。 在 channel name 域中输入新消息通道名称 BPEL_SERVICES。
至此,已经完成了第 1 步。您导入了 WSDL,告知 PeopleSoft 要调用的 Web 服务。您还定义了节点、消息和通道,将信息传递给 Web 服务 (BPEL Process CreateOrder)。在下个步骤中,您将在销售订单 EIP 和这个新配置的节点之间建立关系。 2. 在 EIP 和节点之间建立关系 该步骤将在 CRM_SALES_ORDER EIP 和新节点之间创建一个链接。将 CRM_SALES_ORDER EIP 发布到集成代理程序时,以上创建的链接将把 CRM_SALES_ORDER 消息作为请求消息发送给上面创建的节点。 从 People Tools > Integration Setup 中选择 Node Definition;搜索 BPEL_CREATEORDER 节点。 在上面选择的节点中,将 Transaction type 更改为“Outbound Asynchronous”并在 Request Message 中输入“CRM_SALES_ORDER”。 3. 创建转换代码 在该步骤中,您将创建应用程序引擎程序 WSDL_ORDER。(应用程序引擎是 PeopleSoft 高容量应用程序处理器。应用程序引擎是使用 Application Designer 开发的,并可以利用常见的 PeopleTools 对象,如记录、PeopleCode 和 SQL 对象。)WSDL_ORDER 将从 EIP 接收的销售订单消息转换为 BPEL 请求(SOAP 消息)并在节点通道上发布已转换的消息。 将以下代码添加到 transform 并将请求发送给上面创建的节点。将请求提交给节点后,该节点将调用配置给它的 Web 服务。将调用此 Web 服务并向该节点(将 XML 消息发送给 PeopleCode 方法)返回响应。 /* Get the data from the AE Runtime */ Local TransformData &transformData = %TransformData;
Local File &logFile = GetFile("TestSyncReqResStep3.log", "W", %FilePath_Absolute);
Local string &destNode = &transformData.DestNode;
&logFile.WriteLine("DestNode:" | &destNode);
/* Set a temp object to contain the incoming document */ Local XmlDoc &xmlDoc = &transformData.XmlDoc;
Local string &xmlStr = &xmlDoc.GenXmlString();
&logFile.WriteLine("Transformed XML :" | &xmlStr);
/* Maps the &xmlDoc to the BPEL_ORDER_REQ and publish to the BPEL_CREATEORDER node. Node will invoke BPEL CreateOrder process. Response will be assigned to &response variable. */
Local XmlDoc &response = SyncRequestXmlDoc(&xmlDoc, Message.BPEL_ORDER_REQ, Node.BPEL_CREATEORDER);
&logFile.WriteLine("Response XML Data:" | &response.GenXmlString());
&logFile.Close();
4. 将 WSDL_ORDER 应用程序引擎与节点链接 在该步骤中,您将把转换代码关联到 CreateOrder 节点。因此,每当调用 BPEL 流程管理器时,将执行该转换节点。
创建一个新的关系 WSDL_ORDER,并将它映射到节点 WSDL_ORDER。为此,执行以下操作:
从 People Tools > Integration Setup 中选择 Relationships 并选择 Add New Value。
将初始节点映射为 BPEL_CREATEORDER、将请求消息名称映射为 CRM_SALES_ORDER、将事务类型映射为 OA、将结果节点映射为 BPEL_CREATEORDER 并将请求消息名称映射为 CRM_SALES_ORDER,默认情况下将选择它们的版本。然后,单击 Add。
将转换请求映射为 WSDL_ORDER。 至此,已完成了销售订单创建步骤。请再次观看设计时 viewlet,了解如何配置所有这些步骤;在运行时 viewlet中,您实际上将看到一个从 PeopleSoft 中提交并发送给 Oracle 应用程序的销售订单。 结论 由于异类应用程序分布在多个不同业务单元中,因此企业在聚合信息方面面临挑战。集成这些系统需要大量投资。现在,正如本文所演示的,此类企业可以选择使用类似 BPEL 这样的标准集成这些应用程序。 --------------------------------------------------------------------------------
Lawrence Pravin 是 Sierra Atlantic Inc. 流程集成包的产品经理。流程集成包在企业应用程序之间提供了端到端的业务流程集成解决方案。他在打包应用程序方面拥有 10 年以上的丰富经验,并在 Oracle、PeopleSoft、Siebel 和 SAP 应用程序方面拥有过硬的集成专业技能。
|
|
|
[编辑文章 3 次, 最后修改: Pioneer 于 06-6-5 下午5:55] |
|
|
|
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
|
|
作者:Stany Blanvalet
了解如何在 BPEL 生产环境中使用 BPEL 流程管理器的 API 和 Dehydration Store 自动化常见管理任务。
一些企业将其 70% 的 IT 预算花在了维护和管理当前 IT 功能以及操作上。但矛盾的是,对于多数使用面向服务体系结构 (SOA) 的公司而言,管理 Web 服务的性能和可用性并非首要之事。因此,随着企业采用 Web 服务和 BPEL 来构建 SOA 基础架构,设计新的策略来降低应用程序管理成本变得愈加势在必行。
因为通常会将多个业务流程部署至生产环境,所以这对于 BPEL 实施而言尤其重要。随着生产环境中部署了越来越多的流程,有效管理变得日趋重要。每个已执行完毕的 BPEL 流程(无论成功与否)都存储在数据库中,在流程流的不同步骤间进行交换的每条 XML 消息也是如此。正如您可能预料到的,该流程将导致数据库大小呈几何级增长,进而导致出现性能瓶颈。
由于这些原因,在 BPEL 生产环境中,最为重要的是要能够
在不影响生产系统稳定性的情况下,存档已完成 BPEL 流程的信息 删除从数据库成功交付和解析的所有 XML 消息 删除陈旧的实例 重新运行失败的流程 在 BPEL 简明手册的这一部分中,您将了解到 BPEL 流程管理器的 API 和 Dehydration Store 是如何实行这些功能,以及如何存档和删除已完成 BPEL 流程实例的信息。您还将学习如何使用 PL/SQL 和 EJB 删除陈旧的实例、完成调用以及回调 XML 消息。最后,将介绍如何通过 BPELTest 实用程序返回失败的流程实例。
BPEL 流程管理器 API 和 Dehydration Store Oracle BPEL 流程管理器控制台为管理、调试部署至 BPEL 服务器的流程提供了一个基于 Web 的友好界面。但是,在生产环境中,管理员需要对管理任务具有强有力的控制。通过针对 BPEL Dehydration Store 数据库的 PL/SQL 查询或 BPEL API,可以将这些管理任务中的多数进行自动化。但在创建操作项之前,了解 Dehydration Store 和 BPEL 流程管理器 API 的基础概念至关重要。
Dehydration Store 数据库用于存储流程状态数据,尤其是异步 BPEL 流程的数据。以下简要介绍了一些非常重要的表。
表 内容
CUBE_INSTANCE 实例元数据信息(创建日期、当前状态、流程 id)
CUBE_SCOPE 实例的范围数据
AUDIT_TRAIL 实例的审计跟踪信息。该信息可通过 BPEL 控制台查看。
AUDIT_DETAILS 流程实例的详细审计信息
DLV_MESSAGE 回调消息元数据
DLV_MESSAGE_BIN 回调消息的有效负载
INVOKE_MESSAGE 调用消息元数据
INVOKE_MESSAGE_BIN 调用消息的有效负载
DLV_SUBSCRIPTION 实例的交付订阅
TASK 为实例创建的任务(即标题、任务接受人、状态、有效期)
表 1:BPEL Dehydration Store 中的重要表
数据库模式位于 $ORABPEL$\integration\orabpel\system\database\scripts 目录下的 DDL 脚本 domain_oracle.dll 中。正确了解该模式后,管理员无需 BPEL 控制台就可直接针对该存储编写 SQL 查询。
除了此种 SQL 方法,管理员还可利用 BPEL 流程管理器 API。该 API 提供了一个详尽的类集,可用于在各种状态中查找、存档、删除实例,跨不同的域删除回调/调用消息,或查询特定域、流程或实例的状态。(API 文档位于 $ORABPEL$\integration\orabpel\docs\apidocs\index.html 中。)下表概述了一些相关性最强的类/接口以及相应的方法。
类/接口 方法
类 WhereConditionHelper 提供诸如 whereInstancesClosed()、whereInstancesStale() 和 whereInstancesOpen() 之类的方法,用于构造搜索相应实例的 where 子句。
接口 IBPELDomainHandle 允许开发人员在处于运行中的 BPEL 流程域上执行操作。提供诸如 archiveAllInstances()、deleteAllInstances()、d eleteInstancesByProcessId()、deployProcess()、undeployPorcess()、deleteAllHandledCallback() 以及 deleteAllHandledInvoke() 等方法。
接口 IinstanceHandle 允许用户在活动的实例上执行操作。提供诸如 isStale()、getState()、getModifyDate() 以及 delete() 等方法。
类 Locator 允许用户搜索已在 Orabpel 流程域内部署并实例化的流程、实例以及活动。提供诸如 listInstances() 和 listActivities() 等方法,并可接受 where 子句作为参数。
表 2:用于执行管理任务的重要类
接下来,您将学习如何执行一些最重要的管理任务。
存档已完成的实例 如前所述,所有执行成功的流程实例均存储在 Dehydration Store 中。现在,在实例完成后,一个 BPEL 实例保存在了两个表中:cube_instance 和 cube_scope。前者存储实例头信息:域、创建日期、状态(已完成、运行中、陈旧、已取消)、优先级、标题等等。后者存储实例的状态(变量值等)。默认情况下,使用这两个表存储已完成的实例。
可从 BPEL 控制台清除数据库中的实例信息,如下所示。
图 1:删除已完成的实例 在生产环境中,有必要在删除信息之前对其进行存档 — 需对数百个实例进行此项操作。幸运地是,您可以使用 PL/SQL 或 EJB 来达到此目的。(请记住,在将信息从 BPEL 数据库中清除之前,应将这些信息移至其他位置。)我们来看一些示例:
利用 EJB 存档。 此例将用到以下接口和方法。
com.oracle.bpel.client 接口 IBPELDomainHandle
方法摘要
int archiveInstances(WhereCondition wc, boolean deleteInstances)
(存档所有由 wc 指定的搜索条件返回的实例)
方法 archiveInstances 将存档并删除所有已完成的实例。它接受参数 keepdays,该参数指定已完成实例在存档前可保留的天数。
public static int archiveInstances(Locator locator, String processId, int keepdays) throws ORABPELAccessException { try { WhereCondition wc = WhereConditionHelper.whereInstancesClosed(); WhereCondition tmpWhere = new WhereCondition(); NonSyncStringBuffer buf = new NonSyncStringBuffer(); if (!"*".equals(processId)) { buf.setLength(0); tmpWhere.setClause(buf.append(" AND ").append( SQLDefs.AL_ci_process_id).append(" = ?").toString()); tmpWhere.setString(1, processId); wc.append(tmpWhere); } Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -keepdays); buf.setLength(0); tmpWhere.setClause(buf.append(" AND ").append( SQLDefs.AL_ci_modify_date).append(" <= ?").toString()); tmpWhere.setTimestamp(1, cal.getTime()); wc.append(tmpWhere); IBPELDomainHandle domain = locator.lookupDomain(); return domain.archiveInstances(wc, true); } catch (ServerException se) { throw new ORABPELAccessException(se.getMessage()); } }
利用 PL/SQL 存档。 管理员还可利用 PL/SQL 来达到此目的。在将记录从数据库中删除之前,DBA 可根据自身需要将记录移至其他数据库/表。下面就是一个例子:
Query: SELECT CIKEY FROM CUBE_INSTANCE, DOMAIN WHERE BPELMNG.CUBE_INSTANCE.DOMAIN_REF = BPELMNG.DOMAIN.DOMAIN_REF AND BPELMNG.DOMAIN.DOMAIN_ID = 'XXX' ?XXX is the name of the domain AND STATE = 5 ?'5' mean COMPLETED AND MODIFY_DATE < SYSDATE-X ?X is the number of day of history AND PROCESS_ID = 'XXX'; ?XXX is the process name Actions: For each CIKEY, call COLLAXA.delete_ci(CIKEY); oracle procedure.
在接下来的部分中,您将学习如何删除回调和调用消息。
删除回调和调用消息 只要实例要求从合作伙伴获得消息(receive、onMessage 等),就针对该特定接收活动发出订阅。一旦接收到交付消息,交付层就会试图将消息与预定的订阅相关联。成功订阅的消息将继续保留在数据库中。这些消息可通过 collaxa.delete_ci(CIKEY) 存储过程删除(操作如同前述的实例存档)。
所有的回调和调用 XML 消息均是如此。即使已成功解析和交付这些消息,它们仍会保留在数据库中。
可以使用以下方法删除所有回调、调用以及订阅。
com.oracle.bpel.client 接口 IBPELDomainHandle
方法摘要
int deleteAllHandledCallback ()
(删除所有交付至此域的、已成功解析和交付的回调消息)
int DeleteAllHandledInvoke ()
(删除所有交付至此域的、已成功解析和交付的调用消息)
int DeleteAllHandledSubscription ()
(删除此域中所有已成功解析和处理的消息订阅者 — 即已向其交付了消息)
还可以使用 PL/SQL 来执行相同的操作,如以下存储过程所示。建议 DBA 将该脚本用作模版,并对其进行修改来满足特定的存档需求(删除、移至另一数据库、更改 where 子句以包含基于业务条件的选择,等等)。
/** * Procedure to clean invocation messages for a particular domain. * Invocation messages are stored in invoke_message and invoke_message_bin table * It will select all the invocation messages from invoke_message table. * For each message which has been delivered or resolved, delete it from * invoke_message and invoke_message_bin table */ procedure delete_invoke( p_domain_ref in integer ) as cursor c_invoke_message is select message_guid from invoke_message where ( state = 2 or state = 3 ) and domain_ref = p_domain_ref for update; begin for r_invoke_message in c_invoke_message loop delete from invoke_message_bin where message_guid = r_invoke_message.message_guid; delete from invoke_message where current of c_invoke_message; end loop; commit; end delete_invoke;
/** * Procedure to clean callback messages for a particular domain. * Callback messages are stored in dlv_message and dlv_message_bin table * It will select all the invocation messages from dlv_message table. * For each message which has been delivered or resolved, delete it from * dlv_message and dlv_message_bin table */ procedure delete_callback( p_domain_ref in integer ) as cursor c_dlv_message is select message_guid from dlv_message where ( state = 2 or state = 3 ) and domain_ref = p_domain_ref for update; begin for r_dlv_message in c_dlv_message loop delete from dlv_message_bin where message_guid = r_dlv_message.message_guid; delete from dlv_message where current of c_dlv_message; end loop; commit; end delete_callback;
接下来,简要介绍一下如何删除陈旧的实例。
删除陈旧的实例 使用 BPEL 控制台可识别所有陈旧的实例,并按如下所示将其清除。
图 2:在 BPEL 控制台中清除陈旧的实例 遗憾地是,只能针对特定域搜索到这些陈旧实例。但在生产环境中,可能要跨不同域部署多个流程,从而造成沉重的管理负担。此外,在一次性清除特定域内的所有陈旧实例不可能做到。
作为一种替代方式,可以通过该 SQL 查询查找每个陈旧实例的特有多维数据集实例键 (cube instance key, cikey)。
SELECT CUBE_INSTANCE.cikey, CUBE_INSTANCE.root_id, CUBE_INSTANCE.process_id, CUBE_INSTANCE.domain_ref FROM CUBE_INSTANCE WHERE STATE = 9
一旦识别出了每个陈旧实例的 cikey,就可使用该键通过调用由 SQL 查询找到的每个多维数据集实例 delete_ci(CIKEY) 从 CUBE_INSTANCE 中删除陈旧实例以及其他引用这些多维数据集实例的表。delete_ci(CIKEY) 是一个存储过程,以多维数据集实例作参数;它删除多维数据集实例以及其他引用该多维数据集实例的 BPEL 表上的所有行。
该方法的好处之一是可跨多个域删除陈旧实例(如果删除了 where 条件中的 domain 子句)。它还允许大量清除陈旧实例。这两个好处使 PL/SQL 成为管理生产环境的理想选择。
以下的示例代码演示了如何在 EJB 中使用这些方法列出和删除陈旧实例。
WhereCondition where = WhereConditionHelper.whereInstancesStale(); IInstanceHandle[] instances = getLocator(domainId, domainPassword).listInstances(where); for(int i=0; i<instances.length; i++){ instances.delete(); }
前两行按域返回了所有陈旧实例的 IInstanceHandle bean 数组。之后,使用 IInstanceHandle.delete() 删除所有这些实例。可轻松扩展该代码来包含所有域。
存档旧实例和删除陈旧实例以及处理过的 XML 消息将有助于减小表的大小。结果表明,除非截断或重建表,只是删除行并不会将空间释放回表空间。
使用以下命令重新获取可用空间;可在 Dehydration Store 中针对其他表执行类似命令。 alter table bookings enable row movement; alter table bookings shrink space cascade; alter table cube_scope shrink space; alter table cube_scope disable row movement;
此外,为了防止以后的增长,DBA 可以操纵 PCTFREE、PCTUSED 以及 PCTVERSION 参数。
最后,我们来看一下如何处理运行时失败的实例。
返回失败的实例 BPEL 流程失败的原因可能有多种,如错误输入、不正确的流程设计或外部应用程序不可用,等等。在任何情况下,流程都不会成功完成它的执行并以“fault”状态结束。如果流程由于不正确的设计而失败,则必须修改流程设计并重新部署 BPEL 流程。
然而,如果流程失败是由于错误输入或外部问题(网络故障、外部应用程序不可用)导致,则您可能希望在更正输入或解决了外部问题后重新运行流程。理论上,应使用旧的输入重新执行流程,以便可正确处理最初的请求。
可使用 BPELTest(10.1.3 及以后版本中有提供)实现该目标,这是一个重要的实用程序,可用于在 BPEL 流程上创建和运行测试用例以进行单元测试和集成测试。BPELTest 可模仿合作伙伴调用、执行断言以及提供各种测试结果的信息。(有关详细信息,请查看此处所列的 BPELTest 网络研讨会录像。)
BPELTest 中最重要的功能是其能够从审计跟踪创建测试用例,这也就是所谓的自动测试生成 (Automatic Test Generation)。例如,考虑一下流程实例由于外部应用程序脱机而导致执行失败的情况。理论上,您可能会在外部应用程序重新联机后以完全相同的条件重新运行该流程。但是,该方法可能比较麻烦;它涉及到重新配置流程所有着可控或不可控的外部相关性。
而使用 BPELTest,您可以从失败实例的审计跟踪生成基本的测试用例。生成的测试用例将包含完全仿效合作伙伴的命令,就像失败实例所具有的那样。在遇到不正确的数据时,可使用正确数据修改测试用例。如果导致实例失败的原因是外部应用程序不可用,则只需在应用程序可用时重新运行测试用例即可。
结论 如您所见,可以针对 BPEL Dehydration Store 使用 BPEL 流程管理器 API 和 EJB 或 PL/SQL 将 BPEL 生产环境的管理进行部分自动化。随着部署的 BPEL 流程越来越多,设计可自动化日常任务并主动解决潜在生产问题的实用程序库势在必行。 -------------------------------------------------------------------------------- Stany Blanvalet 是一位 BPEL 与 J2EE 咨询师。之前曾做过 Java EE 架构师。Stany 引进并管理着 Belgacom 的基于 BPEL 的 DSL 供应应用程序,这是一个任务关键的 BPEL 生产系统。他与人共同开发了jaisy-OrabpelInterface 项目,一个适用于 Oracle BPEL 流程管理器的开放源代码的 JMX 监视工具。
|
|
|
[编辑文章 2 次, 最后修改: Pioneer 于 06-6-7 下午5:22] |
|
|
|
楼 10
|
发布时间 : 06-6-7 下午5:23 |
|
作者:
Pioneer
等级: 初级会员 注册日期:2006-5-22 文章:84 活跃指数:373 经验值:331 状态: 离线 |
第 10 部分:使用 BPEL 进行可靠处理 |
引言回复
回复
|
|
|
作者:Michael Cardella 和 Jeremy Bolie
了解如何使用 BPEL 构建高度可靠的可重用业务流程。 随着企业内部 Web 服务和 BPEL 流程的激增,服务质量成为是否采用特殊服务的决定因素。如何确保服务实现所请求的功能,而不受各种障碍(如网络故障或应用程序不可用)的影响?服务能否在不同的业务流程中使用?所有这些问题的答案将决定某个特定业务流程的可重用性。业务流程的可靠性越高,跨多个应用程序的流程的可重用性就越高。 在 BPEL 简明手册的本部分中,我们将介绍一个由多个应用程序组成的业务情形。该情形演示了能够提供可靠功能的 BPEL 流程的必要性,以及如何在不同的业务情形中多次使用此 BPEL 流程。然后,本文将引导您逐步构建一个通过智能重试逻辑提供此高质量服务的 BPEL 流程。此外,您还将了解如何通过出色的异常管理、基于电子邮件的通知以及错误记录来增强此流程。 业务情形 服务可重用性是任何面向服务体系结构 (SOA) 策略的基石。只有能够创建一组可重用服务,企业才能从 SOA 实施中取得真正的价值。这些服务随后将由不同的部门或应用程序在不同的业务环境中使用。除了所提供的实际业务价值以外,服务的成功情况还将推动特定服务的可重用性。服务的故障率是多少?服务能否克服网络中断?服务是否足够灵活,从而实现错误与异常恢复?服务完成请求作业的可靠程度越高,服务在不同业务环境中得到使用的可能性就越高。 看一看图 1 所示的情形:企业需要向不同合作伙伴提供产品的技术文档。文档的访问级别取决于合作伙伴类型以及所请求的产品文档。该信息存储在 Oracle 数据库中。随着合作伙伴加入和离开网络,需要通过多个企业应用程序中的相应审批和更新来修改提供的信息(添加/更新/删除访问权限)。 图 1 授权提供环境 在授权数据库中激活、禁止和修改授权后,必须向 Documentum 发送通知。授权更改的发送顺序必须与其创建顺序一致。必须确保消息的完整性,并且必须维护完整的审计日志并将其记录到中央应用程序数据库日志中。 BPEL 在编排授权激活和禁止方面起到至关重要的作用。此 BPEL 流程将与 TIBCO 消息传递总线紧密协作,以便可靠地向 Documentum 传递消息。它还将负责错误记录和通知。该流程执行任务的效率和可靠性必须足够高,以免因网络中断或 Documentum 应用程序不可用而中断。它应能够不断的尝试操作,直到完成其任务。如何开发能够进行可靠处理的类似 BPEL 流程? 本文的余下部门将详细介绍一个使用 BPEL 提高服务处理质量的策略。创建数据处理重试的关键因素在于数据库。该策略只是用于提高在 BPEL 中运行的流程的可靠性和服务质量这一方法的一部分。 体系结构 下面,让我们了解一下此 BPEL 流程的设计逻辑。 图 2 BPEL 流程逻辑 此 BPEL 流程(从数据库中读取记录并对其进行处理)由 Oracle BPEL 的数据库轮询适配器启动。此 BPEL 流程最后几个操作之一是向数据库报告成功或失败。随后,数据库过程将根据重试尝试的状态和次数来确定是否需要重试该流程,如果确实需要,则将记录重新安排为在将来获取。该流程的最后一步是调用日志服务。除了在数据库中创建日志条目以外,该服务还使用一组规则来确定给定流程中具有某种状态的消息是否应发送通知。如果应发送通知,则它还将选择要使用的电子邮件模板和电子邮件发送列表,邮件中将包含日志中的相应信息。 无论是在问题可以自动更正的情况下,还是在需要人力参与解决问题的情况下,该方法均可以提高可靠性。与合作伙伴重试不同,该方法重试 BPEL 流程的整个执行过程。它的功能丰富,并不仅限于在 BPEL 中创建一个简单的重试循环。 该处理模型易于从外部进行监控和交互。如果在数据库中管理流程的创建日期和上次修改日期,则可以对该数据库运行查询以判断 哪些记录尚未由 BPEL 获取 哪些记录未能及时完成处理 哪些记录已经终止 此外,启动已终止记录的重试以及加速计划的重试也很简单。在实施以上设计时应执行以下三个重要操作: 将已处理的记录的状态存储到数据库中。该状态包括流程状态、下一个流程尝试时间以及处理尝试计数。 创建一个可更新视图(只公开可以处理的记录)。由于数据库适配器无法处理与 SYSDATE 进行比较的 where 子句,因此需要使用视图。 设计用于确定是否重试出现故障的流程以及何时进行重试的逻辑。该信息将在数据库中使用存储过程更新。也可以使用更新合作伙伴链接以及 BPEL 中的其他逻辑执行该操作。 在下一个部分中,您将了解如何构建这样的流程。 构建该示例 下面我们将构建以上介绍的流程。首先,请创建数据库表以支持该流程,然后使用 BPEL PM Designer 建立该流程的模型。 创建数据库对象。由于该流程将重试状态存储到数据库中,因此在创建 BPEL 流程之前需要设计数据库组件。如上所述,需要向数据库中添加的内容包括 更多用于跟踪已处理记录的状态的字段 可更新视图 状态过程可以向包含修改数据的行或与主要表保持一对一关系的并行表中添加其他字段。应添加的主要列包括 Status Process Not Before Retry Count Create DTS Last Modified DTS 状态字段与 BPEL 的数据库轮询适配器标识未处理记录所使用的字段应为同一字段。创建一个规范很有帮助,因为这样做便于标识仍进行处理的记录、已经成功完成的记录以及在出错情况下完成的记录。实现的方法有数字或前缀规范。请查看 示例代码下载 中的 CREATE_TB_DB_POLL_SOURCE.sql。 该视图应只公开其 Process Not Before 列条目早于当前 SYSDATE 或为空的记录。通过该视图还可以轻松地限制应处理的记录数。此外,该视图还可以只公开要处理的记录的主键,从而使视图更简洁。查看随附示例中的 CREATE_VW_ DB_POLL_SOURCE_VW.sql。 状态过程应包含一个用于指示错误的标记,或者也可以使用一个单独的过程来标识错误状态。对于错误状态而言,该过程将标识是否应重试流程实例,以及在需要重试的情况下确定重试时间。随后,该过程应相应地更新记录。一个典型的策略是先进行几次间隔较短的重试,然后再进行大量间隔更长的重试。检查 示例代码下载 中的 SET_DB_POLL_SOURCE_FAULTED.sql。 然后,请创建实际的 BPEL 流程,以便可靠地处理数据库记录。创建数据库轮询流程.该操作涉及几个步骤: 创建一个新的 BPEL 项目。 创建一个空的 BPEL 项目。 图 3 创建一个 BPEL 项目 创建一个数据库轮询适配器。 创建一个新的合作伙伴链接。 单击 Wizard 按钮。 选择 Database Wizard。 指定服务名称 DBPolling。 图 4 创建数据库轮询适配器 配置数据库连接后,选择 Poll for New or Changed Records in a Table 作为操作类型。 图 5 选择操作类型 导入数据库视图 DB_POLL_SOURCE_VW。 接受随后几个屏幕中的默认值(本示例中没有 where 子句)。选择列 ID 作为主键。 对视图执行读取后,该向导需要知道应对记录执行什么操作。选择 Update a Field in the Activities Table (Logical Delete),如下所示。 图 6 选择“Update a Field...” 现在,您将看到 Logical Delete 屏幕。指定要更新的 BPEL_STATE 字段以便从逻辑上删除该行。 图 7 指定 BPEL_STATE 字段 创建一个接收活动。 要向 BPEL 流程中添加接收活动,请执行下列操作: 将接收连接器拖动到在步骤 2 中创建的 DBPolling 合作伙伴链接。 将接收活动重命名为“receive”。 选中 Create Instance 复选框。 单击接收活动弹出窗口上的变量向导,然后创建一个名为 inputVariable 的变量。 图 8 创建一个变量 单击 OK。 BPEL 流程将类似如下所示: 图 9 到目前为止的 BPEL 流程 添加自定义故障定义。 添加自定义故障的前提条件是包含故障定义的 WSDL 必须由某个合作伙伴链接的 WSDL 引用。尽管可以修改任何合作伙伴链接的 WSDL,但如果重新运行该向导,则将重新生成该合作伙伴链接的 WSDL。这意味着如果重新运行该向导,则需要重复向 WSDL 中添加导入的步骤。 要将 BpelFault.wsdl 添加到项目文件夹,请执行下列操作: 在 Oracle JDeveloper 中选择该项目,选择“File/Add to DB_to_JMS.jpr”,然后选择要添加的 BpelFault.wsdl。 将以下行添加到 DBPollingService.wsdl 中的打开的定义标记之后和 types 元素之前。 该 WSDL 对数据的每个部分使用 message part,而不是一个 complex 元素,从而使用同一故障定义作为 BPEL 的默认返回类型。如果 WSDL 没有 message part 部分,BPEL 将创建一个 RPC 样式的 Web 服务,而非文档样式的 Web 服务。 创建 BPEL 流程的余下部分。 下面我们将将不准备逐步完成构建 BPEL 流程的余下步骤,我们将了解一下最终流程的情况,然后获得各个元素,。整个 BPEL 流程如下。 图 10 整个 BPEL 流程 下面看一看此 BPEL 流程的各个元素。主要部分包括 初始块(位于流程作用域中) 处理 回复/报告最终状态 记录 重新引发故障 初始块 这是处理作用域中的第一组任务。顾名思义,它负责流程初始化以及设置全局变量、错误变量和日志变量。如图 11 所示, 示例代码下载 中包含下列活动。 图 11 初始化流程的步骤流 Checkpoint(可选) 检查点强制脱水。尽管它略微降低了执行速度,但可以保证启动的每个 BPEL 流程实例将显示在控制台中。 BPEL 控制台只向最后一个脱水点显示执行状态。某些错误将终止执行而不允许向控制台报告状态。此外,某些合作伙伴链接同步调用可以无限期地处于等待状态,而不允许报告脱水状态。 global_init 它用于初始化几个由异常处理机制使用的“常数”。该活动应在流程开始之前执行,即在任何有可能引发故障的操作之前执行。 init_log init_log 任务在 Java 中初始化一个时间,以便可以轻松地跟踪相应的处理时间(精确到毫秒)。仅当流程集成的日志系统将收集精确到毫秒的执行时间时才需要该任务。 处理 现在,我们将了解一下处理核心。看一看下面的 BPEL 流程流。 图 12 BPEL 流程流 流程流。初始化变量后,该流程开始读取数据库。它将当前状态更新为“processing”,然后读取数据库记录。验证数据的正确性后,它将转换消息以将其传递到目标。在将消息发送到目地的之前,它将数据库中的当前状态更新为“sending”。最后,它将消息发送到目标(在该示例中为 JMS 总线)。如果流程长时间运行或存在一些关键的风险区域,则流程在遍历流中的关键点时更新数据库中的状态这一方法尤其有用。读取数据库操作(ReadDB 合作伙伴链接)已经与启动流程的视图(DBPolling 合作伙伴链接)分开。这使视图比较简单,并消除了无法对 BPEL 中的视图使用连接的限制。 异常处理。较大的作用域中包含的每个作用域可以捕获所有异常并抛出内部定义的故障。例如,如果在读取数据库记录期间出现错误,则作用域将捕获该错误,将错误状态设置为“Error while trying to read in data to be processed”并将该错误抛到父作用域。这意味着每个故障均定位到更精确的级别。 每当主要处理的内部出现错误时,均会抛出内部类型的故障。随后,外部捕获块将捕获该故障。使用该策略时,应注意不要在 catchall 块中捕获自定义故障,因为这会导致丢失所有定制故障信息。如果在作用范围内部抛出了定制故障,则除了使用将捕获任何其他错误的 catchall 块以外,还将使用捕获该特定故障的 catch 块。 可重用性.必须注意的是,处理逻辑基于业务需要。在本情形中,该流程将消息可靠地传递到 JMS 目标。但在实际环境中,处理方法可能有所不同,其中既包括更新银行帐户,也包括创建新客户,还包括同步订单数据。该流程提供的可靠性保持一致。此外,还可以可靠地重用该流程。 回复/报告最终状态 图 13 描绘最终状态更新的流 处理状态在数据库中更新为 SUCCESS 或该流程执行过程中遇到的故障(如上所示)。尽管该更新是可选的,但仍建议您启用外部应用程序来监视所有流程实例从头到尾的进度。 本示例使用数据库过程(SetFaulted 合作伙伴链接)来报告最终状态。尽管可以在 BPEL 内部进行报告,但延迟对数据库过程的更新可以简化 BPEL 流程。 指示最终状态为 unsuccessful 的报告将触发流程重试。如果重试流程的次数未达到最大次数,则将在某个间隔过后重试该流程。 记录 记录流程收集处理信息并将其发送给集中化的记录程序。该信息最重要的部分是错误的严重等级和消息代码。记录具有以下优点: 它生成一个可以通过数据库轻松搜索到的审计日志。 严重等级和消息代码决定是否发送通知。 消息包含信息的某些重要方面,如 BPEL 进程实例以及启动处理的行的主键。这使故障排除程序可以在 BPEL 控制台中快速找到该进程,或在数据库中找到数据。 重新抛出故障 图 14 为找出错误流程而抛出故障 如图 14 所示,最终的重新抛出故障简化了有问题的流程实例的查找。可以轻松地在 BPEL 控制台中找到这些流程。当最终重新引发故障时,流程实例将在控制台中得到标记,您也可以过滤以只显示结束时出现故障 (Canceled) 的流程。 BPEL 流程开发到此结束。该流程应与其他实践组合使用以提供最佳的可靠性;例子包括数据库监控、同步事务以及日志监控。该流程使您可以轻松地标识已经成功、最终出现故障或未及时完成其处理的记录。所有这些信息对于实际的业务环境很有帮助,实际业务环境中处理的每个记录可能价值数千美元,而违反 SLA 可能导致客户不满。 结论 文本演示了如何构建一个高度可靠地执行其任务的可重用业务流程。您构建的流程可以可靠地向 JMS 目标发送消息,并且由于它的可重用性很高,因此还可以使用它可靠地提供任何业务功能。 所有业务异常均无法在 BPEL 流程中捕获。提供高质量服务并不仅限于流程级别。必须将其与高效的审计日志监控、通知相应的相关人员、在数据和流程级别排除异常以及在每个处理阶段实现透明性相结合。任何可靠的流程均应满足所有这些要求。 -------------------------------------------------------------------------------- Michael Cardella 是 Qualcomm CDMA Technologies (QCT) 的高级工程师。Michael 在自定义应用程序开发小组工作,主要从事 Web 服务以及与业务流程相关的应用程序开发。此前,他曾担任过领先级 Web 服务安全性和管理产品的主要设计师。 Jeremy Bolie 是 QCT 的高级 IT 经理,他负责管理自定义应用程序和 Documentum 开发小组。Jeremy 在 Java 和 Oracle 技术方面具有 10 年以上的工作经验,从 1990 年年底开始一直从事 Web 服务和面向服务体系结构方面的工作。
|
|
|
[编辑文章 2 次, 最后修改: Pioneer 于 06-6-7 下午5:26] |
|
|
|
|