内容


IBM WebSphere Message Broker V6.1 中的 SOAP 节点,第 2 部分

SOAP 域逻辑树

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: IBM WebSphere Message Broker V6.1 中的 SOAP 节点,第 2 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:IBM WebSphere Message Broker V6.1 中的 SOAP 节点,第 2 部分

敬请期待该系列的后续内容。

SOAP 域逻辑树简介

本系列的第 1 部分中描述的 SOAP 节点为所有 Web 服务消息提供了一致的逻辑树表示形式。在运行时,如图 1 所示的 SOAP 域逻辑树用于表示所有的 Web 服务消息格式。

图 1. SOAP 域树
SOAP 域树
SOAP 域树

树格式为用户提供了一种方便的方式来访问消息的重要部分:SOAP 正文、SOAP 标题和任何 SwA 附件(有关本文章系列中使用的术语的定义,请参阅术语列表)。消息以与位流(bitstream )消息格式无关的一致方式来提供。

树中的 SOAP 元素松散地对应于 Web 服务消息中的 SOAP 信封。HeaderBody 元素表示 SOAP 消息的标题和正文(有效负载)部分。上下文信息保存在 Context 下面,例如命名空间属性和 WSDL 派生的信息。所有的 SwA 附件出现在 Attachment 下面。(如 MTOM 部分所述,MTOM“附件”以内联的方式表示为 SOAP 内容的一部分。)

使用 SOAP 树

在以下两种场景之一中,将会自动创建 SOAP 域树(请参见图 1):

  • SOAPInput 节点接收到 Web 服务请求。
  • SOAPRequest 或 SOAPAsyncResponse 节点接收到 Web 服务响应。

当消息流使用 SOAPReply、SOAPRequest 或 SOAPAsyncRequest 节点来发送 Web 服务消息时,必须提供 SOAP 域树(不过此规则存在一些例外;请参阅消息域部分)。

在 SOAPInput-SOAPReply 流的情况下,通常修改 SOAPInput 节点创建的 SOAP 域树来创建所需的 Web 服务响应消息。

在 SOAPRequest 或 SOAPAsyncRequest 的情况下,消息流可能需要从头创建 SOAP 域树。这是使用任何代理转换节点来完成的。下面几个部分将演示对 Compute 节点使用扩展 SQL (ESQL) 的示例。

消息域

SOAP 节点的不同寻常之处在于,它们与特定的域相关联:SOAP 域。如果查看 SOAPInput 和 SOAPRequest 节点的 Message domain 属性,可以看到已预先将其选择为 SOAP。这是因为 SOAP 节点有效地包含 与 SOAP 相关联的语义,例如 WS-Addressing 和 WS-Security 支持。

因此,SOAP 节点通常与 SOAP 域树一起工作,本文的其余内容将对此进行描述。但是,存在两个例外:

  • 可以向 SOAPReply、SOAPRequest 或 SOAPAsyncRequest 节点提供非 SOAP 域 树。特别是在 SOAPRequest 或 SOAPAsyncRequest 的情况下,您可以拥有表示 SOAP 请求数据的非 SOAP 消息树。作为便利措施,您可以将这样的树直接传递给节点。最常见的示例是 XMLNSC 树。在此情况下,如果 XMLNSC 树的根元素是型式正确的 SOAP 信封,则消息将按原样使用。否则,将把根元素视为 SOAP 正文有效负载,并自动添加适当的信封。这可能非常便利,但是请注意,SOAP 域树通常为您提供了更多的灵活性和控制。
  • 可以将 SOAP 域树提供给非 SOAP 输出节点。如果将 SOAP 域树发送到非 SOAP 输出节点,当前会写出该树的 XML 序列化,而不是 SOA 样式的 Web 服务消息。这种机制允许将 SOAP 域与 Aggregation 和 Collector 节点结合使用,这些节点需要能够序列化并重新创建逻辑树。通常,您不会看到这种 XML 序列化的形式,除非您显式地将 SOAP 域消息发送到非 SOAP 输出节点,例如 MQOutput。这样的消息也许只有有限的用途,虽然可以在对应的输入节点中将其读回,在此情况下,将选择带 SOAP 域的 MQInput 节点。

