WebSphere Enterprise Service Bus 与 WebSphere Integration Developer 入门

本文将向开发人员介绍 IBM WebSphere Enterprise Service Bus server 及其附带的工具 WebSphere Integration Developer。本文描述如何完成以下任务:1) 开发提供基本 Web 服务的中介流;2) 开发中间流,以连接到此服务(使用该工具提供的若干预先构建的中介功能所提供的更为复杂的路由逻辑);3) 使用工具测试机制和独立的基于 JSP 的前端来部署和测试这些流。

Calum Byrom (byromca@uk.ibm.com), 助理软件工程师,WebSphere ESB Function and System Test 团队, IBM

Calum Byrom 的照片Calum Byrom 是位于英国的 IBM Hursley Software Lab 的 WebSphere ESB Function and System Test 团队的助理软件工程师。自从 2002 年加入 IBM 后,他曾在各个 WebSphere 和 Java 部门担任过各种职位。在此前,他曾在英国的曼彻斯特大学和爱丁堡大学从事过长时间的物理学方面的研究。他的专业领域包括 Java、软件测试、使用 Perl-CGI 的网页开发和使用各种脚本预演的流程自动化。您可以通过 byromca@uk.ibm.com 与 Calum 联系。



2006 年 4 月 20 日

引言

IBM® WebSphere® Enterprise Service Bus (ESB) 服务器及其关联的工具 WebSphere Integration Developer 是两款新 IBM 产品,可用于提高异类系统之间的连接性。就实质而言,WebSphere Integration Developer 可帮助您开发框架(中介流),用于在将消息相应地路由到不同的目的地前根据需要处理传入数据(消息)、调整和记录内容。您可以随后使用 WebSphere ESB 来运行这些流,以处理其他特性(如安全性、性能、可靠性和事务管理)。本文说明如何完成以下任务:

  • 开发简单中介来公开 Web 服务。
  • 开发更为复杂的中介来连接到此 Web 服务,并提供逻辑来对传入消息进行筛选、转换和路由。
  • 使用 WebSphere Integration Developer 测试客户端和基于 JSP Web 的前端调用生成的中介流,并检查生成的结果。

首先,定义接口,然后使用工具自动生成必要的代码,以建立一个用于连接到中介流的简单 Web 服务,如下面的部分中所述。

创建库接口

Web 服务使用接口进行定义,接口提供调用该服务所需的所有信息(即所需的输入和输出参数的类型和 Web 服务的位置)。虽然可以通过使用 WebSphere Integration Developer 中的 Web Services Explorer 导入现有外部 Web 服务接口,但本文将演示的是如何从头开发 Web 服务,从而说明整个相关的过程。

打开 WebSphere Integration Developer 并关闭欢迎窗格,以进入 Business Integration 透视图。如果碰巧关闭了此透视图,可以通过选择 Window => Open Perspective => Other => Business Integration 来重新打开它:

图 1.1.Business Integration 透视图
图 1.1.Business Integration 透视图

首先,创建一个合适的项目,以在其中存储 Web 服务接口:

  1. 选择 File => New => Other 并从向导中选择 Library
    图 1.2.New Project 向导
    图 1.2.New Project 向导
  2. 将 Library Name 指定为 StockQuoteLibrary,然后单击 Finish
    图 1.3.New Library 向导
    图 1.3.New Library 向导

现在开始创建接口本身:

  1. 在工具左侧的 Business Integration Navigator 中展开 StockQuoteLibrary 项目,然后右键单击 Interfaces => New => Interface
    图 1.4.创建新接口
    图 1.4.创建新接口
  2. 提供 StockQuoteService 作为 Name,然后单击 Finish
    图 1.5.New Interface 向导
    图 1.5.New Interface 向导

现在将在主显示中打开新接口,不过目前其大部分为空白,因为我们尚未定义任何内容。每个 Web 服务都要实现一个效用函数,我们需要在定义接口时加以指定。为了简单起见,我们将使用传统的“stock quote”服务——该服务接收股票名称,并返回表示该股票价格的浮点数。我们需要从类型的服务定义“双向的”,因为其中会涉及到请求和响应消息:

  1. 单击 Add Request Response Operation,即 Define Operations 右侧的第一个图标,以向接口表添加一个行。
  2. 将此行中的缺省名称由 operation1 更改为 getQuote,然后单击 Add Input(Define Operations 右侧的第三个图标)。
  3. 将输入参数的缺省名称由 input1 更改为 inputGetQuote
  4. 单击 Type 列并选择 New,以创建一个新业务对象类型来充当输入。在 Data Type Selection 弹出菜单中单击 New
    图 1.6.定义接口
    图 1.6.定义接口
  5. 在随即打开的 New Business Object 对话框中(图 1.7),指定名称 StockName 并单击 Finish => OK
    图 1.7.New Business Object 向导
    图 1.7.New Business Object 向导
  6. StockName 业务对象现在应出现在 Type 列中。右键单击它,并选择 Open in Business Object Editor。将随即打开一个新编辑器,可以在其中详细定义这个新业务对象。
  7. 单击 Business object 右侧的 Add an attribute to a business object,并将缺省值 attribute1 更改为 name
    图 1.8.StockName 业务对象接口
    图 1.8.StockName 业务对象接口
  8. 关闭面板,并选择保存更改;已经定义了一个简单的业务对象,该对象仅对一个 String 值进行包装。回到接口面板,进行类似的过程,以使用新类型 StockQuote 定义名为 outputGetQuote 的输出参数,该参数对名为 price 的浮点值进行包装。
  9. 保存接口:按 Ctrl-S,或关闭窗口,并在有屏幕提示时单击 Yes

现在已经完成了接口的定义,该接口现在应与下面的图 1.9 所示内容类似。虽然可以直接在使用接口的中介项目中对其进行定义和存储(通过采用上述方式在独立的库项目中进行创建),但仍然可以十分方便的供其他中介项目重用。

