问题 如何最好地验证JAX-WS输入?


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

这些是我遇到过的设计。

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

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

我真的希望错误以与API错误相同的方式返回,而不是作为soap错误。有任何想法吗?我看过一些网站正在谈论用一种过滤器拦截请求。不知道这对于不同的操作的不同响应如何工作。

例如。

<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。


4202
2017-07-04 11:12


起源



答案:


如果您坚持控制(在执行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并对其进行验证 Validator 使用 validate() 方法。

捕获验证周围的异常并构建自己的SOAP Fault:

 //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服务)


7
2017-07-04 12:03



大声笑我,但有时候我们没有选择;)我试图让开发尽可能简单,所以我觉得这可能会让一些人感到困惑。 - Ben Thurley
这可以和Axis一起使用吗? - ctomek


答案:


如果您坚持控制(在执行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并对其进行验证 Validator 使用 validate() 方法。

捕获验证周围的异常并构建自己的SOAP Fault:

 //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服务)


7
2017-07-04 12:03



大声笑我,但有时候我们没有选择;)我试图让开发尽可能简单,所以我觉得这可能会让一些人感到困惑。 - Ben Thurley
这可以和Axis一起使用吗? - ctomek


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

我让它在我的标准响应布局中返回解析错误消息。我只需要测试它将在客户机器上工作。 (有人说他们遇到过@SchemaValidation的问题)


7
2017-07-04 13:16



upvote让我想起了这个。现在几个项目正在生产中,我们没有遇到任何问题。 - Ben Thurley


在你想要实现的场景中,那里 不会是任何SOAP错误。验证逻辑(这将是最终处理请求的代码的一部分 ),必须确保处理所有验证方案。

我们遇到过这样的情况:第三方集成我们的Web服务无法解释SOAP故障,我们通过创建错误响应就像您构思的那样。我建议采用以下方法。

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

2
2017-07-04 12:38



这听起来像已经发生的事情,但问题是如果它无法将元素映射到jaxb对象,那么它就会无声地失败。 - Ben Thurley
你是对的。只是想知道JAXB元素的null值是否足以指示验证失败。 - Santosh
不是真的。你怎么知道是否有错误或者它是否是一个他们没有通过的可选元素? - Ben Thurley


我不确定我是否理解你,但maby这有助于你:

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


0
2017-07-04 11:38



看一下,但这假设我有原始的xml可以使用。当我的端点获得请求时,它已被映射到pojo。 - Ben Thurley