IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope:Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  SOA and Web services  >

Web Services 提示与技巧: 设计可重用的 WSDL 错误定义

developerWorks
文档选项
PDF 格式 - A4

PDF - A4
35KB

Get Adobe® Reader®

未显示需要 JavaScript 的文档选项

讨论

英文原文

英文原文


级别: 中级

Russell Butek (butek@us.ibm.com), SOA 和 Web 服务顾问, IBM 

2008 年 3 月 27 日

我们都赞同定义 Web 服务描述语言 (WSDL) 错误定义是较好的做法(如果您不同意,则不需要阅读本文)。存在许多定义 WSDL 错误的方法,但是只有有限的内容提到了重用。本文向您介绍可重用的 WSDL 错误定义模板、展示如何重用该模板,同时指出了一些应该注意的事项。

可重用的错误定义模板

在详细介绍如何重用错误定义之前,让我们先看一个可重用错误定义的示例。清单 1 显示了 XML 模式,清单 2 显示了 WSDL。


清单 1. 用于可重用错误定义的模板模式
                
<xsd:schema 
    targetNamespace="urn:SchemaTemplates"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:complexType name="Fault">
                    <xsd:sequence>
                      <xsd:element minOccurs="0" name="reason" type="xsd:string"/>
                    </xsd:sequence>
                  </xsd:complexType>
</xsd:schema>


清单 2. 可重用错误定义的模板 WSDL
                
<wsdl:definitions 
    targetNamespace="urn:WSDLTemplates"
    xmlns:tns="urn:WSDLTemplates"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
  <wsdl:types>
    <xsd:schema 
        targetNamespace="urn:WSDLTemplates" 
        xmlns:tns="urn:WSDLTemplates"
        xmlns:t="urn:SchemaTemplates"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:import namespace="urn:SchemaTemplates" schemaLocation="Fault.xsd"/>
      <xsd:element name="op1" type="tns:op1"/>
      <xsd:complexType name="op1">
        <xsd:sequence>
          <xsd:element name="input" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="op1Response" type="tns:op1Response"/>
      <xsd:complexType name="op1Response">
        <xsd:sequence>
          <xsd:element name="output" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="fault" type="t:Fault"/>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="op1RequestMsg">
    <wsdl:part name="op1Parameters" element="tns:op1"/>
  </wsdl:message>
  <wsdl:message name="op1ResponseMsg">
    <wsdl:part name="op1Result" element="tns:op1Response"/>
  </wsdl:message>
  <wsdl:message name="faultMsg">
                    <wsdl:part name="fault" element="tns:fault"/>
                  </wsdl:message>
  <wsdl:portType name="Interface">
    <wsdl:operation name="op1">
      <wsdl:input name="op1Request" message="tns:op1RequestMsg"/>
      <wsdl:output name="op1Response" message="tns:op1ResponseMsg"/>
      <wsdl:fault name="fault" message="tns:faultMsg"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="Binding" type="tns:Interface">
    <soap:binding 
        style="document" 
        transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="op1">
      <soap:operation soapAction=""/>
      <wsdl:input name="op1Request">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="op1Response">
        <soap:body use="literal"/>
      </wsdl:output>
      <wsdl:fault name="fault">
                        <soap:fault use="literal" name="fault"/>
                      </wsdl:fault>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="Service">
    <wsdl:port name="Port" binding="tns:Binding">
      <soap:address location="http://www.example.org/"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>





回页首


重用级别

如果您定义的 WSDL 符合此模式,则可以获得可重用的错误定义。但是可重用性具有许多级别。您没有必要遵守此处介绍的全部可重用性。让我们看一下这些级别。

WSDL 内重用(Intra-WSDL)

WSDL 内重用 是本地级别的重用:即 WSDL 文件中的重用。要实现 WSDL 内重用,请避免不必要的关联;特别是,避免将操作名称放入错误名称中。这听起来非常容易,但是一些工具可创建此类错误名称。例如,可能将消息名称生成为 op1_faultMsg。使用工具和图形编辑器可以非常容易地完成许多繁锁的工作,但是它们生成的内容有时可能不是您需要的。如果错误定义包含操作名称,那么在创建新的操作(例如 op2),并需要重用 op1 的错误时,在 op2 中引用 op1_faultMsg 看起来就有些奇怪了。您可以创建名为 op2_faultMsg 的另一个 WSDL 消息,它可引用 op1_faultMsg 引用的同一模式元素,但这是不必要的额外开销。如果将错误的消息名称与操作名称分离,则可以重用该消息,并且看起来也不感到陌生(请参见清单 3)。