图 1.9.已完成的 StockQuote 接口
图 1.9.已完成的 StockQuote 接口

实现 Web 服务

既然已经定义了 Web 服务接口,接下来就需要创建此服务的一个本地实现,以便通过中介流进行访问。和处理接口一样,首先创建一个合适的项目来承载此服务:

  1. 选择 File => New => Other ,并从向导中选择 Mediation Module
  2. 在 New Mediation Module 弹出对话框中输入 StockQuoteService 作为 Module Name,并确保将 get Runtime specified 设置为实际的 WebSphere ESB 服务器或 WebSphere ESB 服务器存根。保持缺省设置的选中状态,并单击 Next
  3. 在下一个面板中选择前面创建的 StockQuoteLibrary,并单击 Finish

工具左侧的 Business Integration Navigator 现在将显示新项目。对其进行扩展,并找到子组件 StockQuoteService。它表示中介模块的组装关系图,可在其中指定高级中介组件的配置(如导入和导出连接、中介流的数量和参数等等)。要实现此接口,请执行以下操作:

  1. 双击此子组件。将随即打开 Assembly Diagram Editor,在其中包含单个中介流组件 Mediation1。此编辑器的重要功能如下图所示:
    图 2.1.新 StockQuoteService 中介模块的组装关系图
    图 2.1.新 StockQuoteService 中介模块的组装关系图
  2. 单击中介流组件两次,然后将名称更改为 StockQuoteServiceMediation。(在这些关系图中使用的名称并不是基础代码实际使用的名称,但这些名称更便于从用户的角度进行理解,并简化了输出到系统日志的信息。)
  3. 从面板左侧的图标菜单中选择带绿色箭头的图标(如上面的图 2.1 中所示),以展开菜单。然后选择下箭头图标(表示导出组件)。单击 Assembly Diagram 画布,以将导出组件添加到组装关系图,并将其重命名为 StockQuoteServiceExport
  4. 单击底部的图标(图标菜单中的 Wire),然后单击 StockQuoteServiceExportStockQuoteServiceMediation,以将二者连接起来。(可以单击导出组件,将产生的连接线拖放到中介组件,然后释放鼠标按钮,从而创建相同的连接。)
  5. 现在将显示一个面板 (Add Wire),说明连接操作将向导出添加与中介组件所使用的接口相匹配的接口,从而将此接口公开,以供其他模块使用。选择 Always create without prompt 并单击 OK
  6. 在下一个窗口 (Add Interface) 中选择前面定义的 StockQuoteService 接口,并单击 OK
  7. Assembly Diagram Editor 现在应在导出和中介组件之间显示一个链接。请注意,每个组件上都指定了匹配接口,使用包含“I”字符的圆圈表示。到目前为止,此关系图中已经有了一个导出组件(将此中介流公开,以供其他流使用)和一个中介组件(其中包含实际中介流的详细信息)。所需的最后一个组件是要调用的 Web 服务的表示形式。要创建此组件,请单击信封图标,选择下部具有“J”字符的图标,然后单击画布。
  8. 和前面一样,将此组件重命名为 StockQuoteService,并将中介组件连接到其上(选择 StockQuoteLibrary 接口作为要添加的引用)。此引用允许通过链接中介组件 StockQuoteServiceMediation 来访问 Java 组件。它在编辑器中以图形方式显示为包含 1..1 的框形。
  9. 最后,为了使得画布更为有条理,请右键单击编辑器画布,并选择 Arrange Contents Automatically,然后保存更改。

现在中介流的基本框架已经成形,应该与下面的图 2.2 所示类似。蓝色的惊叹号表示组件的基础实现尚未完成。

图 2.2.已完成的 StockQuoteService 组装关系图
图 2.2.已完成的 StockQuoteService 组装关系图

我们将首先实现 Java 组件:

  1. 双击 Java 组件图标,并选择缺省选项。将自动在文本编辑器中打开 Java 类 StockQuoteServiceImpl(基于 StockQuoteService 库)。该类提供了接口中详细说明的所有方法的基本框架。在我们的简单示例中,这意味着我们仅使用 getQuote 方法和 getMyService 方法返回类实例。
  2. 使用下面部分中给出的代码替换 getQuote 方法。除了提供合适的输出日志外,它还将使用 Web 服务接口创建和填充用于输出的有效业务对象。返回值取决于输入消息的内容,具体将在下面进行详细讨论。
    清单 1. StockQuoteServiceImpl.java 中 getQuote 方法的代码
    public DataObject getQuote(DataObject inputGetQuote) throws
       ServiceBusinessException {
       // retrieve the String value of the 'name' attribute
       System.out.println("StockQuoteServiceImpl - getQuote : Get name from inputGetQuote");
       String name = inputGetQuote.getString("name");
       System.out.println("StockQuoteServiceImpl -	getQuote : name = " + name);
       // Now get the BO Factory to create the reply from
       System.out.println("StockQuoteServiceImpl - getQuote : Create BOFactory");
       ServiceManager serviceManager = new ServiceManager();
       BOFactory bofactory =
          (BOFactory) serviceManager.locateService("com/ibm/websphere/bo/BOFactory");
       // Create the output message structure - as specified by the StockQuoteSerice interface
       System.out.println("StockQuoteServiceImpl - getQuote : Create getQuoteResponse");
       DataObject getQuoteResponse = bofactory.createByElement(
          "http://StockQuoteLibrary/StockQuoteService",
          "getQuoteResponse");
       // Now create the Data Object to populate with the return value
       System.out.println("StockQuoteServiceImpl - getQuote : Create outputGetQuote");
       DataObject outputGetQuote = getQuoteResponse.createDataObject("outputGetQuote");
       // And finally, set the appropriate return value
       if (name.equals("IBMvetted")) {
          System.out.println("StockQuoteServiceImpl - getQuote : Set the price to 100.00f");
          outputGetQuote.setFloat("price", 100.00f);
       } else if (name.equals("IBM")) {
          System.out.println("StockQuoteServiceImpl - getQuote : Accessed with not vetted input"
             + " - return old stockquote price, 80.00f");
          outputGetQuote.setFloat("price", 80.00f);
       } else {
          System.out.println("StockQuoteServiceImpl - getQuote : Unrecognised stockquote name"
             + " - set price to 0.00f");
          outputGetQuote.setFloat("price", 0.00f);
       }
       return outputGetQuote; 
    }
  3. WebSphere Integration Developer 应会突出显示此新代码中的一些错误,这些错误是由于无法解析引用该方法的类引起的。要导入这些类,请单击右键,并选择 Source => Organise Imports