ESQL 命名空间声明和代码自动完成

ESQL 通常至少使用两个命名空间:SOAP 信封的命名空间和应用程序数据使用的一个或多个命名空间。如果使用 ESQL 编辑器的内容辅助功能,则会自动向 ESQL 添加适当的命名空间声明。(ESQL 命名空间声明与 XML 中的命名空间前缀的概念密切对应。有关如何在写出树时控制命名空间前缀的信息,请参阅 SOAP.Context 部分。)在下面的示例中,应用程序数据使用 http://a/b/c/myNamespace 命名空间, 并假设已经做出了以下命名空间声明:

DECLARE ns1 NAMESPACE 'http://a/b/c/myNamespace'

同时,还假设已经为适当的 SOAP 信封命名空间做出了类似的声明 soapenv。如果 WSDL 指定了 SOAP 1.1 绑定,则该声明将为:

DECLARE soapenv NAMESPACE 'http://schemas.xmlsoap.org/soap/envelope/'

请注意,在消息集中导入或生成 WSDL 定义时,开发时内容辅助功能和映射节点支持是自动启用的。所创建的消息定义同时定义了 SOAP 域树本身和可出现在其中的特定于应用程序的数据。内容辅助功能也称为代码自动完成。实际上,它意味着您可以输入类似于 SET OutputRoot.SOAP 的内容,然后按 Ctrl+Space,并让 ESQL 编辑器为您提供可出现在该路径中的此位置的有效元素选择。(如果代码自动完成功能似乎没有生效,请检查消息集的缺省消息域是否为 SOAP,并且在消息流项目的 Properties > Project References 下选择您的消息集项目。)

SOAP.Body

SOAP 消息具有一个 XML 根标记 soapenv:Envelope。SOAP 消息的内容或有效负载作为 soapenv:Body 出现在 Envelope 下面,并在逻辑树中表示为 SOAP.Body。如果您在消息流中构建 SOAP 树,则 SOAP.Body 是必须 提供的唯一树部分。请注意,SOAP.Body 是 SOAP 域树中的逻辑路径。无论使用什么 SOAP 版本,它都是相同的。特别是,逻辑树中的这些元素没有限定命名空间。

下面的示例显示了一个 SOAP 响应的构造,在此例中是通过修改对应 SOAP 请求中接收的值来构造的(即假设消息流为 SOAPInput - Compute – SOAPReply):

SET OutputRoot.SOAP.Body.ns1:responsePayload.X=InputRoot.SOAP.Body.ns1:requestPayload.Y

请注意:

  • SOAPInput 节点是使用一个 WSDL 绑定来配置的,该绑定定义一个或多个 WSDL 操作。
  • XML 元素 ns1:requestPayload 标识了其中一个操作,我们将其称为 op1
  • WSDL 指定了 op1 的响应必须为 ns1:responsePayload
  • WSDL 还包括 XML 模式定义,其中定义了 ns1:requestPayloadns1:responsePayload 的详细结构。

SOAP.Header

SOAP 信封还包含(可选的) soapenv:Headersoapenv:Header 的任何子元素称为标头块,并在逻辑树中包含在 SOAP.Header 下面。您的 WSDL 中的 XML 模式可能定义了标头块,也可能没有定义。

下面的示例说明了如何在现有的 SOAP 树的基础上填充所有标头块:

SET OutputRoot.SOAP.Header = InputRoot.SOAP.Header

或者,您可能希望填充选定的标头;在下面的示例中,该标头块为 ns1:header1

SET OutputRoot.SOAP.Header.ns1:header1 = InputRoot.SOAP.Header.ns1:header1