清单 3. 将 op2 添加到 WSDL
                
  .
  .
  .
    <wsdl:operation name="op2">
      <wsdl:input name="op2Request" message="tns:op2RequestMsg"/>
      <wsdl:output name="op2Response" message="tns:op2ResponseMsg"/>
      <wsdl:fault name="fault" message="tns:faultMsg"/>
    </wsdl:operation>
  .
  .
  .

WSDL 间重用

WSDL 间重用 是 WSDL 之间的重用,其中多个 WSDL 可以使用同一错误定义。这里需要避免两种情况:

  • 显然,在 WSDL 的类型部分中不能定义您的错误定义。在 WSDL 类型部分中直接定义的任何内容仅对该 WSDL 可视。其他 WSDL 不可重用这些内容。
  • 第二种情况比较难,需要考虑到编程语言的映射。请看一下错误类型。因为 fault 包含单一字符串字段,您可能更愿意采用简单的路由,并将字符串直接放入错误元素中,而不是通过 t:Fault 获得该字符串。某些工具可创建此类错误(请参见清单 4)。

清单 4. 简单的错误定义
                  .
  .
  .
  <xsd:schema ...>
  .
  .
  .
    <xsd:element name="fault" type="xsd:string"/>
  </xsd:schema>
  .
  .
  .
  <wsdl:message name="faultMsg">
    <wsdl:part name="fault" element="tns:fault"/>
  </wsdl:message>
  .
  .
  .

当重用模式元素和模式类型时,请考虑 WSDL 要映射的编程语言。语言映射(如 Java™ API for XML-based RPC (JAX-RPC))以直接的方式将模式类型映射到语言构造。但是如何映射元素并不总是显而易见的。对于 JAX-RPC,错误定义可映射为一个异常类。如果使用类型定义错误,则从该错误的类型名称和命名空间映射该异常的名称和包。如果仅将错误定义为一个元素,则从消息名称映射异常的名称,从消息的命名空间映射数据包(请参见清单 5)。因此,错误定义仅在消息的封闭命名空间中可重用,没有普遍的可重用性。您可以定义重用现有错误元素的另一个错误消息,但是 JAX-RPC 仍将其映射为另一个异常;它不重用现有异常。


清单 5. 清单 4 中 WSDL 的 Java 签名
                
public String op1(String input) throws RemoteException, WSDLTemplates.FaultMsg;

对象重用

重用的最后一个级别更抽象一些。按以往方法定义一个错误,它不仅是一种错误,而且是一种数据类型。当错误数据必须位于 SOAP 错误的外部时,这特别有用,。例如,如果您在处理批操作时。在简单的操作中,您将有一组输入和一组输出。此操作的批量版本将包含输入集的数组和输出集的数组。如果操作的非批量版本也可以抛出错误,则应通过一种方法将错误数据插入输出数组。在定义与本文中类似的错误时,此操作非常容易。清单 6清单 7 显示了一个批量示例。它从清单 1清单 2 中 XML Schema Definition (XSD) 和 WSDL 的基础上构建,并添加一个称为 batchOp1 的 op1 批量版本以及它的其他数据类型。


清单 6. 用于批量操作错误的 XSD
                
<xsd:schema 
    targetNamespace="urn:SchemaTemplates"
    xmlns:tns="urn:SchemaTemplates"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:complexType name="Fault">
    <xsd:sequence>
      <xsd:element minOccurs="0" name="reason" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
<xsd:complexType name="Response" abstract="true"/>
                <xsd:complexType name="NormalResponse">
                 <xsd:complexContent>
                  <xsd:extension base="tns:Response">
                   <xsd:sequence>
                    <xsd:element name="response" type="xsd:string"/>
                   </xsd:sequence>
                  </xsd:extension>
                 </xsd:complexContent>
                </xsd:complexType>
                <xsd:complexType name="FaultResponse">
                 <xsd:complexContent>
                  <xsd:extension base="tns:Response">
                   <xsd:sequence>
                    <xsd:element name="fault" type="tns:Fault"/>
                   </xsd:sequence>
                  </xsd:extension>
                 </xsd:complexContent>
                </xsd:complexType>
</xsd:schema>


清单 7. 用于批量操作错误的 WSDL
                
