简体   繁体   English

Apache CXF在Web服务上的命名空间问题

[英]namespace issue on web service with Apache CXF

I'm using Apache CXF 2.7.3, and running into a namespace issue that I really don't understand. 我正在使用Apache CXF 2.7.3,并遇到一个我真的不明白的命名空间问题。 I've tried extensively to search on this, but most of the results that I find are for different behaviors. 我已经尝试过广泛搜索,但我找到的大部分结果都是针对不同的行为。 The issue is when invoking the web service, it will fail if the parameter element is namespace qualified. 问题是在调用Web服务时,如果参数元素是名称空间限定的,它将失败。 All the rest of the elements in the message are qualified, and it accepts that, just not the parameter element. 消息中的所有其他元素都是合格的,它接受它,而不是参数元素。 Here is the precise behavior: 这是精确的行为:

request WITHOUT parameter element qualified: 请求WITHOUT参数元素限定:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:ord="http://www.example.org/order">
<soapenv:Header/>
   <soapenv:Body>
      <ord:getOrder>
         <id>a</id>
      </ord:getOrder>
   </soapenv:Body>
</soapenv:Envelope>

results in success: 结果成功:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:getOrderResponse xmlns:ns2="http://www.example.org/order">
         <return>
            <ns2:errorCode/>
            <ns2:errorMessage/>
            <ns2:order>
               <ns2:orderNumber>ABC123</ns2:orderNumber>
               <ns2:lastName>Smith</ns2:lastName>
            </ns2:order>
         </return>
      </ns2:getOrderResponse>
   </soap:Body>
</soap:Envelope>

request WITH parameter qualified: 请求WITH参数限定:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:ord="http://www.example.org/order">
   <soapenv:Header/>
   <soapenv:Body>
      <ord:getOrder>
         <ord:id>a</ord:id>
      </ord:getOrder>
   </soapenv:Body>
</soapenv:Envelope>

results in exception from JAXB: 导致JAXB异常:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Client</faultcode>
         <faultstring>Unmarshalling Error: unexpected element (uri:"http://www.example.org/order", local:"id"). Expected elements are &lt;{}id></faultstring>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

In all the research I have done, this usually means that a namespace doesn't match up somewhere. 在我所做的所有研究中,这通常意味着命名空间在某处不匹配。 But I have checked it thoroughly, and the namespace is identical everywhere, including the ObjectFactory.class, package-info.class, and the cxf-servlet.xml configuration file as well as the @WebService annotation. 但是我已经彻底检查了它,并且命名空间在任何地方都是相同的,包括ObjectFactory.class,package-info.class和cxf-servlet.xml配置文件以及@WebService注释。 Can anyone point me in the right direction as to what I am missing here? 任何人都可以指出我正确的方向,我在这里失踪了什么?

The source of the problem is wsgen, and I think this is a bug. 问题的根源是wsgen,我认为这是一个错误。 It does not make the wsdl and the jaxb generated classes compatible. 它不会使wsdl和jaxb生成的类兼容。 In the jaxb generated classes, the elements are not default form qualified, which puts the parameter element into a null namespace. 在jaxb生成的类中,元素不是默认形式限定的,它将参数元素放入空命名空间。 However in the WSDL, it IS default form qualified, and therein lies the problem. 但是在WSDL中,它默认的表单限定,其中存在问题。 There are probably a number of ways to solve this, the most quick and dirty way I found is to set the targetNamespace on the @WebParam annotation. 可能有很多方法可以解决这个问题,我发现最快速和最脏的方法是在@WebParam注释上设置targetNamespace。 Here are code snippets to demonstrate what I mean, and I hope this helps someone else who runs into this. 以下是用于演示我的意思的代码片段,我希望这可以帮助遇到此问题的其他人。

Here is what I had originally for the bottom-up implementation class: 以下是我最初为自下而上的实现类所做的事情:

@WebService(serviceName="OrderService")
public class OrderService {

    public OrderResponse getOrder(@WebParam(name="id", targetNamespace="http://www.example.org/order") String id)  {

This will result in the following generated JAXB classes. 这将导致以下生成的JAXB类。 As you can see it sets the namespace for the root but its not form qualified, and it does not generate a package-info file either. 正如您所看到的那样,它为root设置了命名空间,但它不是形式限定的,并且它也不生成package-info文件。

@XmlRootElement(name = "getOrder", namespace = "http://www.example.org/order")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getOrder", namespace = "http://www.example.org/order")

public class GetOrder {

    @XmlElement(name = "id")
    private java.lang.String id;

Then I changed the service implementation class, to add the namespace to the @WebParam: 然后我更改了服务实现类,将命名空间添加到@WebParam:

@WebService(serviceName="OrderService", targetNamespace="http://www.example.org/order")
public class OrderService {

    public OrderResponse getOrder(@WebParam(name="id", targetNamespace="http://www.example.org/order") String id)  {

While that doesn't make it default form qualified, it does add the namespace to the element in the generated JAXB class: 虽然这不会使默认表单限定,但它会将命名空间添加到生成的JAXB类中的元素:

@XmlRootElement(name = "getOrder", namespace = "http://www.example.org/order")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getOrder", namespace = "http://www.example.org/order")

public class GetOrder {

    @XmlElement(name = "id", namespace = "http://www.example.org/order")
    private java.lang.String id;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM