我正在使用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 <{}id></faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
在我所做的所有研究中,这通常意味着命名空间在某处不匹配。但是我已经彻底检查了它,并且命名空间在任何地方都是相同的,包括ObjectFactory.class,package-info.class和cxf-servlet.xml配置文件以及@WebService注释。任何人都可以指出我正确的方向,我在这里失踪了什么?
答案 0 :(得分:8)
问题的根源是wsgen,我认为这是一个错误。它不会使wsdl和jaxb生成的类兼容。在jaxb生成的类中,元素不是默认形式限定的,它将参数元素放入空命名空间。但是在WSDL中, IS 默认表单是合格的,其中存在问题。可能有很多方法可以解决这个问题,我发现最快速和最脏的方法是在@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;