【问题标题】:SOAP faults or results object?SOAP 错误或结果对象?
【发布时间】:2010-05-12 22:05:21
【问题描述】:

我正在与一位同事讨论这个问题,但我们无法达成协议,所以我想听听你的想法。我对此有自己的看法,但我不会为你剧透。

什么时候应该返回一个SOAP 错误,什么时候应该返回一个包含错误信息的结果对象?假设这是一个可以被各种系统(.NET、Java 等)使用的通用 Web 服务。结果对象将有一个 isError 标志、一个 errorType(类似于特定的异常类型)和一条消息。

需要考虑的几点:

  1. 数据验证错误是否属于故障?
  2. 是否应该同时存在错误(对于非常特殊的情况)和结果对象(对于“预期的”错误)?
  3. 您将如何对 SOAP 错误进行分组(关键 [空引用] 与验证 [邮政编码不正确])?
  4. 快速失败与必须记住检查错误
  5. 最佳实践、模式、标准等

文章链接有效。尽管听起来我需要您的意见,但请坚持事实(x 更好,因为 y 和 z...)

【问题讨论】:

  • 六年后,我从 SOAP 1.2 中学到了一些新东西:w3.org/TR/soap12-part1/#faultcodes 故障的Code 元素可以具有值Sender,它被描述为The message... did not contain the appropriate information in order to succeed. For example, the message could lack... payment information. It is generally an indication that the message is not to be resent without change. 这对我来说似乎是数据验证因此表明应该使用故障。

标签: web-services exception-handling soapfault


【解决方案1】:

大多数 SOAP 客户端会将错误转换为运行时异常(如果客户端语言支持的话)。考虑到这一点,我认为您可以将问题改写为“我什么时候想抛出异常而不是返回错误值”?我相信您可以找到很多关于 API 设计的总体意见,特别是关于该主题的意见。

也就是说,返回错误通常对客户端没有帮助:

  1. 客户端需要手动枚举和处理您的错误代码,而不是允许存根代码生成并抛出适当类型的异常。使用错误代码可以防止客户端使用面向对象的技术,例如通过超类处理异常。

  2. 如果您不将错误代码作为 WSDL 的一部分;客户将没有关于它们是什么或何时发生的文档。类型错误是 WSDL 的一部分,因此(在一定程度上)是自记录的。

  3. 故障消息可以包含客户端可用于错误报告和恢复的特定于故障的上下文。例如,抛出包含实际无效输入元素和原因的输入验证错误。如果您返回带有错误代码和不透明字符串的结果,客户端别无选择,只能将您的错误消息传递给用户,这会破坏国际化、UI 一致性等。

回答您的具体问题:

  1. 验证错误是错误。想象一下,如果您从具有有限错误处理能力的 AJAX 客户端调用 Web 服务;您希望服务返回 5xx HTTP 代码,而不是带有一些意外响应的 400 成功代码。

  2. 没有。 API 应提供一致的错误报告接口。 WSDL 设计是 API 设计。强制客户端实现两个不同的错误处理程序不会让客户端的生活更轻松。

  3. 故障设计应反映您的请求/响应模型并显示适合服务抽象的信息。不要设计 NullReference 错误;设计一个 XYZServiceRuntimeFault。如果客户端经常提供无效请求,设计一个 InvalidRequestFault,带有适当的子类,以便客户端可以快速找出无效数据在哪里。

【讨论】:

  • 我很难决定给谁回答...@gibbss 是第一位的,@Richard 的参考资料很好。我认为您提出了一个很好的观点,即“强制客户端实现两个不同的错误处理程序”。仅仅因为存在可能包含错误信息的结果对象并不意味着永远不会发生 SOAP 错误。我会再考虑一下...
  • 好答案。只想指出 400 代码是错误的请求响应,而 200 是成功响应。
  • @yogibear 如果web服务器抛出错误是4xx,如果应用程序抛出错误是5xx,成功是200。
【解决方案2】:

结果对象应该只包含结果。如果您的结果对象提供了另一个系统上发生的错误列表,那么这就是您何时可以拥有“isError”标志的示例;否则你不能,因为结果要么有效要么无效。

当发生错误时,您应该始终使用 SOAPFault。验证是一个错误,认为验证不如无法打开数据库严重是魔鬼自己的陷阱。这两种情况的影响相同 - 操作无法按要求完成。

因此,您应该使用结果对象来表示结果,而 SOAP 错误则应该用于阻止有效结果对象的任何事情;包括但不限于错误、验证失败、警告、总线故障等。

在异常发生之前的日子里,没有选择,因此许多 API 变得不一致,并且大多数 API 在如何返回错误方面存在差异。它曾经(现在仍然是)可怕、令人困惑并且经常减慢开发速度,因为您必须查找每个 API 条目如何返回错误,并且通常如何解码或了解有关错误的更多信息。

  1. 当您考虑它时,使用 SOAPFaults / Exceptions 处理验证更合乎逻辑,并且一旦您考虑它通常会更容易。您确实需要设计验证故障类,以便它包含足够的信息来以不一定需要原始请求的方式识别违规元素。这样您就可以开始更通用地处理验证错误。

  2. 如果结果对象包含错误,则它们只能在结果的域内;例如,产品缺货,因为仓库中的某个人无法计算库存控制范围内。

  3. 区分严重错误和验证错误是不明智的,在我看来这不是一个有效的比较,因为任何严重级别的分配都是非常主观的。例如,在向消防员提供化学品信息的系统中,严重可能意味着着火的卡车载有 UN 1298 和 UN 1436,并且在尝试加载警告图形时不是空引用。

    设计故障,以便能够简明地识别并相应地处理它们。确保它们传达足够的信息。当您有足够的信息时,Abritrary 分类是不必要的,因为错误将允许自己被识别。

  4. 将 SOAPFault 转换为异常是实现快速失败的最可靠方法。

  5. 最佳实践、参考资料等

【讨论】:

  • 在第 3 点上,我可能想要显示验证错误(电子邮件无效),而不是任何其他类型的异常。我不完全同意不将它们分组。毕竟,这就是为什么我们在 .NET 中有这么多 Exception 类(IOException、ArgumentException 等)。当然,它们仍然是 Exceptions 并且没有以自定义方式处理,但它们是分组的。
  • 异常可以并且应该按类型或类来识别,例如验证失败、安全失败、相关密钥失败。但是,不应将这些身份分组(或放入类别),因为这意味着处理程序应在每个实例的基础上做出决定。虽然如果您正在处理所有异常,您可能希望显示验证失败,那么由处理程序根据它们的类型来区分它们。
【解决方案3】:

我认为简短的回答是使用肥皂故障,除非您知道客户端将有能力处理作为结果返回的错误。如其他答案中所述,我还在考虑异常和错误结果之间的类比。

根据客户的需要,有一些灰色区域可以被合理地视为异常和结果错误。然后,您可以向服务提供一个参数,以更改这些错误类型的返回方式。默认是使用 SOAP 错误,但如果客户端设置参数以获取错误结果,则表明它愿意将此作为结果的一部分进行处理。对我来说,验证错误就在这个灰色区域。对于大多数客户端,它们应该被视为错误,但如果客户端想要使用数据来标记带有验证错误的 UI,那么将验证错误作为结果的一部分返回可能会更有用。

【讨论】:

    【解决方案4】:

    我在服务设计中遵循的规则是:

    • 业务级别响应(甚至业务异常)到响应对象
    • 技术/集成级别故障进入肥皂故障

    服务消费者可以相信所有类型的业务响应都来自响应对象并将其呈现给服务(业务)用户。只有在无法交付业务响应时才使用肥皂故障。

    Soap 故障应通过监控触发支持警告/操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-24
      • 1970-01-01
      • 2018-01-20
      • 2021-03-12
      相关资源
      最近更新 更多