关闭并保存该 Java 类,然后通过双击 Mediation 组件并选择缺省值来实现该组件。将随即打开双面板 Mediation Flow Editor。顶部的面板 Operation Connections 窗格中显示对中介组件可用的接口和引用。底部的窗格(Mediation Flow 窗格)显示实际的中介流:

图 2.3.Mediation Flow Editor
图 2.3.Mediation Flow Editor

此中介模块允许调用服务(由 Java 组件表示),因此流应该为简单而直接的连接。要完成实现,请执行以下操作:

  1. 在顶部窗格左侧的接口框中单击 getQuote 操作,以在下面的 Mediation Flow 窗格中打开流。此流最初包含两个未连接的节点,分别表示消息将进入 (StockQuoteService_getQuote_Input) 和退出 (StockQuoteService_getQuote_InputResponse) 流的位置。由于顶部窗格中的 StockQuoteServicePartner 引用未连接到接口,因此流只能直接返回消息,而不能将其传递到其他位置供其他中介组件进行进一步的处理。
  2. 为了让中介组件访问前面定义的 Java 组件,在顶部面板中,通过在两个 getQuote 操作间单击并从左拖到右将接口和引用联接起来。将随即在底部窗格创建新节点 StockQuoteService_getQuote_Callout
    图 2.4.在 Mediation Flow Editor 中连接接口和引用
    图 2.4.在 Mediation Flow Editor 中连接接口和引用

现在我们将创建严格意义上的第一个中介流。由于此流的主要目的是为了提供到 Java 组件的连接,因此我们将使相应的内容尽量简单一些。在 Mediation Flow 面板左侧的菜单中的图标表示一组可用的中介原语。这些原语提供了预先构建的功能单元,以作为中介流的基本构建块使用,如图 2.5 中所示:

图 2.5.中介原语选择面板
图 2.5.中介原语选择面板
  1. 选择 Message Logger 中介原语(图标为页面上重叠一个信封),并单击 Mediation Flow 画布。将在流中创建一个 Message Logger 原语 (MessageLogger1),其任务是自动将通过其的消息写入数据库,以便稍后在数据库中对此消息进行检查(有关详细信息,请参阅检查 Message Logger 缺省数据库)。
  2. 右键单击 MessageLogger1 并选择 Show in Properties,从而在 WebSphere Integration Developer 底部打开视图,以在其中查找进一步的信息和指定配置细节,如下面的图 2.6 中所示。其中最有意义的是 Details 子视图,可以在其中指定不同的数据库细节。由于将自动创建缺省 Cloudscape 数据库,因此请保持其最初的设置:
    图 2.6.检查 Message Logger 原语的详细信息
    图 2.6.检查 Message Logger 原语的详细信息
  3. 请对编辑器画布中左侧和右侧中介节点上的小框加以注意。这些框表示输入、输出和失败端子,用于提供到其他中介原语的连接,从而创建有用的中介流(要确定各个框的情况,请将鼠标悬停在其上即可)。单击 Input 节点的输出端子并将生成的连接线拖动到 MessageLogger1 的输入端子,从而将其连接到一起。采用类似的方法将 MessageLogger1 联接到 Callout 节点。要处理错误恢复,可以使用失败端子来指定 Message Logger 原语引发异常时应采用的独立路由。为了暂时使事务保持简单,请使此端子保持未连接状态。完成的流应与以下所示类似:
    图 2.7:StockQuoteService 的已完成请求中介流
    图 2.7:StockQuoteService 的已完成请求中介流
  4. 在 Mediation Flow 窗格的底部单击 Response:getQuote 选项卡,以切换到表示调用 Web 服务后访问的中介流(响应流)的画布。
  5. 重复上述过程,以添加一个 Message Logger 原语并将其连接到 CalloutResponse 和 InputResponse 节点:
    图 2.8.已完成的 StockQuoteService 响应中介流
    图 2.8.已完成的 StockQuoteService 响应中介流
  6. 关闭 Mediation Flow Editor,并保存更改,然后将更改保存到相关的组装关系图中。现在已经完成了第一个中介模块!

创建更为高级的中介模块

下一步是开发更为复杂的中介模块来连接到刚刚创建的模块。此模块将对传入的消息筛选和调整,从而根据消息的内容提供不同的中介路由和不同的结果。此处的示例基于一个实际的场景,在此类场景中,可能会采用多种方式连接单个 Web 服务。此处,我们将股票报价服务和其他业务逻辑合并,以模拟根据输入消息内容强制实现“服务水平”的情况:

  1. 重复在上一部分中使用的过程,创建一个名为 StockQuoteMediation 的中介模块(使用 StockQuoteLibrary 接口)。
  2. 打开 Assembly Diagram Editor,添加一个导出组件,并将其连接到该中介组件(和前面一样,通过选择现有的接口 StockQuoteService)。
  3. 由于此中介模块旨在提供到我们刚刚定义的模块的连接,因此需要一个导入组件。可以使用侧菜单添加它(具有绿色水平箭头的图标),但这要求进行额外的手动配置,以设置到 StockQuoteService 模块的连接。您可以转而采用自动方式定义此配置。为了完成此任务,请在 Business Integration Navigator 中展开 StockQuoteService 模块,然后展开下面的 StockQuoteService 文件夹来查看此模块的导出组件 StockQuoteServiceExport。通过选择 Import with SCA Bindings,以将其拖放到当前中介模块的 Assembly Diagram Editor。将会添加一个导入组件,可提供到 StockQuoteService 模块中的导出组件的直接连接:
    图 3.1.从现有导出组件创建导入组件
    >图 3.1.从现有导出组件创建导入组件
  4. 连接这个新的导入组件,并相应地对编辑器的内容进行重命名,然后保存更改:
    图 3.2.已完成的 StockQuoteMediation 组装关系图
    图 3.2.已完成的 StockQuoteMediation 组装关系图