在这两种情况下,您还可能希望添加某些新的标头;在下面的示例中,该标头块为 ns1:newHeader

SET OutputRoot.SOAP.Header.ns1:newHeader = '42'

最后,下面的示例说明了如何向该标头添加属性(在 WebSphere Message Broker V6.1 的初始版本中,您需要使用 XMLNSC 关键字而不是 SOAP 来限定元素类型):

SET OutputRoot.SOAP.Header.ns1:newHeader.(SOAP.Attribute)soapenv:mustUnderstand = '1'

注意:mustUnderstand 将在本系列的第 4 部分中进行描述。

SOAP.Attachment (SwA)

正如前面提到过的,树中的 SOAP 元素松散地对应于 SOAP 信封。关键区别在于,SOAP 逻辑树 包含 Web 服务消息的任何附件。这意味着无论消息的位流是 SwA、MTOM 还是纯 SOAP,逻辑树结构都是相同的。

每个 SwA 附件保存在其 Content-Id 下面。例如,带标头 Content-Id=Id1 的多用途 Internet 邮件扩展(Multipurpose Internet Mail Extensions,MIME)部分保存在 SOAP.Attachment.Id1 下面。附件的完整 MIME 标头集存储在子文件夹 MIME_Headers 下面,数据本身表示为 BLOB

下面的示例说明了如何在现有的 SOAP 树的基础上填充所有的附件:

SET OutputRoot.SOAP.Attachment = InputRoot.SOAP.Attachment

或者,您可能希望填充选定的附件,在此例中为 Id1

SET OutputRoot.SOAP.Attachment.Id1 = InputRoot.SOAP.Attachment.Id1

在两种情况下,您还可能希望添加某些新的附件。假设您希望在新的 Content-Id Id2 下添加一个附件。下面的示例有点做作,但是演示了一种设置附件数据的方法;在此例中,二进制数据恰好对应于 ASCII 字符 <HelloWorld/>:

SET OutputRoot.SOAP.Attachment.Id2.BLOB = X'3c48656c6c6f576f726c645c3e'

最终的位流是一个 MIME 消息。顶级 Content-Type 是使用类似如下的值自动生成的:

multipart/related; boundary=WMBMIME...; type="text/xml";start="<...>";charset=utf-8

start 参数标识的 MIME 部分(通常是第一个 MIME 部分)包含 SOAP 消息。第二个 MIME 部分是为新附件 Id2 而生成的。此部分的 Content-Type 缺省为 application/octet-stream,但是可以按如下方式显式地指定值:

SET OutputRoot.SOAP.Attachment.Id2.MIME_Headers."Content-Type" = 'text/xml'

您可能希望显式地设置的另一个标头是 Content-Id:

SET OutputRoot.SOAP.Attachment.Id2.MIME_Headers."Content-Id" = 'Id3'

如前所述,缺省的 Content-Id 值是 Attachment 的子元素的名称。在此例中,缺省的 Content-Id 为 Id2,但是将由 ESQL 重写,并将改为使用值 Id3

在输出时,如果 SOAP 域树在 SOAP.Attachment 下面具有任何子元素,则位流将写为 MIME(明确地说是写为 SwA),并且附件将显示为单独的 MIME 部分。在此情况下,WSDL 绑定是否指定使用 MIME 并不重要。

MTOM

MTOM 似乎与 SwA 类似,因为它们都使用 MIME。然而,MTOM 仅将 MIME 用作优化机制,允许以未编码(因此未展开)的方式在网络上 发送二进制数据。

必须在 SOAP 消息中进行编码的数据将在单独的 MIME 部分中作为原始二进制数据进行传输。大块二进制数据所占的空间比其编码的表示形式更小,因此 MTOM 可以减少传输时间(尽管它会引入某些处理开销)。使用 MTOM 来传输的候选元素在 WSDL(XML 模式)中定义为 base64Binary。在 SwA 中,附件被视为逻辑上单独的项。在 MTOM 中,元素始终保持为 SOAP 消息的不可分割的一部分;它们只是在消息“正在传输”时临时地分拆开。

