Aar*_*n T 4 java web-services cxf java-ws jaxb2
我正在使用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>
Run Code Online (Sandbox Code Playgroud)
结果成功:
<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>
Run Code Online (Sandbox Code Playgroud)
请求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>
Run Code Online (Sandbox Code Playgroud)
导致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>
Run Code Online (Sandbox Code Playgroud)
在我所做的所有研究中,这通常意味着命名空间在某处不匹配.但是我已经彻底检查了它,并且命名空间在任何地方都是相同的,包括ObjectFactory.class,package-info.class和cxf-servlet.xml配置文件以及@WebService注释.任何人都可以指出我正确的方向,我在这里失踪了什么?
问题的根源是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) {
Run Code Online (Sandbox Code Playgroud)
这将导致以下生成的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;
Run Code Online (Sandbox Code Playgroud)
然后我更改了服务实现类,将命名空间添加到@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) {
Run Code Online (Sandbox Code Playgroud)
虽然这不会使默认表单限定,但它会将命名空间添加到生成的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;
Run Code Online (Sandbox Code Playgroud)