现在,双击中介组件,接受所提供的缺省设置,并按照如下所示进行实现:

  1. 按照和前面一样的方式进行联接接口和引用操作,以允许连接到 StockQuoteService 导入组件和 StockQuoteService 模块。
  2. 向 Mediation Flow Editor 画布添加一个 Message Filter 原语(带有两个箭头的信封图标)。此原语允许根据有效负载内容将消息路由到不同目的地。可以创建其他输出端子,然后将其与选择条件相关联:
    1. 将输入节点的输出端子连接到筛选原语的输入。
    2. 右键单击筛选器,选择 Add Output Terminal,并接受弹出对话框中的缺省值。这样就向该中介原语添加了一个新的端子,名为 match1
    3. 再次右键单击筛选器,并选择 Show In Properties,然后访问下方视图中的 Details 选项卡。您的屏幕显示应与以下所示类似:
      图 3.3.StockQuoteMediation 流(添加了 Message Filter 原语,并显示 Details)
      图 3.3:StockQuoteMediation 流(添加了 Message Filter 原语,并显示 Details 选项卡)
    4. 在此 Details 视图中,单击 Add 并选择 Custom XPath
    5. 在 XPath Expression Builder 窗口中,展开 body : getQuoteRequestMsg 结构,并单击 name : string,以在 XPath Location:框中选择它。
    6. 在 Condition: 行中单击 Location 值然后选择 self::node()
    7. 单击 Value,选择 String,然后输入字符串 IBM
    8. 面板底部的 Full XPath Expression 值现在应为 /body/getQuote/inputGetQuote/name[self::node()="IBM"],如下面的图 3.4 中所示。单击 OK 并验证 Terminal name 是否与刚刚添加的端子匹配 (match1)。然后单击 Finish
      图 3.4.已完成的 XPath Expression Builder
      图 3.4.已完成的 XPath Expression Builder
    9. 重复第 2 步到第 8 步,以添加名为 match2 的新输出端子(应与 IBMold 而不是 IBM 匹配)。
    10. 将此新端子连接到 StockQuoteServicePartner Callout 节点。
    11. 最后要配置分发模式:从 Distribution 下拉菜单中选择 All,以允许访问传入消息满足筛选条件的所有输出端子。

    最终的排列情况应与以下所示类似:

    图 3.5.已完成 Message Filter 原语的 StockQuoteMediation 流
    图 3.5.已完成 Message Filter 原语的 StockQuoteMediation 流

    您可能已经注意到,我们现在使用了一个筛选器来检查输入消息的值(假定使用了接口指定的正确格式)。如果相应的值等于 IBMIBMold,则指定的端子将传递该输入消息,并访问相应的后续连接。

  3. 向画布添加一个 Message Logger 原语,并将 Message Filter 的缺省端子连接到其输入。如果其他端子上用户定义的筛选器未为传入消息产生有效的匹配,则将触发缺省筛选器端子。
  4. 添加一个 Stop 原语(红色方形图标)。将 Message Logger 原语的输出连接到其上,如下面的图 3.6 中所示。Stop 原语允许中介流完全挂起。在本例中,它用于结束通过 Message Filter 缺省端子进行路由的任何流(在其消息已由 the Message Logger 原语进行了记录后)。换句话说,将仅在传入消息的名称具有值 IBM 时才访问 StockQuoteService 模块。
    图 3.6.添加了 Message Logger 和 Stop 原语的 StockQuoteMediation 流
    图 3.6.添加了 Message Logger 和 Stop 原语的 StockQuoteMediation 流
  5. 向画布添加一个 XSL Transformation 原语(具有大小两个页的图标)。此原语允许对传入消息的内容进行调整。可以使用它来向传输的股票报价名称追加一个字符串:
    1. 将 Message Filter 的 match1 输出连接到 XSL Transformation 原语的输入。
    2. 将 XSL Transformation 输出端子连接到 Callout 节点的输入。
    3. 右键单击 XSL 原语,选择 Show In Properties,并访问下部视图中的 Details 选项卡。
    4. 将缺省 Root: 设置保持为 body,以将原语限制为仅更改消息正文的内容。
    5. 单击 New,以开始定义映射转换。在 New XSLT Mapping 窗口中,输入和输出消息类型均已预定义,如下面的图 3.7 所示。由于输入和输出端子均已连接,因此该原语知道预期的消息类型和要传出的消息类型。如果需要其他消息类型,请通过直接从现有接口中的 Browse 按钮进行选择来指定。单击 Finish,以接受缺省设置:
      图 3.7.XSLT Mapping 向导
      图 3.7:XSLT Mapping 向导
    6. 现在将打开 XSL Transform Editor,并在其中显示传入和传出消息的正文结构。展开两个消息中的 smo(服务消息对象,Service Message Object——中介流中使用的数据对象类型)元素:
      图 3.8.XSL Transform Editor,输入 (Source) 和输出 (Target) 消息结构均已展开
      图 3.8.XSL Transform Editor,输入 (Source) 和输出 (Target) 消息结构均已展开
    7. 单击两个消息的 smo 根元素,然后右键单击并选择 Match Mapping,该操作会将输入消息的内容复制到输出消息中,已确保两者完全相同。
    8. 右键单击传出 (Target) 消息的 name [0..1] 元素,并选择 Define XSLT Function
    9. 在弹出窗口中选择 String,并单击 Next
    10. 从下拉菜单中选择 concat,单击 Add,并输入字符串 'vetted'(包括单引号)。此新函数现在应出现在中间的表中:
      图 3.9.XLST Functions 向导
      图 3.9.XLST Functions 向导
    11. 退出 XSL Transform Editor,并保存更改。回到 Mediation Flow Editor,应会在 Properties 视图中显示这个新创建的映射文件。所需的最后一个步骤是将此映射文件转换为恰当的 XSL 文件,以使用其进行实际的转换工作。单击 Regenerate XSL 并保存流:
      图 3.10.StockQuoteMediation 流,已实现了 XSL Transformation 原语,并显示 Details
      图 3.10.StockQuoteMediation 流,已实现了 XSL Transformation 原语,并显示 Details

    现在已经配置此中介原语将字符串 vetted 追加到输入股票报价名称值中。

  6. 最后要添加 Fail 原语(红色惊叹号图标——您可能需要单击红色方框来访问)。此原语与 Stop 原语类似,也提供了一种完全挂起流的方法。区别在于对向其传递的异常消息的处理方式不同:Stop 原语会对堆栈上收到的任何异常进行传播,将其发送回中介的调用方,而 Fail 原语将完全不会向外传递。请注意,这可能不是所希望的行为,因为这可能会导致隐藏系统问题。不过,在此例中,我们使用其来处理来自第二个 Message Logger 原语的错误(例如,可能会因为数据库访问问题而引发此类错误)。由于这提供的是不太关键的功能(记录“死锁”流上的消息),因此适合在此处使用 Fail 原语。
  7. 请求流现在已完成,应与以下所示类似:
    图 3.11.完整的 StockQuoteMediation 流
    图 3.11.完整的 StockQuoteMediation 流
  8. 配置中介流的最后一步是连接响应流。采用和前面一样的方式进行此操作(包括一个 Message Logger 原语)。结果应与 StockQuoteService 中介中使用的流相似,如上面的图 2.7 中所示。

