我正在服务器端使用 JAX-WS 完成 Web 服务的工作。在许多域对象中,我使用 @XmlRootElement
来帮助促进使用 JAXB 将 XML 文件解码到服务中。一切都很顺利,输出正是我期望使用 SoapUI 看到的结果。
但是,当我使用 wsimport 创建客户端(作为其他开发人员的便利 DAO)时,我开始在客户端集成测试类中遇到 NullPointerExceptions。
对 Web 服务的调用工作正常,并且客户端收到了响应,但我的更复杂的对象为空。简单的属性(例如字符串)返回了完整的可用数据,但没有返回较大的对象。
通过使用简单字符串重新创建服务并迁移到更复杂的对象的迭代,我发现当客户端收到在服务器上使用 @XmlRootElement
声明的对象时,这些对象为 null 。如果服务器对象没有 @XmlRootElement
注释,客户端就会收到所有复杂的数据。
最初,缺少 @XmlRootElement
让我无法在服务器上解码数据,但是 this answer帮我解决了。
因此,由于 @XmlRootElement
注释(在服务器上!),wsimport 客户端在解码 Web 服务响应时默默失败的现象引起了我的担忧。在这种情况下,我控制了双方,并且可以采取一些措施。但是,如果我无法控制服务器怎么办?我如何仅使用 wsimport 生成的代码来解决这个问题?
最佳答案
找到答案或原因,所以我想分享。
@XmlRootElement
注释对于普通 JAXB
很有用绑定(bind),但是当对象(以及生成的 XML)打包为 SOAP
时响应,它们可能与 WSDL
不完全匹配数据的表示取决于其他注释的值。
与 @XmlRootElement
服务器上由 @WebMethod
返回的类上的注释方法,WSDL
将包含一个元素定义,例如:
<xs:element name="foo" type="tns:FooType"/>
然后在其他地方你的 WSDL
将包含对序列中元素的引用,例如:
<xs:seqeunce>
<xs:element maxOccurs="unbounded" minOccurs="0" ref="tns:foo"/>
</xs:sequence>
此引用是由 @XmlRootElement
引起的与 SOAP 响应的实际 XML 相比,注释可能会混淆根元素声明的意图。
相比之下,WSDL
生成时没有 @XmlRootElement
服务器对象上的注释不包含 <xs:element name="foo"/>
根本没有声明。相反,它的元素被描述为:
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="foo" type="tns:FooType"/>
</xs:sequence>
这可能更符合 SOAP 响应 XML 的表示方式以及将 XML 解码到 wsimport
生成的类中的方式。工作得很好。
如何使用@XmlRootElement
在 JAX-WS
服务?
wsimport
似乎在处理服务返回的 XML 有效性方面存在某种程度的惰性。吸取的教训是要勤奋地使用name
和targetNamespace
在您的@WebResult
上描述您的 Web 服务方法的注释。 @XmlRootElement
注释需要匹配 name
targetNamespace
内。当它们全部匹配时,解码就会按预期发生。当这些值不匹配时,您的 stub 类将生成并由 wsimport
注释。将无法正确使用 XML。
关于java - 为什么 wsimport 在处理具有 @XmlRootElement 注释的服务器对象时遇到问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14149121/