2

我正在使用服务器端的 JAX-WS 完成 Web 服务的工作。在许多领域对象中,我@XmlRootElement使用 JAXB 帮助促进将 XML 文件解组到服务中。一切顺利,输出是我使用 SoapUI 所期望看到的。

但是,当我使用 wsimport 创建客户端(作为其他开发人员的便利 DAO)时,我开始在客户端集成测试类中遇到 NullPointerExceptions。

对 web 服务的调用正常工作,客户端收到了响应,但我的更复杂的对象为空。简单的属性,如字符串,返回的都是可用数据,但不是较大的对象。

通过使用简单字符串重新创建服务并迁移到更复杂的对象的迭代,我发现当客户端收到在服务器上声明的对象时@XmlRootElement,这些对象是空的。如果服务器对象没有@XmlRootElement注释,则客户端会收到所有复杂荣耀中的所有数据。

最初,缺乏@XmlRootElement让我适合解组服务器上的数据,但这个答案帮助了我。

@XmlRootElement因此,wsimport 客户端由于注释(在服务器上!)而在 Web 服务响应的解组时静默失败的现象让我感到担忧。在这种情况下,我可以控制双方并且可以做点什么。但是,如果我无法控制服务器怎么办?仅使用 wsimport 生成的代码我将如何解决这个问题?

4

1 回答 1

2

Found the answer, or the reason, so thought I would share.

The @XmlRootElement annotation is useful for plain JAXB bindings, but when the objects (and the resulting XML) are packaged as a SOAP response it is possible that they don't exactly match the WSDL's representation of the data depending on the value of other annotations.

With the @XmlRootElement annotation on the class on the server which is being returned by a @WebMethod method, the WSDL will include an element definition such as:

<xs:element name="foo" type="tns:FooType"/>

then elsewhere your WSDL will include a reference to the element in a sequence such as:

<xs:seqeunce>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:foo"/>
</xs:sequence>

This referencing is caused by the @XmlRootElement annotation may confuse the intent of the root element declaration compared to the actual XML of the SOAP response.

In contrast, the WSDL generated without the @XmlRootElement annotation on the server objects does not contain a <xs:element name="foo"/> declaration at all. Rather its element is described as:

<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="foo" type="tns:FooType"/>
</xs:sequence>

This probably better matches the way the SOAP response XML is represented and the unmarshalling of the XML into the classes generated by wsimport works just fine.

How to use @XmlRootElement in a JAX-WS service?

wsimport seems to handle some degree of laziness in the validity of the XML returned by a service. The lesson learned is to be diligent in your use of name and targetNamespace on your @WebResult annotations describing your web service method. The @XmlRootElement annotation needs to match the name within the targetNamespace. When they all match, the unmarshalling happens as expected. When those values do not match, your stubbed classes generated and annotated by wsimport will not be able to properly consume the XML.

于 2013-05-08T15:58:18.197 回答