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

编程入门 行业动态 更新时间:2024-10-10 02:20:05
Apache CXF在Web服务上的命名空间问题(namespace issue on web service with Apache CXF)

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

请求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注释。 任何人都可以指出我正确的方向,我在这里缺少什么?

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:

request WITHOUT parameter element qualified:

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

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

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

最满意答案

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

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

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

这将导致以下生成的JAXB类。 正如您所看到的那样,它为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;

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

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

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;

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

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;

更多推荐

本文发布于:2023-07-17 10:08:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1142772.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:空间   Web   CXF   Apache   service

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!