Apache CXF在Web服务上的命名空间问题 [英] namespace issue on web service with Apache CXF

查看:1927
本文介绍了Apache CXF在Web服务上的命名空间问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Apache CXF 2.7.3,并遇到了我真的不明白的命名空间问题。我已经尝试过广泛搜索,但我发现的大部分结果都是针对不同的行为。问题是在调用Web服务时,如果参数元素是名称空间限定的,它将失败。消息中的所有其他元素都是合格的,它接受它,而不是参数元素。以下是准确的行为:

I'm using Apache CXF 2.7.3, and running into a namespace issue that I really don't understand. 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. 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:

请求 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>

结果成功:

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

请求 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>

导致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>

在我所做的所有研究中,这通常意味着命名空间在某处不匹配。但我已经彻底检查了它,并且命名空间在任何地方都是相同的,包括ObjectFactory.class,package-info.class和cxf-servlet.xml配置文件以及@WebService注释。任何人都可以指出我正确的方向,我在这里缺少什么?

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. Can anyone point me in the right direction as to what I am missing here?

推荐答案

问题的根源是wsgen,我认为这是一个错误。它不会使wsdl和jaxb生成的类兼容。在jaxb生成的类中,元素不是默认形式限定的,它将参数元素放入空命名空间。但是在WSDL中, IS 默认表单是合格的,其中存在问题。可能有很多方法可以解决这个问题,我发现最快速和最脏的方法是在@WebParam注释上设置targetNamespace。这里有代码片段来展示我的意思,我希望这可以帮助遇到此问题的其他人。

The source of the problem is wsgen, and I think this is a bug. It does not make the wsdl and the jaxb generated classes compatible. In the jaxb generated classes, the elements are not default form qualified, which puts the parameter element into a null namespace. However in the WSDL, it IS default form qualified, and therein lies the problem. 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. 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)  {

这将导致以下生成的JAXB类。正如您所看到的那样,它为root设置了名称空间,但它不是形式限定的,并且它也不会生成package-info文件。

This will result in the following generated JAXB classes. 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.

@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;

然后我更改了服务实现类,将命名空间添加到@WebParam:

Then I changed the service implementation class, to add the namespace to the @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)  {

虽然这不会使默认表格合格,但它会将命名空间添加到生成的JAXB类中的元素:

While that doesn't make it default form qualified, it does add the namespace to the element in the generated JAXB class:

@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;

这篇关于Apache CXF在Web服务上的命名空间问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