图 2. SwA 与 MTOM 之比较
SwA 与 MTOM 之比较
SwA 与 MTOM 之比较

SOAP 域自动处理入站 MTOM 消息。不过,您不会在 SOAP 域树中看到 MTOM 的任何迹象;MTOM 部分已经重新合并到了 SOAP 正文中。

可以在 SOAPRequest、SOAPAsyncRequest 和 SOAPReply 节点上配置对出站 MTOM 消息的使用。如果以下所有条件均属实,则会写出 MTOM 输出消息:

  • 节点的 WS Extensions 选项卡上的 Allow MTOM 选项已选中。
  • 节点的 Validation 选项卡上的 Validation 已启用。
  • 输出消息中的有些元素在关联的 XML 模式中标识为 base64Binary,并且其长度不会低于 1000 个字节的缺省阈值大小(让我们将这些元素称为限定元素)。

在此情况下,限定元素将输出为 MTOM 消息中的各个 MIME 部分。否则,将不会使用 MTOM。可以使用用户跟踪消息来确认是否使用了 MTOM。Allow MTOM 节点选项和缺省的 element-size 阈值可以在 LocalEnvironment 中进行覆盖。

下面的代码片段中的 ESQL 演示了在 SOAPRequest 或 SOAPAsyncRequest 节点之前设置的 Allow MTOM 和 element-size 阈值:

SET OutputLocalEnvironment.Destination.SOAP.Request.AllowMTOM = true;
SET OutputLocalEnvironment.Destination.SOAP.Request.MTOMThreshold = 100; -- bytes

SOAPReply 节点需要的等效设置如下面的示例所示:

SET OutputLocalEnvironment.Destination.SOAP.Reply.AllowMTOM = true;
SET OutputLocalEnvironment.Destination.SOAP.Reply.MTOMThreshold = 100; -- bytes

请注意,SwA 和 MTOM 没有一起使用,并且 SOAP.Attachment 下面任何子元素的存在始终会导致仅使用 SwA,而不进行任何 MTOM 处理。

MTOM 消息的顶级 Content-Type 具有如下所示形式的值:

>multipart/related;boundary=WMBMIME...; type="application/xop+xml";
start="<...>";charset=utf-8

SOAP.Context

正如已经描述过的,WSDL 在配置使用 SOAP 节点的消息流方面起作重要作用。事实上,当在运行时创建树时,将会向树的 SOAP.Context 部分添加某些从 WSDL 派生的关键信息。例如,在 SOAP.Body 部分所示的示例中,operation=op1 将包括在 Context 之下。

不过,本部分将描述影响输出 位流(从而可能需要在消息流中进行显式设置)的 SOAP.Context 方面。

首先,下面的示例说明了如何在现有树的基础上填充整个 SOAP Context:

SET OutputRoot.SOAP.Context = InputRoot.SOAP.Context

下面几个部分将描述 SOAP.Context 的各个组成部分所起的作用。

命名空间

SOAP.Context 的关键部分之一是 Namespace 子树。通常,您希望为消息中的命名空间 URI 指定特定的命名空间前缀。(否则将会自动生成前缀名称。)当接收到某个 Web 服务消息时,将会自动在 SOAP.Context.Namespace 下面创建适当的条目,并且通常不需要进一步的操作。然而,如果是从头创建 SOAP 树,或者需要添加或修改命名空间前缀定义,您可以通过在 SOAP.Context.Namespace 下面添加或修改该名-值对子元素来实现此目的。

可以使用下面的示例中的 ESQL 来创建 ns1 的命名空间前缀定义:

SET OutputRoot.SOAP.Context.Namespace.(SOAP.NamespaceDecl)xmlns:ns1=
'http://a/b/c/myNamespace';

