|
IBM WebSphere Message Broker 作为主流的 ESB 产品,对 Web Services 有良好的支持,在 WebSphere Message Broker 6.0 版本中,我们可以通过 HTTP 传输节点进行对 Web Services 的支持。然而随着 WebSphere Message Broker 6.1 于 2007 年 12 月发布,我们可以看到 Message Broker 6.1 对 Web Services 的支持有了比较大的增强。对基于 SOAP 的 Web Services 的开发,我们现在可以方便地导入 WSDL 接口文件,利用新的 SOAP 节点迅速地构造 SOAP 服务,而不需要以前那样需要通过 HTTP 节点,再对 SOAP 消息进行解析。基于 Message Broker 6.1 这种新特性对 Web Services 的强大支持,使得开发人员加快了工作效率,而且开发起来更为直观;另外 Message Broker 6.1 对异步的 Web Services 的开发也进行了支持,现在开发人员可以直接在 Message Broker 6.1 里面用 SOAPAsyncRequest、SOAPAsyncResponse 两个异步节点进行异步 Web Services 服务调用的开发。
本文将对 Message Broker 6.1 的 Web Services 新节点进行介绍,然后通过构建两个 Web Services 范例,从同步和异步这两种不同方式描述如何在 Message Broker 6.1 上构建基于 SOAP 的消息流的开发。
WebSphere Message Broker 6.1 新增的 Web Services 节点的介绍
Message Broker 6.1 新增的 Web Services 节点包括:
-
SOAPInput node
-
SOAPReply node
-
SOAPRequest node
-
SOAPEnvelope node
-
SOAPExtract node
-
SOAPAsyncRequest node
-
SOAPAsyncResponse node
-
Register Lookup node
-
Endpoint Lookup node
SOAPInput node
对应于 Message Broker6.0 的 HTTP Input 节点,使用 SOAPInput 节点可以用来处理客户端的 SOAP 请求,使得 Message Broker 方便地成为 SOAP Web Servcies 的 Provider。
SOAP Input 节点需要有 SOAP Reply 节点在同一消息流中与之相对应,或者必须把消息传递给包含 SOAP Reply 节点的另一消息流。SOAP Input 节点同时支持 HTTP 和 HTTPS 两种请求通讯方式。SOAP Input 节点在消息流画板的 Web Services 标签下,拉到消息流编辑器则如下图所示:
必须指定 SOAP Input 节点的 URL selector 属性和 WSDL 属性。URL selector 指定该 SOAP 消息流被访问的 URL;而在 Basic 下的 WSDL properties 则指定该 SOAP 消息流对应的 WSDL 文件,指定的 WSDL 文件必须是被 import 到某一消息集项目中的文件,而不能是原始的 WSDL 文件;指定好 WSDL 文件后,则可以继续选择 Port type、Imported binding、Service port 等属性,这些属性和标准的 WSDL 属性存在相对应的关系;
SOAPReply node
对应于 Message Broker6.0 的 HTTP Reply 节点,使用 SOAP Reply 节点与 SOAP Input 相结合可以用来处理客户端的 SOAP 请求,它把响应消息回送到调用消息流的客户端,SOAP Reply 节点必须和 SOAP Input 节点在同一消息流中,或者它的消息是从某一个 SOAP Input 节点的消息流接收的。可以在 SOAP Reply 的 Validation 下的 Validate 设置它的校验规则,默认是 Inherit。
SOAPRequest node
对应于 Message Broker6.0 的 HTTP Request 节点,使用 SOAP Request 节点方便发送 SOAP 请求调用 Web Services,比如部署在 WebSphere Process Server 或 WebSphere Application Server 上的 Web Services;SOAP Request 发出的请求可选择由消息树中的部分或者全部组成。开发中如有用到 SOAP Request 节点则需要指定它 HTTP Transport 下的 web Service URL 属性,该属性为 SOAP 请求的 Web Service 的 URL,另外还需指定 Basic 下的 WSDL properties,这些 WSDL properties 和 SOAP Input 节点的 WSDL properties 对应一致。
SOAPExtract node
使用 SOAPExtract 节点可以把接收到的 SOAP 消息的 Envelope 移除,另外它可以根据 SOAP 消息的 operation 名把 SOAP 消息 route 到对应的 Label node。去除掉 envelope 的 Message 在消息树里面更为方便使用。
SOAPEnvelope node
使用 SOAPEnvelope 可以对已在消息流中的消息加封装 SOAP envelope,一般来讲,该节点可以和 SOAPExtract 结合起来一起使用,由于 SOAPRequest 和 SOAPReply 节点等可以自动构建 SOAP Envelope,所以是否需要使用 SOAPEnvelope 节点可根据实际应用情况考虑。
SOAPAsyncRequest node
SOAPAsyncRequest node 可以联合 SOAPAsyncResponse node 构造异步的 Web Service 调用消息流。SOAPAsyncRequest node 发送 Web Service 请求,但是并不需要等待请求的回复,就可以继续进行接下来的动作;Web Service 请求的回复由 SOAPAsyncResponse node 接收,而该节点可以在另外的消息流上,SOAPAsyncRequest 和 SOAPAsyncResponse node 是成对使用的。
SOAPAsyncResponse node
SOAPAsyncResponse 节点用来接收由 SOAPAsyncRequest 节点发出的 Web Service 请求的回复信息。一般而言,SOAPAsyncResponse 节点不和 SOAPAsyncRequest 节点放在同一条消息流上,且是在其他消息流的开始节点位置。
Registry Lookup node
使用 Registry Lookup node 来访问存在服务注册库 WebSphere Service Registry and Repository (WSRR) 上的服务元数据;一般来讲它和 EndPoint Lookup 节点一起结合使用。
Endpoint Lookup node
使用 Endpoint Lookup node 来访问存在服务注册库 WebSphere Service Registry and Repository (WSRR) 上的服务元数据,比如 WSDL 文件。
在本文中我们不涉及使用 WSRR 服务注册库,读者如有兴趣,可以访问参考资源里 WSRR 的相关信息站点以获取更多的信息。
此外,详细的节点属性配置及其含义,在参考资源里的 Message Broker 6.1 的 InfoCenter 网站,或者 Message Broker 6.1 Toolkit 自带的 InfoCenter 均可查阅。
在了解了各 SOAP 节点基本功能后,接下来,我们将分别介绍如何在 Message Broker 里构造同步 Web Service 和异步 Web Service,通过这两个范例来领略 Message Broker 6.1 给我们带来的好处。
同步 Web Service
第一步:根据范例业务场景准备 WSDL 文件
在本例中,我们模拟一测试场景 , 建立一个简单的 Web Service,Web Service 客户端发送客户订单到服务端 , 客户定单包含的内容有客户的定单号、客户基本信息、定货数量等,服务端接受客户请求,根据定单的详细信息,构造完整的送货单返回给客户端。如下所示,客户方发送的客户定单对应的 soap 消息为:
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<NS1:helloInvokeRequest xmlns:NS1="http://localhost/service/synchronization">
<NS1:orderID>A38C884</NS1:orderID>
<NS1:orderQuantity>100</NS1:orderQuantity>
<NS1:personName>
<NS1:firstName>jerry</NS1:firstName>
<NS1:lastName>lv</NS1:lastName>
</NS1:personName>
<NS1:address>
<NS1:street>linheXi center plaza 40F</NS1:street>
<NS1:city>guangzhou</NS1:city>
<NS1:zipCode>351003</NS1:zipCode>
</NS1:address>
</NS1:helloInvokeRequest>
</soapenv:Body></soapenv:Envelope>
|
服务端返回的送货单对应的 soap 消息为:
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<NS1:helloInvokeResponse xmlns:NS1="http://localhost/service/synchronization">
<NS1:orderStatus>COMPLETE</NS1:orderStatus>
<NS1:orderPrice>50</NS1:orderPrice>
<NS1:deliverPosition>jerrylv,your deliverPosition is:linheXi center plaza 40F
guangzhou 351003</NS1:deliverPosition>
</NS1:helloInvokeResponse>
</soapenv:Body>
</soapenv:Envelope>
|
在 Message Broker 6.1 的 SOAP 开发中,SOAP 节点对基于 WSDL 的 Web Services 已经有良好支持,所以开发第一步是根据上述的业务场景准备服务端和客户端之间的 WSDL 接口文件,在 WSDL 中定义好对应的 operation、portype、type 等。在同步 Web Service 中,我们建立的 WSDL 文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://localhost/service/synchronization"
targetNamespace="http://localhost/service/synchronization">
<wsdl:types>
<xsd:schema targetNamespace="http://localhost/service/synchronization"
elementFormDefault="qualified">
<xsd:element name="helloInvokeResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="orderStatus"
type="xsd:string"/>
<xsd:element name="orderPrice"
type="xsd:int"/>
<xsd:element name="deliverPosition"
type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="helloInvokeRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="orderID"
type="xsd:string"/>
<xsd:element name="orderQuantity"
type="xsd:int"/>
<xsd:element name="personName">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="firstName"
type="xsd:string"/>
<xsd:element name="lastName"
type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="street"
type="xsd:string"/>
<xsd:element name="city"
type="xsd:string"/>
<xsd:element name="zipCode"
type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="helloInvokeRequest">
<wsdl:part name="helloInvokeRequest"
element="tns:helloInvokeRequest"/>
</wsdl:message>
<wsdl:message name="helloInvokeResponse">
<wsdl:part name="helloInvokeResponse"
element="tns:helloInvokeResponse"/>
</wsdl:message>
<wsdl:portType name="synchronizationType">
<wsdl:operation name="helloInvoke">
<wsdl:input message="tns:helloInvokeRequest"/>
<wsdl:output message="tns:helloInvokeResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="synchronizationBinding" type="tns:synchronizationType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="helloInvoke">
<soap:operation
soapAction="http://localhost/service/synchronization"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="synchronizationService">
<wsdl:port name="synchronizationPort"
binding="tns:synchronizationBinding">
<soap:address
location="http://localhost/service/synchronization"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
结合上述的 SOAP 的请求发送和返回消息范例,我们可看到,WSDL 文件中 <wsdl:operation> 定义 Web Service 执行的操作,对应于 soap 消息的 NS1:helloInvokeRequest/ NS1:helloInvokeResponse;<wsdl:types> 定义 Web Service 使用的消息类型;< wsdl:binding> 定义消息使用的通讯协议;<wsdl:message> 定义 Web Service 调用的输入输出消息组成。
第二步:创建 Message Set Project,导入 WSDL 文件
在这一步,我们在创建 Message Flow Project 之前先创建 Message Set Project,并且把 Message Flow Project 需要的 WSDL 文件导入到 Message Set Project 里。
根据 Message Set 创建向导创建 Message Set Project 名为 synchronizationMSP, 如下图所示:
接下来再根据新建”message definition file from WSDL File”向导导入上文所述的 WSDL 文件。
在导入的过程,选上”copy soure file into the ‘importFiles’ directory of message set project”选项,会把源 WSDL 文件导入保留在 project 的 importfile 里。
最终的 Message Set 项目结果如下图所示:
第三步:创建 Messsage Flow Project,并在其中建立 Message Flow
本步骤,我们将建立消息流项目 synchronizationMFP,并在其上创建两条 Message Flow,一条为根据第二步导入到 Message Set Project 的 WSDL 文件创建 Web Service,对接收到的 SOAP 消息进行处理;另一条 Message Flow 则作为 SOAP 请求的客户端发送 SOAP 请求到 Web Service。通过这两条消息流的构建,我们可以掌握 SOAP Input 节点、SOAP Reply 节点、SOAP Extract 节点、SOAP Envelope 节点、SOAP Envelope 节点等节点的基本使用方法。
下面使用的 WebSphere Message Broker V6.0.2 的功能你可以从下面的文章中了解具体的功能,在这里不过多叙述: 有关 WebSphere Message Broker V6.0.2 工具包的十二项重要内容:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/0702_dunn/0702_dunn.html
下图为 SOAP 服务的服务端消息流,请求消息先经过 SOAP Input 节点处理,再由 SOAPExtract 移除 SOAP 消息的 Envelope,方便后续流程的处理,在 Compute 节点构造 SOAP reply 消息,再由 SOAPEnvelope 加上 Soap 的 Envelope,最后由 SOAP Reply 节点把 SOAP 消息回送到请求端。
在 SOAP Input 节点,我们要选择 WSDL file name,此 WSDL file name 对应于消息流项目依赖的消息集项目导入的 WSDL 文件,我们在本例中选择 synchronization.wsdl。
在本节点还需要设置 Http Transport 下的各属性,其中的 URL selector 属性我们设置为 /service/synchronization,这样 SOAP 客户端调用该 SOAP 消息流的 URL 类似于 http://localhost:7800/service/synchronization。
如在 SOAPExtract 节点选上 Remove envelope 意味着 SOAPExtract 节点入口的 SOAP 消息会被移除它的 soap envelope,并且把 soap envelope 放在 Envelope Destination 属性指定的位置。
而在 Compute 节点则根据输入的 SOAP 请求消息,构造它的回复消息,Compute 里的代码如下图所示:
declare m NAMESPACE 'http://localhost/service/synchronization';
CREATE COMPUTE MODULE synchronizationServer_Compute
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot.XMLNSC.m:helloInvokeResponse.m:orderStatus = 'COMPLETE';
SET OutputRoot.XMLNSC.m:helloInvokeResponse.m:orderPrice = 50;
SET OutputRoot.XMLNSC.m:helloInvokeResponse.m:deliverPosition =
InputRoot.XMLNSC.m:helloInvokeRequest.m:personName.m:firstName
||InputRoot.XMLNSC.m:helloInvokeRequest.m:personName.m:lastName
||',your deliverPosition is:'
||InputRoot.XMLNSC.m:helloInvokeRequest.m:address.m:street
||' '||InputRoot.XMLNSC.m:helloInvokeRequest.m:address.m:city
||' '||InputRoot.XMLNSC.m:helloInvokeRequest.m:address.m:zipCode;
END;
|
要注意如果消息中的标签有命名空间,则需要加上它的命名空间,如 OutputRoot.XMLNSC.m:helloInvokeResponse.m:orderStatus = 'COMPLETE'。此计算节点里的 ESQL 根据实际的 SOAP 消息进行解析、再构造出口消息。
最后构建好回复消息 body 后,再加上 SoapEnvelope 节点,把 Soap Envelope 加到回复消息上,构建完整的 soap 回复消息,最后再接上 Soap Reply 节点,整个 SOAP 服务就构建完毕。
第四步:建立 client 端;
在第三步的建好 SOAP 服务端后,接下来我们尝试构建 SOAP 请求 Client 端,首先先建立名为 synchronizationClient 的 message flow,然后再添加配置好整个消息流所需要的节点,如下图所示:
MQInput 节点接收 XML 输入消息后,把 XML 消息传给 Compute Send 计算节点,该节点根据输入的消息重新构建消息树,以符合 SOAP 服务请求的要求; SOAP Request 节点则把 SOAP 消息发送给第三步配好的 Web Service,取得回复 SOAP 消息后,SOAPExtract 去除接收到的 SOAP 消息的 envelope,Compute Reply 再对消息进行处理,最后输出到 MQOutput 指定的 Queue 里。
SOAP Client 端 SOAP Request 节点,本例中的 WSDL Properties 配置和 SOAP 服务端的配置相一致,而相关的参数含义也与服务端的 SOAP Input 的参数含义一致;
而在 SOAP Request 的 Http Transport 中,Web Service URL 参数对应服务端 SOAP Input 配置的 URL Selector 参数,如本例访问本机的 SOAP 服务,则配置为 http://localhost:7800/services/synchronization。
第五步:使用 nettools 进行服务端测试 , 或者发送 message 到 MQInput 中
在本步骤,我们进行两个测试,首先单独对 Web Service 服务端进行测试,根据第一步已有的 WSDL 文件,我们可以使用例如 XMLSPY 等工具生成 SOAP 请求消息,然后再用 nettool 发送请求到服务端,如下所示:
SOAP 请求和回复详细内容查看附件。
如果需要对 SOAP client 的消息流 synchronizationClient 进行测试,则可把如下 xml 消息发送到 synchronizationClient 的 MQInput 节点对应的 Queue SOAP_SYNC_IN 里:
<?xml version="1.0" encoding="UTF-8"?>
<helloInvoke>
<orderID>A38C884</orderID>
<orderQuantity>100</orderQuantity>
<firstName>jerry</firstName>
<lastName>lv</lastName>
<street>linheXi center plaza 40F</street>
<city>guangzhou</city>
<zipCode>351003</zipCode>
</helloInvoke>
|
注:发送 xml 消息到 queue 可使用 rfhutil,rfhutil 的使用可在本文的参考资源中的连接获取 ;
以上消息经过 compute 节点构造成 SOAP 消息发送到 SOAP 服务端,取得 SOAP 返回消息后,把 SOAP 回复消息放入 synchronizationClient MQOutPut 对应 Queue:SOAP_SYNC_OUT 中,查看该 Queue:SOAP_SYNC_OUT,如果有返回消息,则测试成功。
异步 Web Service
Message Broker 6.1 中的 Web Services 异步请求原理
Message Broker 6.1 通过 SOAPAsyncResponse node 和 SOAPAsyncRequest node 两个节点来支持异步的 Web Services 请求,如下图所示,SOAPAsyncResponse node 和
SOAPAsyncRequest node 分别处于不同的消息流,当有消息请求发送到 SOAPAsyncRequest node 的消息流时,SOAPAsyncRequest node 根据配置的 wsdl 发送消息到对应的 web services,而在发送后,此消息流可以继续往下执行,不需要等待 web services 请求的回复。
而当 web services 执行完业务后返回到消息流时,此时是对应的 SOAPAsyncRequest node 接收消息,再对消息进行处理,最后再返回对应的消息。
第一步:根据业务场景准备 WSDL 文件
异步 Web Service 的测试业务场景采用和同步 Web Service 类似场景,客户端发送 SOAP 请求到服务端,在服务端接收处理请求同时,客户端可继续往下同步执行相关的逻辑,因此,我们在异步 Web Service 服务范例的构建上,直接利用同步 Web Service 所生成的 WSDL 文件。
第二步:构建 Web Service 异步服务消息流
在此步骤,我们构建简单的 SOAP 服务消息流 asynchronismServer,如下图所示:
应该注意的是,在异步 Web Service 范例中,我们需要选上 SOAP Input 的 Use Ws-Address 属性,这样 SOAP 消息里的 WS-Addressing headers 就能被 Web Service 服务所识别。
第三步:构建 Web Service 异步客户端消息流
异步消息客户端需要使用 SOAPAsyncRequest 和 SOAPAsyncResponse 这两个节点,构造后的消息客户端流 asynchronismClient 如下图所示:
MQInput 对应的 queue 接收 XML 消息,Compute Send 根据该 xml 消息构造 SOAP 请求,SOAP Asychronous Request 发送异步消息请求,同时流程继续往下执行把输出消息送到 MQ Send Output 节点;当 SOAP 回复消息到达时,SOAP Asynchronous Response 接收该消息,继续往下执行到 Compute Receive 节点,构造输出消息把输出消息输出到 MQ Receive Output node 对应的 queue 里。
应该注意的是,在异步节点 SOAPAsyncRequest 发出请求后,不管 SOAP Asynchronous Response 有无接收到消息,SOAPAsyncRequest 的 Out 输出端口接下来的消息流均可以继续往下执行,Out 端口后续的消息流和 SOAP Asynchronous Response 之间是可并行的关系。
在 SOAPAsyncRequest 节点,我们需要设置 SOAP 请求的 WSDL 属性,HTTP Transport 里的 Web Service URL,以及 Unique identifie 属性,在这里需要注意的是,Unique identifie 是成对使用的,SOAP Asynchronous Response 里的 Unique identifie 需要设置得和 SOAPAsyncRequest 一致。
第四步:测试异步消息流
测试消息流请求异步我们可以利用 Message Broker 6.1 的 Debug 功能,我们需要设立在消息流的服务端和客户端上设立断点,发送消息到 MQInput 对应的 Queue 中,执行调试,如下图所示:
可看到,SOAP 请求发出后,消息流可继续往下执行到 MQ Send Output,而此时服务端 SOAP 回复消息尚未返回;另外,当 SOAP 消息返回后,我们可看下图,Thread4720 和 Thread6228 同时在执行,表明 SOAPAsyncRequest 后续流程和 SOAP Asynchronous 后续流程亦能并发执行。从而,我们通过本例了解了 MB6.1 异步请求的实际执行情况。
结束语
构造高效的 ESB,在 ESB 上以 Web Service 方式提供服务在实践中使用越来越多,在本文中,通过介绍 Message Broker 6.1 的 SOAP 新节点,我们了解了同步和异步两种 Web Services 在 Message Broker 6.1 中的实现,体验了它给我们的 Web Services 开发带来的好处。另外,在实际的企业 ESB 总线设计中,往往需要结合服务注册发布等功能,Message Broker 6.1 亦提供了 Register Lookup node 和 Endpoint Lookup node 支持服务的注册、发布、查找,极其地方便了和 WSRR 等服务注册库的整合。读者如有兴趣,可以查看参考资源中的文档资料,充分利用 Message Broker 6.1 给我们带领的强大功能。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| 示例代码 | attachedfile.zip | 128KB | HTTP |
|---|
|