现在就完成了新中介模块的相关工作,该模块根据以下输入名称字符串来提供三种不同的中介行为:

name=IBM
消息将传递到 StockQuoteService 模块(之前会向其添加了字符串 vetted,以构成名称值 IBMvetted)。
name=IBMold
会将消息原样传递到 StockQuoteService 模块。
name=anything else
消息将记录到本地 Message Logger 数据库中,流将挂起。

通过分析服务实现 StockQuoteServiceImpl.java 的清单,我们可以对此逻辑加以理解:实际上,Route 1 提供高质量服务,能返回最新的 IBM 股票值。此服务仅限于 StockQuoteMediation 流的用户——因为需要追加 vetted 字符串。Route 2 提供了旧的、略微有些过时的 IBM 股票值。Route 3 将服务限制为仅与 IBM 股票值一起使用。未实现 Web 服务的实时方面,但这样的安排可帮助说明通过使用 WebSphere ESB 和 WebSphere Integration Developer 可以实现哪些目标。

公开 Web 服务

既然已经设置了提供服务的中介模块和提供访问此服务的流逻辑的模块,所需要进行的最后一项创建工作就是创建用于调用完整中介流的机制。在业务环境中,这个最后的阶段似乎有些“画蛇添足”,因为很可能直接通过其发布的接口访问生成的模块。不过,这对于演示完整流调用仍然很有用——您将需要在测试期间调用完整的流。

可以采用多种方式调用我们已实现的 StockQuoteService Web 服务。我们将尝试其中的两种方法:WebSphere Integration Developer Universal Test Environment (UTE) 和运行 JSP 的网页。

设置测试环境

在测试此处开发的任何模块之前,您需要在 WebSphere ESB 服务器(WebSphere Process Server) 实例上对其进行部署并启动。以下步骤假定已经安装了服务器:

  1. 在下方的 WebSphere Integration Developer 视图中(进入了 Business Integration 透视图),单击 Servers 选项卡。
  2. 在此新窗口中右键单击并选择 New => Server
  3. 在 New Server 弹出窗口中,选择 IBM => WebSphere ESB Server V6,然后单击 Next
  4. 单击 Browse 并定位安装在您系统上的 ESB——在 Windows 上,缺省位置为 C:\\Program Files\\IBM\\WebSphere\\ESB:
    图 4.1.New server 向导
    图 4.1.New server 向导
  5. 单击两次 Next,接受所有缺省设置。
  6. 在下一个面板中单击 Add All,以将此处开发的两个项目均添加到服务器,然后单击 Finish。服务器将随即启动,而这些项目将自动发布到其上并自动启动。
  7. 单击下部面板中的 Console 选项卡,以检查在服务器的输出日志上列出的服务器启动期间的错误,此日志在缺省情况下位于 <ESB-install-directory>\profilesESB01\logs\server1\SystemOut.log。如果在此过程中引发了任何异常,请在 Servers 面板中单击服务器并选择 Restart the server 图标(两个相对的箭头),从而重新启动该服务器。启动服务器并部署项目可能需要数分钟时间,因此请耐心等待。