注意:同样地,在 WebSphere Message Broker V6.1 的初始版本中,您需要使用 XMLNSC 关键字而不是 SOAP 来限定元素类型。

如果尝试设置某个特定的命名空间前缀,而该前缀未出现在位流中,您可以检查元素类型。下面的代码片段是某个 Trace 节点的输出的一部分,包括本示例的模式 ${Root}。元素类型是十六进制字符串,在每一行的开头:

(0x01000000):Namespace = (
(0x03000102)http://www.w3.org/2000/xmlns/:SOAP-ENV = 'http://.../soap/envelope/'
(0x03000102)http://www.w3.org/2000/xmlns/:ns1 = 'http://a/b/c/myNamespace'
)

这些命名空间前缀定义与位流中的命名空间前缀声明相对应,如下所示:

<SOAP-ENV:Envelope xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/
xmlns:ns1="http://a/b/c/myNamespace">...

SOAP 版本

如果指定了 Context.SOAP_Version 并且其值有效(1.1 或 1.2),则会输出指定版本的信封。否则,将使用 WSDL 中指定的 SOAP 版本。但是请注意,如果有效负载为 SOAP 错误,则确保错误消息与所选的 SOAP 版本兼容是用户的责任。

您可以使用以下 ESQL 在 SOAPRequest 或 SOAPAsyncRequest 节点之前显式设置 SOAP 版本:

SET OutputRoot.SOAP.Context.SOAP_Version = '1.2'

在此情况下,请注意,如果为响应启用了验证,您必须确保适当的 SOPA 信封消息定义在消息集中可用。您可以通过在消息集的上下文菜单中选择 New > Message Definition File From .../ IBM Supplied Message,然后选择适当的 SOAP 信封消息,从而实现此目的。(当您在消息集中导入或生成可部署的 WSDL 时,只有由 WSDL 绑定所指定的SOAP 信封才会导入。)

映射 SOAP 树

如果使用 Mapping 节点而不是 Compute 节点来处理 SOAP 树,您通常需要为 SOAP.Header 或 SOAP.Body 的任何转换定义子映射。这是因为 SOAP 树中的这些项定义为通配符。

有关子映射的讨论超出了本文的范围,但是值得提及一种替代方法。您可以修改 soap.mxsd(在消息集的缺省命名空间中),以便其显式列出消息中允许出现在 Header 或 Body 下面的元素。您需要对 soap.mxsd 做出的更改如下:

  1. 导入定义所需元素的 mxsd。如果您从导入 WSDL 开始,则 mxsd 是适当命名空间中类似于 my_InlineSchema.mxsd 的文件。在 soap.mxsd 的 Properties 选项卡上,右键单击 Imports,选择 Add Import,然后浏览至您的 mxsd。
  2. 添加对所需元素的引用。要添加可出现在 Body 下面的元素,请在 Outline 视图中展开 SOAP_Domain_Msg.Body(请参见图 3)。右键单击 message,从上下文菜单中选择 Add Message,然后选择要添加的元素。

图 3 显示了添加元素 e1e2e3 之后的 soap.mxsd。在此例中,app 是分配给您导入的命名空间的命名空间前缀。

图 3. 定制的 soap.mxsd
定制的 soap.mxsd
定制的 soap.mxsd

然后可以在定义映射时使用元素 e1e2 作为源或目标,如图 4 所示。

图 4. 消息映射编辑器
消息映射编辑器
消息映射编辑器

结束语

您已经研究了 SOAP 域逻辑树和如何使用它。在第 3 部分中,您将研究 SOAP 节点的详细配置。


相关主题


评论

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=SOA and web services, WebSphere
ArticleID=335697
ArticleTitle=IBM WebSphere Message Broker V6.1 中的 SOAP 节点,第 2 部分: SOAP 域逻辑树
publish-date=09042008