<wsdl:definitions 
    targetNamespace="urn:WSDLTemplates"
    xmlns:tns="urn:WSDLTemplates"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
  <wsdl:types>
    <xsd:schema 
        targetNamespace="urn:WSDLTemplates" 
        xmlns:tns="urn:WSDLTemplates"
        xmlns:t="urn:SchemaTemplates"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:import namespace="urn:SchemaTemplates" schemaLocation="Fault.xsd"/>
      <xsd:element name="op1" type="tns:op1"/>
      <xsd:complexType name="op1">
        <xsd:sequence>
          <xsd:element name="input" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="op1Response" type="tns:op1Response"/>
      <xsd:complexType name="op1Response">
        <xsd:sequence>
          <xsd:element name="output" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:element name="batchOp1" type="tns:batchOp1"/>
                <xsd:complexType name="batchOp1">
                  <xsd:sequence>
                    <xsd:element name="input" type="xsd:string" 
                  maxOccurs="unbounded"/>
                  </xsd:sequence>
                </xsd:complexType>
                <xsd:element name="batchOp1Response" 
               type="tns:batchOp1Response"/>
                <xsd:complexType name="batchOp1Response">
                  <xsd:sequence>
                    <xsd:element name="output" type="t:Response" 
                   maxOccurs="unbounded"/>
                  </xsd:sequence>
                </xsd:complexType>
      <xsd:element name="fault" type="t:Fault"/>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="op1RequestMsg">
    <wsdl:part name="op1Parameters" element="tns:op1"/>
  </wsdl:message>
  <wsdl:message name="op1ResponseMsg">
    <wsdl:part name="op1Result" element="tns:op1Response"/>
  </wsdl:message>
  <wsdl:message name="faultMsg">
    <wsdl:part name="fault" element="tns:fault"/>
  </wsdl:message>
  <wsdl:message name="batchOp1RequestMsg">
                    <wsdl:part name="batchOp1Parameters" 
                   element="tns:batchOp1"/>
                  </wsdl:message>
                  <wsdl:message name="batchOp1ResponseMsg">
                    <wsdl:part name="batchOp1Result" 
                   element="tns:batchOp1Response"/>
                  </wsdl:message>
  <wsdl:portType name="Interface">
    <wsdl:operation name="op1">
      <wsdl:input name="op1Request" message="tns:op1RequestMsg"/>
      <wsdl:output name="op1Response" message="tns:op1ResponseMsg"/>
      <wsdl:fault name="fault" message="tns:faultMsg"/>
    </wsdl:operation>
    <wsdl:operation name="batchOp1">
                      <wsdl:input name="batchOp1Request" 
                     message="tns:batchOp1RequestMsg"/>
                      <wsdl:output name="batchOp1Response" 
                     message="tns:batchOp1ResponseMsg"/>
                    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="Binding" type="tns:Interface">
    <soap:binding 
        style="document" 
        transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="op1">
      <soap:operation soapAction=""/>
      <wsdl:input name="op1Request">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="op1Response">
        <soap:body use="literal"/>
      </wsdl:output>
      <wsdl:fault name="fault">
        <soap:fault use="literal" name="fault"/>
      </wsdl:fault>
    </wsdl:operation>
    <wsdl:operation name="batchOp1">
                      <soap:operation soapAction=""/>
                      <wsdl:input name="batchOp1Request">
                        <soap:body use="literal"/>
                      </wsdl:input>
                      <wsdl:output name="batchOp1Response">
                        <soap:body use="literal"/>
                      </wsdl:output>
                    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="Service">
    <wsdl:port name="Port" binding="tns:Binding">
      <soap:address location="http://www.example.org/"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

batchOp1 返回 Response 的数组。Response 是一种抽象类型,因此,您必须使用具体的扩展填充该数组。Response 数组元素可以包含 NormalResponse 对象或 FaultResponse 对象。

批量模型的实际扩展
在实际示例中,您可能有多个错误。要容纳这些错误,可以为错误构建层次结构,然后将所有错误的基类插入 FaultResponse 类型。

总结

尽可能扩展 WSDL 错误定义非常有用。希望您已了解了本文中介绍的操作方式。

分享这篇文章……

digg 提交到 Digg
del.icio.u 发布到 del.icio.u
Slashdot Slashdot 一下!



参考资料

学习

获得产品和技术
  • 使用 IBM 试用软件开发您的下一个项目,可下载或索取 DVD 光盘。


讨论


关于作者

Russell Butek 是 IBM 的一名 SOA 和 Web 服务顾问。他曾是 IBM WebSphere Web 服务引擎的开发人员之一。他也是 JAX-RPC Java Specification Request (JSR) 专家组的成员。他参与了 Apache 的 AXIS SOAP 引擎的实现,并推动 AXIS 1.0 遵守 JAX-RPC 1.0。




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

将您的建议发给我们或者通过参加讨论与其他人分享您的想法.







回页首


IBM 和 IBM 徽标是 IBM 在美国和/或其他国家/地区的注册商标。 Java 和所有基于 Java 的商标都是 Sun Microsystems, Inc. 在美国和/或其他国家/地区的商标。 其他公司、产品或服务的名称可能是其他公司的商标或服务标志。

IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款