级别: 中级 Andrew Ferrier, WebSphere ESB 顾问, IBM Software Services, IBM
2009 年 10 月 12 日 本文向您介绍在 WebSphere Integration Developer 中开发中介流(mediation flow)组件的过程,以帮助您最小化开发时间、按逻辑顺序进行开发、避免后续工作以及创建可维护性更好的工件。
简介
本文向您展示如何在 IBM® WebSphere® Integration Developer 内开发中介流组件并将其部署于 WebSphere ESB 或 WebSphere Process Server 之上。本文还揭示了如何以一种特定的顺序构建这些流,以最小化开发时间和后续的工作,并促进重构和调试。
本文基于大量中介流开发经验,并假设您已经具有了一些 WebSphere Integration Developer 开发和中介流开发的经验。本文不会过多介绍术语和构建中介流的细节,而只会给出一些经充分证实的步骤以使中介模块开发更为有效,后续工作更少。
在开始之前,您需要了解:
- 您将要使用的是哪些界面?这些界面是您设计的,还是第三方提供的?
- 您将要采取哪些绑定类型?您会将中介流公开为 Web 服务么?该中介流是否会使用一个基于 JMS 或 MQ 的服务?
- 您的服务有何作用?您知道该如何构建它么?您最有可能使用哪些中介流原语?
开始之前,您可能并不知道所有这些细节,但是您知道得越多,日后,您重做此中介流的可能性越小。在开发下一个中介流之前,先阅读本篇文章应该有助于加深您对开始工作前的预备知识的理解。
定义并寻找将要使用的界面
首先要做的一件事情是建立您将要使用的界面,二者均在前端(所创建的服务如何被公开)和后端(所调用的服务如何被公开)。好的 SOA 原则一般要求松散耦合和严格定义的服务界面,因此您的其余创建应该受这些界面的约束。界面可以来自第三方,也可以自己定义。如果自己定义,最好是为大块的请求和响应信息定义一个包装器类型对象,以避免后续出现细微问题。图 1 和 2 给出了一些包装器类型的对象的例子:
图 1. 包装器类型的界面示例
图 2. 包装器类型示例
总之,如果您现在花些时间把界面处理好,那么将来会省很多事。虽然以后能够进行重构和更改,但是若能提前就对这些界面进行可靠的定义,事情会进展得更顺利,日后对它们的更改也会降到最少。
任何时候,在需要界面抛出故障时,请务必确保添加模型化了的故障。处理模型化了的故障总是要比处理非模型化的故障简单。如下所示是一个具有模型化的故障的例子:
图 3. 具有模型化的故障的示例界面
另外,请确保向此模型化的故障添加合适的业务或技术数据。(模型化了的故障有时又被称为服务业务异常 或已检测的故障。不过,没有理由将它们规定为业务类型的故障:应该在任何需要抛出异常的情况下使用。)
定义导出和导入
现在,可以将这些界面置于一个组装图中以便定义导入和导出。如下所示是中介模块与外界通信的方式:
图 4. 创建导入和导出
如果您不喜欢为导入和导出所生成的这些名称,可以现在就更改它们。它们在您的环境中嵌入得越深,日后就越难对它们进行更改。
定义中介流
现在,把这个中介流组件本身置于组装图上,并将其连接到导入和导出。请不要忘了重命名该组件。本步骤让您能够在组件上定义这些界面和引用,并完成模块的高级层面,正如下面的组装图所示:
图 5. 组装图的高级层面
上述示例比较简单,只指定了一个导出和导入,但如果需要更多,可以现在添加。
为中介流中的每一个操作定义实现
接下来,继续进行自上而下的开发方式,通过创建一个新的实现来开始实现中介流组件。为左侧的每个操作(正在公开的)定义一个实现(除非您不想现在就实现整个界面)。
对于每个操作,您都需要决定是否使用中介流的 callout 特性来为每个后端服务创建一个完整的请求和响应流,或者是否仅使用一连串 Service Invoke 原语来调用每个后端服务。这个选择并不是一个技术问题,而是一个概念性的设计问题。总之,最好是通过拖动到达某个引用上的某个操作,因此如果中介流将要调用的是一个明显的主引用,则可以定义单个的 callout。如下是一个例子:
图 6. 单个的 callout 定义
有可能会出现这种情况,比如,对应于此 callout 的后端服务很复杂,而中介流的其余部分只是用经 Service Invoke 原语从其他服务检索来的数据扩充了最终发送给该流的消息。
如果中介流调用多个引用,而其中没有一个引用明显是主引用,那么它们应该被视为对等的,并最好是使用
Service Invoke 原语来调用后端服务。如下是一个例子:
图 7. 为对等后端调用服务
这些方法之间没有重要的技术上的差异,但它却让随后维护或读取流的人员清晰地意识到几种服务之间的差别:调用一个主后端并仅使用到其他服务的 callout 来扩大其行为的服务,以及调用几个对等服务来执行其任务的服务。在这两种情况下,中介流引擎的底层行为非常类似。
定义和指定想要使用的上下文对象
下一个步骤是定义想要使用的中介流上下文(correlation、transient 及 shared)。在这个阶段执行此步骤非常重要,因为定义会被放到您之后可能定义的 XSLT 或 BO 映射,所以现在定义它们会让日后的工作减到最少。一种好的做法是为想要使用的上下文定义一个可以包含大量相关数据的包装器 BO 类型(可能存储在此模块自身内)。这么做非常重要,因为每个上下文都可能只包含一个特定类型的对象。并且,包装器还让您能够在日后向此上下文添加字段。如下所示的是一个包装器业务对象的例子:
图 8. correlation 上下文的包装器对象
这个 transient 上下文多少有点像某种编程语言中的一组本地变量。通常,您可以使用它来存储流内由一个中介原语创建、由另外一个中介原语使用的临时数据。比如,一个中介原语会覆盖此 Service Message Object 的 /body 部分,并且如果还有需要保存的数据,也可以保存在这个 transient 上下文内。因此,需要提前考虑好所需要的字段。
correlation 上下文通常用于中介流内请求流和响应流之间所共享的数据。例如,当要求为每个为登录目的而共享的消息使用一个惟一 ID 时,也可以使用它。当然,您仍然需要提前了解自己的需求以便能够定义 correlation 上下文包装器类型。当处理中介流中的分支逻辑时,一般都会使用 shared 上下文。更多信息,请参见 developerWorks 文章 WebSphere ESB V6.1 中的聚合功能。
定义中介流的消息类型流
现在,通过放入原语就可以开始定义中介流本身了。
首先,通过添加预期要用到的所有原语并将它们通过编程组织在一起来定义中介流的基本结构。在这个阶段,一般不会对这些原语设置属性。在这个阶段中尤其重要的是获得正确的消息类型:换言之,就是要确保将各种消息原语的所有终端都设置为理想的消息类型。定义全程都要使用的中介流格式和类型将会使得日后回过头来设置这些原语上的属性更为简单,而不是并行处理这二者。而且它还能提供某些验证以便中介流的基本结构能够互相一致。如下是要遵守的一些规则:
- 从左向右工作:首先创建您想要使用的第一个原语,并将其连接到输入节点。然后创建第二个原语,并将其连接到第一个原语,以此类推。
- 每当创建一个输出终端数量可变的原语时,可按照您的进展创建这些终端以确保流的所有可能路径是明显的。
- 每当创建一个输出终端类型不必与输入终端类型(比如 Custom Mediation、XSLT 或 BO Map)相同的原语时,可按您的进展手动定义输出终端类型,以确保终端的类型均被设置完毕。
- 每当创建一个 Set Message Type 或 Type Filter 的原语时,可按您的进展定义 Message Type Refinements 表或 Filters 表,以确保下行的(逻辑上向右)原语能够感知到消息的该部分要比上行的更具体一些。本条规则是上述要求不在此阶段设置中介属性的那条规则的一个例外。
- 当创建流内的一个 Service Invoke 原语时,此工具会要求您指定应被调用的 partner 引用和操作。请准确对之进行定义,因为它会自动为您设置合适的终端类型。
- 在这个阶段,按您的进展需要将所有原语的名称从默认名称改为对您有意义的名称或者满足您命名约定的名称。这么做会确保您日后创建的任何工件的名称都将会从原语名称自动获得并准确匹配。
- 只要原语不更改消息类型,您无需包括进任何非功能性的原语,比如进行日志记录的那些原语。可以日后再插入它们。
有时,也可以从右侧开始,或者同时从两个方向开始。这么做在简单的流中会非常有用,尤其是当进行映射时:因为 Mediation Flow Editor 知道输出节点的类型,所以它可以自动设置原语上的输出终端类型。以下是一个例子:
图 9. 从右侧工作的例子
被突出显示的终端类型不应手动设置,而只要将其连接到 Partner callout 即可,这样一来,其类型会被自动设置。
定义映射
现在,定义 XSLT 上的映射以及要置于中介流之内的 BO 映射原语。由于您已经定义了流内的所有中介原语上的终端类型,此任务应该非常直观和简单。您只需简单定义一个新映射,此映射的输入和输出类型将会被自动设置,如下所示:
图 10. XSLT Map 的定义,显示了自动类型引用
设置所有属性
现在,可以正确设置所有其余中介原语上的属性了,这些属性之前尚未设定。不要错过任何一个!
定义消息类型不变的原语
如上所述,有些人会将定制中介用于日志记录或其他非功能性的目的。如果这样的话(并且它们未曾更改消息类型),不妨将它们置于最后,甚至是在第一轮测试结束后,正确设置终端类型就会更简单。对于 Service Registry V6.2,很容易做到这一点:只需将新的原语放置于连接上,它会被插入到合适的位置。对于终端类型灵活的那些原语,比如 Custom Mediation,输出终端类型还是需要被正确设置。
测试
至此,已经完成了流的初始构建,现在是测试的时候了!WebSphere Integration Developer 具有一个单元测试架构,非常适合测试您所构建的这个中介流。更多信息,请参见参考资料部分。
致谢
作者要感谢 IBM 的 Kim Clark 和 Dave George,感谢他们为本文提供的反馈意见及帮助。
参考资料
关于作者  | 
|  | Andrew Ferrier 是 IBM Software Services 的一名顾问,专攻 WebSphere ESB。他定期为欧洲及之外的客户服务,帮助他们更高效地使用 WebSphere ESB 和其他的 IBM 产品。他在很多地方,尤其是在他与别人共建的 SOA Tips 'n' Tricks 博客上,撰写过有关这些主题的大量文章。 |
对本文的评价
|