4

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

没有限定参数元素的请求:

<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注解。谁能指出我在这里缺少什么的正确方向?

4

1 回答 1

8

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

这是我最初为自下而上的实现类所做的:

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

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

这将产生以下生成的 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")
    private java.lang.String id;

然后我更改了服务实现类,将命名空间添加到@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 类中的元素中:

@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;
于 2013-05-14T18:23:30.500 回答