现在服务应该已处于运行状态(由 Servers 视图中的 started 状态指示)且项目已经部署,可以进行测试了。调用中介前的最后一件事——在服务器中打开额外的日志详细信息,以生成详细报告来了解在调用期间发生的事务:

  1. 将 Web 浏览器指向 http://localhost:9060/ibm/console/ ,以进入 WebSphere ESB 管理控制台的登录页,此管理控制台是基于 Web 的 GUI 界面,用于配置正在运行的 WebSphere ESB 服务器实例:
    图 4.2.WebSphere ESB 管理控制台登录面板
    图 4.2.WebSphere ESB 管理控制台登录面板
  2. 单击 Log in 并从 Task filtering selector 列表中选择 Server and Bus,然后单击 Apply
    图 4.3.在管理控制台中选择任务筛选器
    图 4.3.在管理控制台中选择任务筛选器
  3. 展开左侧的 Troubleshooting 菜单,并选择 Logs and Trace
  4. 在新面板中选择 server1
  5. 可以从此处调整历史副本的大小和数量,以用于保存产生的各种服务器日志文件。我们暂时仅对调整跟踪文件的记录详细程度感兴趣,因此请单击 Change Log Detail Level
  6. 在此新页面中的文本框中输入 *=info:com.ibm.ws.sibx.*=fine 并单击 OK,然后保存更改。
  7. 要使这些更改生效,请重新启动服务器:返回 WebSphere Integration Developer,进入 Servers 视图,然后单击 Restart the server 图标。

现在已经配置服务器使用非常详细的日志形式,以打印出在中介流中每个组件的入口点和出口点通过中介模块传递的消息的全部内容(我们将在下一部分讨论具体的结果)。虽然这是个很优秀的初级调试工具,但由于其相关的性能开销以及详细的日志文件,通常并不会将其用于商用部署的应用程序。

通过 Universal Test Environment (UTE) 进行调用

UTE 提供了一个接口,可用于在中介模块中特定组件处使用特定操作直接调用流:

  1. 在左侧的 Business Integration Navigator 中右键单击 StockQuoteMediation 项目,并选择 Test => Test Module
  2. 将随即打开一个新编辑器,并在其中显示与所选中介模块关联的接口所提供的各种调用选项。接受缺省值,并输入 IBM 作为 name 值,如下面的图 4.4 所示。单击 Continue,以启动测试客户端。
    图 4.4.初始 UTE 面板,已输入了 IBM 输入值
    图 4.4.初始 UTE 面板,已输入了 IBM 输入值
  3. 在 Deployment Location 弹出窗口中展开 WebSphere ESB Server V6 位置,并选择下面的 localhost 服务器,然后单击 Finish
  4. 客户端现在将开始运行——首先启动服务器,然后发布测试客户端,并利用指定的输入参数 IBM 使用其访问 StockQuoteMediation 模块。如下面的图 4.5 中所示,UTE 将显示消息在中介模块之间的路由,并显示最终的结果——在此例中为预期的价格 100.0:
    图 4.5.使用输入 IBM 调用 getQuote 操作后的 UTE 面板
    图 4.5.使用输入 IBM 调用 getQuote 操作后的 UTE 面板
  5. 使用 Invoke 图标(编辑器右上角的选择面板中的第一个图标)重复访问调用。输入诸如 IBMoldxxx 一类的值来验证预期结果——分别为 80.0null

对输出日志记录进行进一步检查

前面一部分验证了流按照预期的工作,但仅使用 UTE 仅能提供很少的流调用期间消息所实际经历的情况细节。有两种方法用于获取此类信息:检查 SystemOut 日志文件,和检查 Message Logger 缺省数据库。

检查 SystemOut 日志文件

如前面所提到的,WebSphere ESB 在缺省情况下将其系统日志记录信息输出到 <ESB-install-directory>\profilesESB01\logs\server1\SystemOut.log。打开此文件并检查其内容,请将重点放在文件末尾,UTE 测试的输出就存储在此处。由于在前一部分指定了详细日志记录选项“Setting up the test environment”,因此将打印每个中介原语的入口点和出口点处的完整消息。例如,下面的清单 2 显示了记录的 XSL Transformation 原语(使用输入名称值 IBM)的出口点处的信息:

清单 2. WebSphere ESB SystemOut.log 文件的示例内容,演示了典型的消息内容,其中突出显示了各个重要特性
[26/01/06 11:46:34:430 GMT] 00000058 SystemOut     O 
++++++++++++++++++++++++++++++++++++++++
ProcessMessage
Flow metadata   :
    Port type   : {http://StockQuoteLibrary/StockQuoteService}StockQuoteService
    Operation   : getQuote	--> invoked operation
    Interaction : Request	--> direction of mediation flow
    Component   : com.ibm.ws.sca.internal.scdl.impl.ManagedComponentImpl@2db851d4 (description: null) 
    		(displayName: StockQuoteMediationMediation) (name: StockQuoteMediationMediation)
Node name        : XSLTransformation1	--> current mediation primitive
Node name        : XSLTransformation1
Node display name: XSLTransformation1
Node type (class): com.ibm.ws.sibx.mediation.primitives.xslt.XSLTMediation
Node properties  : {XSLTransform=xslt/XSLTransformation1_req_1.xsl, root=/body, 
		associatedXSL=xslt/XSLTransformation1_req_1.xsl, sibxMayChangeMessage=true, 
		XMXMap=xslt/XSLTransformation1_req_1.xmx, validateInput=false}
Terminal name    : out
Terminal type    : Output	--> current mediation terminal
Message          : com.ibm.ws.sibx.smobo.impl.ServiceMessageObjectImpl@9511ec 
		{ <?xml version="1.0" encoding="UTF-8"?>
<smo:smo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:service="http://StockQuoteLibrary/StockQuoteService" 
		xmlns:smo="http://www.ibm.com/websphere/sibx/smo/v6.0.1">
  <context/>
  <headers>
    <SMOHeader>	--> message header information
      <MessageUUID>fe498906-0901-0000-0080-91d5c1b505a5</MessageUUID>
      <Version>
        <Version>6</Version>
        <Release>0</Release>
        <Modification>1</Modification>
      </Version>
      <MessageType>Request</MessageType>
    </SMOHeader>
  </headers>
  <body xsi:type="service:getQuoteRequestMsg">
    <getQuote>
      <inputGetQuote>
        <name>IBMvetted</name>	
        		--> actual message body content -- with 'vetted' appended as expected
      </inputGetQuote>
    </getQuote>
  </body>
</smo:smo> }

如前面所提到的,可从 WebSphere Integration Developer Console 获得相同的信息,但其缓冲区的更小(可以在 Preferences 设置中进行调整),因此 SystemOut.log 文件通常在问题诊断中使用。另外,处理记录输出消息的内容外,日志文件中包含来自运行于服务器上的 Java 代码且写入到 System.out 的输出消息的内容。检查服务实现 StockQuoteServiceImpl.java 生成的输出。

检查 Message Logger 缺省数据库

此处定义的中介流使用了多个 Message Logger 原语,其功能是用于将通过其中的消息内容写入指定的数据库。在部署这些原语时,我们使用了缺省的 Cloudscape 数据库。要访问此数据库,请执行以下操作:

  1. 访问 Servers 视图,并停止服务器,因为服务器运行时会在 Cloudscape 数据库上保持一个锁定。
  2. 运行 <ESB install directory>\cloudscape\bin\embedded\cview.bat 来访问数据库的 GUI 界面。
  3. 在浏览器中选择 File => Open 并选择 <ESB install directory>\profiles\ESB01\databases\EsbLogMedDB
  4. 在侧菜单中展开 Tables,并单击 MSGLOG,此表是用于存储消息内容的缺省表。
  5. 在右侧面板中单击 Data。它提供了对记录的所有信息的访问权限,包括记录消息的时间和位置(原语和模块名称)以及消息内容本身。由于这个表相当小,请使用 Text Editor 图标来在另一个编辑器中显示完整的信息,如下面的图 4.6 中所示。由于我们选择了缺省 Message Logger 设置,因此将仅在此数据库表中记录消息正文。将其与 SystemOut.log 的内容进行比较,以了解两者之间的不同之处:
    图 4.6.Message Logger DB 表的内容,显示了记录的典型消息内容
    图 4.6.Message Logger DB 表的内容,显示了记录的典型消息内容

创建并通过 JSP 运行

现在我们已经演示了中介模块按照预期工作,我们可以组建一个使用 JSP 的基于 Web 的服务前端。(如果需要有关 JSP 技术的更多信息,请参阅下面的参考资料。)

首先,我们需要创建对中介模块的引用,以充当 JSP 的输入点:

  1. 打开 Assembly Diagram Editor(StockQuoteMediation 模块)。
  2. 从编辑器的左侧的图标选择面板中,展开绿色箭头图标并选择蓝色箭头图标 (Stand-alone References)。
  3. 将此组件添加到编辑器画布,并将其连接到 StockQuoteMediationMediation 组件,并在 Add Wire 窗口中选择 No。编辑器应该与以下所示类似:
    图 4.7.StockQuoteMediation 模块的组装关系图,添加了独立引用
    图 4.7.StockQuoteMediation 模块的组装关系图,添加了独立引用
  4. 保存更改,并将鼠标悬停在新引用名称上(1..1 图标)来显示其名称。名称 (StockQuoteServicePartner) 充当流的入口点,将由下面的 JSP 使用。

现在已经设置了一个有效的引用,以用作流的入口点,接下来我们将定义一个相应 JSP:

  1. 在 Business Integration Navigator 中右键单击 StockQuoteMediation,并选择 New => Other
  2. 在新窗口中展开 Web(如果此选项最初不可用,请选中 Show All Wizards 复选框),单击 JSP File,然后单击 Next
  3. 单击 Browse 并在新窗口中展开 StockQuoteMediationWeb。选择下面的 WebContent 文件夹,JSP 文件将存储于此,从而使其对 Web 浏览器可用。
  4. 回到 New JSP File 弹出窗口输入 invokeStockQuoteService 作为 JSP 名称:
    图 4.8. 已完成的 New JSP File 向导
    图 4.8.已完成的 New JSP File 向导
  5. 单击 Finish。WebSphere Integration Developer 将生成此文件的基本框架,并将其在 JSP 编辑器中打开它,主窗格中将显示三个选项卡:Design、Source 和 Preview:
    图 4.9.JSP Editor(显示了基本代码框架)
    图 4.9.JSP Editor(显示了基本代码框架)
  6. 选择 Source 选项卡,并使用以下代码替换现有模板:
    清单 3. invokeStockQuoteService JSP 的代码
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <HTML>
    <HEAD>
    <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
        pageEncoding="ISO-8859-1"%>
        <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <META name="GENERATOR" content="IBM Software Development Platform">
        <META http-equiv="Content-Style-Type" content="text/css">
        <LINK href="theme/Master.css" rel="stylesheet"
        type="text/css">
        <TITLE>invokeStockQuoteService.jsp</TITLE>
    </HEAD>
    <BODY>
    <%@ page import="com.ibm.websphere.sca.ServiceManager" %>
    <%@ page import="com.ibm.websphere.sca.Service" %>
    <%@ page import="commonj.sdo.DataObject" %>
    <%@ page import="com.ibm.websphere.bo.BOFactory" %>
    <%@ page import="com.ibm.websphere.sca.ServiceBusinessException;" %>
    <H1 align="center">StockQuote Application</H1>
    <form action="invokeStockQuoteService.jsp" method="get">
            
    <TABLE border="0" cellpadding="5" cellspacing="0">
       <TBODY>
          <TR>
             <TD>Enter a StockQuote name (e.g. IBM): </TD>
             <TD><INPUT type="text" name="name" size="30" maxlength="30"></TD>
          </TR>
       </TBODY>
    </TABLE>
    <P><INPUT type="submit" name="Submit" value="Submit"></P>
    </form>
    <%
    System.out.println("Client accessed");
    System.out.println("invokeStockQuoteService.jsp : Check for name");
    // retrieve name value input in HTML text box
    String name = request.getParameter("name");	
    String ref = "StockQuoteServicePartner";	
    if (name != null) {
       System.out.println("invokeStockQuoteService.jsp : 
             Retrieved stockquote name: " + name + " from browser");
       // now attempt to invoke the StockQuote mediation flow
       try {
          // First retrieve an instance of the service to invoke
          ServiceManager serviceManager = new ServiceManager();
          Service service = (Service) serviceManager.locateService(ref);
    		
          // Locate the BOFactory via its 'well known' location name
          // com/ibm/websphere/bo/BOFactor
          // this is used to generate a Business Object -- the data structure used by
          // the message passed to the mediation flow 
          System.out.println("invokeStockQuoteService.jsp : Locating BOFactory");		
          BOFactory bofactory = 
                (BOFactory) serviceManager.locateService("com/ibm/websphere/bo/BOFactory");
    		
          // Use BOFactory with  service interface to create a correctly formatted input message
          System.out.println("invokeStockQuoteService.jsp : Get message getQuote");
          DataObject getQuote = 
                bofactory.createByElement("http://StockQuoteLibrary/StockQuoteService", "getQuote");
    		
          // Now get hold of necessary part of this input message and add the value input at browser
          System.out.println("invokeStockQuoteService.jsp : Get input parameter inputGetQuote");
          DataObject inputGetQuote = getQuote.createDataObject("inputGetQuote");
    		
          System.out.println("invokeStockQuoteService.jsp : Set inputGetQuote::name = " + name);
          inputGetQuote.setString("name", name);
          DataObject getQuoteResponse = null;
    		
          try {
      
             // Now invoke the operation 'getQuote' operation - note, the 'getQuoteResponse'
             // object represents the returned message
             System.out.println("invokeStockQuoteService.jsp : Invoke getQuote with " + name);
             getQuoteResponse = (DataObject)service.invoke("getQuote", inputGetQuote);
             // Retrieve the output, using the format specified in the interface
             System.out.println("invokeStockQuoteService.jsp : Retrieving the outputGetQuote");
             DataObject outputGetQuote = getQuoteResponse.getDataObject("outputGetQuote");
    			
             if (outputGetQuote == null) {
                out.println("No message returned - this may be due to the " +
                   "flow encountering a Stop or Fail mediation primitive.");
             } else {
                System.out.println("invokeStockQuoteService.jsp : Retrieving the price");
                float result = outputGetQuote.getFloat("price");
                System.out.println("invokeStockQuoteService.jsp : 
                      outputGetQuote::price = " + result);				
                // Finally print the return value to the browser page
                out.println("<p>" + name + " stock price: " + result + "</p>");
             }
          } catch (ServiceBusinessException sbe) {
    		
             out.println("invokeStockQuoteService.jsp : 
                   ServiceBusinessException caught - content as follows:</br>");
             out.println("invokeStockQuoteService.jsp : " + sbe.getMessage() + "</br>");
          }
       } catch (Exception e) {
          System.out.println(e);
       }
    }
    %>    
    </BODY>
    </HTML>

    代码中的 ref 变量用于查找要调用的访问,该变量已设置为在 StockQuoteMediation module 组装关系图中显示的引用值,如图 4.7 中所示。日志 out.println 将被定向到 Web 浏览器(在其中显示 JSP 所生成的页面),而 System.out.println 的日志被定向 WebSphere ESB SystemOut 日志。

  7. 保存更改并关闭 JSP 编辑器。

JSP 存储在 StockQuoteMediation 模块中,因此需要将其重新部署到服务器,以使更改生效:访问 Servers 视图,右键单击 localhost 服务器实例,并选择 Restart Project => StockQuoteMediation

一旦项目重启后,请检查控制台输出中的错误,打开 Web 浏览器并输入 URL:

http://localhost:9080/StockQuoteMediationWeb/invokeStockQuoteService.jsp

将加载与此类似的网页:

图 4.10.StockQuoteService JSP 网页(含有 IBM StockQuote 输入的结果)
图 4.10.StockQuoteService JSP 网页(含有 IBM StockQuote 输入的结果)

和 UTE 部分中一样,使用不同的 StockQuote 名称输入值进行试验,以验证返回了预期的响应。要特别输入一个预期值 IBM 和 IBMold 之外的值,并检查 SystemOut 日志,以验证使用了另一个中介路由。

结束语

在本文中,我们使用 WebSphere Enterprise Service Bus 和 WebSphere Integration Developer 开发并部署了一个基于 Web 的服务。具体说来,我们进行了以下工作:

  1. 开发一个简单的基于 Java 的 Web 访问,用于提供基本的 StockQuote 服务。
  2. 开发了连接到此服务的中介流,其逻辑会根据消息有效负载将请求路由到不同的目的地。
  3. 将这些项目部署到正在运行的 WebSphere ESB 服务实例,并使用提供的测试环境和独立 JSP 前端对其进行调用。
  4. 讨论了可用的输出日志工具。

我希望这个相当简单的示例能对 WebSphere Enterprise Service Bus 和 WebSphere Integration Developer 的各种功能进行有用的说明。

致谢

作者感谢 IBM 的 Chris Markes 为撰写本文所提供的帮助。


下载

描述名字大小
Code samples in zip formatdWProjectInterchangeFile.zip  ( HTTP | FTP )88 KB

参考资料

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


这是您第一次登陆到 developerWorks,已经自动为您创建了您的概要文件。 选择您概要文件中可以公开的信息的信息(如姓名、国家/地区,以及公司),这些信息同时也会与您所发布的内容相关联。 您可以随时更新您的 IBM 账号。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=109200
ArticleTitle=WebSphere Enterprise Service Bus 与 WebSphere Integration Developer 入门
publish-date=04202006