【问题标题】:How best to validate JAX-WS inputs?如何最好地验证 JAX-WS 输入?
【发布时间】:2013-07-02 08:56:45
【问题描述】:

我目前正在使用 JAX-WS 编写一组新的 Web 服务,但在确定验证输入的最佳方式时遇到了困难。我可以在我的实现类中进行一些验证,但一些输入错误会静默失败。例如,数字元素中的字符数据将导致 JAXB 对象中的 Integer 为空。

这些是我遇到的设计。

  1. @SchemaValidation
    我可以将此注释添加到端点类,JAX-WS 将负责验证。这在 tomcat 本地工作,但有人担心它不会在某些服务器上工作。我的主要抱怨是我必须放弃对错误在响应中的输出方式的控制。

  2. 所有输入为字符串
    我讨厌这种方法,但我见过其他所有输入都定义为字符串的 Web 服务。这将捕获数字元素中字符数据的情况,因为我可以在调用 API 的地方检查它,尽管您仍然会错过任何命名错误的 xml 元素。

我真的希望错误以与 API 错误相同的方式返回,而不是肥皂错误。有任何想法吗?我见过一些网站谈论使用一种过滤器来拦截请求。不过,不确定这将如何处理不同操作的不同响应。

例如

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <myOperationResponse>
         <return>
            <success>false</success>
            <errors>
               <error>
                  <code>UNIQUECODE</code>
                  <message>Message text</message>
               </error>
            </errors>
         </return>
      </myOperationResponse>
   </S:Body>
</S:Envelope>

也许我要求太多,但我想看看我是否错过了什么。 TIA。

【问题讨论】:

    标签: java jaxb jax-ws


    【解决方案1】:

    我不确定我是否理解你的正确,但这可能对你有帮助:

    http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html

    【讨论】:

    • 看了一下,但这假设我有原始 xml 可以使用。当我的端点收到请求时,它已被映射到 pojo。
    【解决方案2】:

    如果您坚持控制(就像您在执行 Jax-WS 时通常需要放弃...),您可以实现针对 XSD 架构进行验证的 Provider 和 Validator。

    XSD Schema 将负责验证输入(类型和可能的枚举、模式匹配等...)

    要将javax.xml.ws.Provider 实现为您的 SOAP 端点,请创建一个如下所示的类

    @javax.xml.ws.ServiceMode(value = javax.xml.ws.Service.Mode.MESSAGE)
    @javax.xml.ws.WebServiceProvider(
        wsdlLocation = "WEB-INF/wsdl/MyService.wsdl", 
        targetNamespace = "urn-com-acme-webservice", 
        serviceName = "ProcessPurchaseOrderService", 
        portName = "ProcessPurchaseOrderPort"
    )
    public class ProcessPurchaseOrder implements Provider<SOAPMessage> {
    
    
                @override
        public SOAPMessage invoke(final SOAPMessage request) {
    
                    //see below     
        }
    }
    

    SOAPMessage 将被传递给 invoke 方法,该方法期望返回有效响应或包装在 SOAPMessage 中的 SOAPFault;

    要再次验证 XSD,请使用 javax.xml.validator

        URL url = this.getClass().getResource(xsdSchemaLocation);
    
        String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;
        SchemaFactory factory = SchemaFactory.newInstance(language);
        Schema schema = factory.newSchema(url);
    
        validator = schema.newValidator();
    

    提取SOAPBody xml 并使用validate() 方法针对Validator 进行验证。

    围绕验证捕获异常并构建您自己的 SOAP 错误:

     //Build the SOAP Fault Response
     MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
     SOAPMessage response = factory.createMessage();
    
     SOAPFault fault = response.getSOAPBody().addFault();
     fault.setFaultString(myCustomErrorString);
    
     fault.addDetail().addChildElement("exception").addTextNode(myCustomErrorId);
    

    然后返回包含故障的 SOAPMessage。

    (不,我不喜欢 SOAP Web 服务)

    【讨论】:

    • 大声笑我也没有,但有时我们无法选择;)我试图让开发尽可能简单,所以我认为这可能会让一些人感到困惑。
    • 这可以和 Axis 一起使用吗?
    【解决方案3】:

    在您尝试实现的场景中,不会出现任何 SOAP 错误。验证逻辑(将成为最终处理请求的代码的一部分)必须确保处理所有验证场景。

    我们曾经遇到过这样的情况,在第三方集成我们的 Web 服务时,无法从 SOAP 错误中解读出太多信息,因此我们按照您的设想创建了错误响应。我建议采用以下方法。

    • 编写您自己的验证逻辑
    • 创建适当的对象结构。您已经拥有一个 XML 格式的文件。只需要客观化它。
    • 调用此验证逻辑并将输入对象传递给它。验证逻辑将验证所有输入并填充适当的响应对象 (myOperationResponse)。
    • 返回验证方法时,检查状态或错误对象。如果有错误,则返回响应对象或继续进一步处理请求,然后返回成功响应。

    【讨论】:

    • 这听起来像是已经发生的事情,但问题是如果它不能将元素映射到 jaxb 对象,那么它就会默默地失败。
    • 你是对的。只是想知道在您的情况下,JAXB 元素的 null 值是否足以指示验证失败。
    • 并非如此。你怎么知道是有错误还是他们没有通过的可选元素?
    【解决方案4】:

    发现这篇文章解释了一种可能的方法。
    http://one-size-doesnt-fit-all.blogspot.co.uk/2009/04/jax-ws-schemavalidation-custom-handler.html

    我让它在我的标准响应布局中返回解析错误消息。我只需要测试它是否可以在客户机器上运行。 (有些人说他们遇到了@SchemaValidation 的问题)

    【讨论】:

    • 投票让我想起了这一点。现在已经为多个项目投入生产,我们没有遇到任何问题。
    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 2012-09-10
    • 2012-05-25
    • 2012-01-05
    相关资源
    最近更新 更多