为什么由wsimport生成的类需要JAXBElement<ClassName>参数?

5
我有一个来自Axis2 Web服务的WSDL文件。当我使用wsimport生成客户端存根时,由于需要JAXBElement参数,生成的类会出现这种情况。为什么会这样?
以下是一个生成类中的示例方法:
JAXBElement<DataBean> value;

public void setValue(JAXBElement<DataBean> value)
{
    this.value = ((JAXBElement<DataBean>) value);
}

我期望它看起来像这样(不包含JAXBElement):
DataBean value;

public void setValue(DataBean value)
{
    this.value= (DataBean) value;
}

我在网上看到的教程没有将类设置为JAXBElement。可能的问题是什么?请注意,服务器是一个Axis2 Web服务,并且WSDL文件是由Axis2自动生成的。假设我无法控制服务器。
我该如何使wsimport不将参数转换为JAXBElements?
以下是来自WSDL文件的摘录:(我忽略了一些标记,只包含必要的标记)
<xs:element name="getData">
    <xs:complexType>
        <xs:sequence>
            <xs:element minOccurs="0" name="getData" nillable="true" type="ax220:getData"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:complexType name="getData">
    <xs:sequence>
        <xs:element minOccurs="0" name="value" nillable="true" type="ax219:DataBean"/>
    </xs:sequence>
</xs:complexType>

<wsdl:message name="getDataRequest">
    <wsdl:part name="parameters" element="ns:getData"/>
</wsdl:message>

<wsdl:message name="getDataResponse">
    <wsdl:part name="parameters" element="ns:getDataResponse"/>
</wsdl:message>

<wsdl:operation name="getData">
    <wsdl:input message="ns:getDataRequest" wsaw:Action="urn:getData"/>
    <wsdl:output message="ns:getDataResponse" wsaw:Action="urn:getDataResponse"/>
</wsdl:operation>

<wsdl:operation name="getData">
    <soap:operation soapAction="urn:getData" style="document"/>
    <wsdl:input>
        <soap:body use="literal"/>
    </wsdl:input>
    <wsdl:output>
        <soap:body use="literal"/>
    </wsdl:output>
</wsdl:operation>

<wsdl:operation name="getData">
    <soap12:operation soapAction="urn:getData" style="document"/>
    <wsdl:input>
        <soap12:body use="literal"/>
    </wsdl:input>
    <wsdl:output>
        <soap12:body use="literal"/>
    </wsdl:output>
</wsdl:operation>

<wsdl:operation name="getData">
    <http:operation location="getData"/>
    <wsdl:input>
        <mime:content type="text/xml" part="parameters"/>
    </wsdl:input>
    <wsdl:output>
        <mime:content type="text/xml" part="parameters"/>
    </wsdl:output>
</wsdl:operation>

你能发一下WSDL文件中定义和使用DataBean的相关部分吗?包括在消息和操作中用到的部分。 - joergl
@joergl:我修改了我的帖子,包括所请求的细节。 - Arci
2个回答

7

在这个页面上阅读:

http://www.techdevtips.com/java/java-webservice-client-how-to-remove-jaxbelement

使用一个数据绑定文件和以下代码:

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
  xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
  <jaxb:globalBindings generateElementProperty="false">
    <xjc:simple />
  </jaxb:globalBindings>
</jaxb:bindings>

您可以通过填充wsimport ant任务中的binding属性(或者如果您使用可运行文件,则为-b标志参数)来使用它。

祝好:)


2
首先:我认为这是不可能完成的。也就是说,我认为您无法告诉wsimport以不同的方式生成类。但是,我可以告诉您如何修改WSDL,以便以不同的方式生成模式,并仍然能够与服务通信。
我从WSDL中获取了类型定义,调整了complexType的名称,并添加了DataBean的类型,该类型在上面缺失。我将其粘贴到模式中,并使用xjc编译了模式,这是由wsimport用于从类型定义生成类的JAXB模式编译器。以下是模式:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/DataBean"
    xmlns:tns="http://www.example.org/DataBean" elementFormDefault="qualified"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="getData">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" name="getDataType" type="tns:getDataType" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="getDataType">
        <xs:sequence>
            <xs:element minOccurs="0" name="value" type="tns:DataBean" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="DataBean">
        <xs:simpleContent>
            <xs:extension base="xs:int" />
        </xs:simpleContent>
    </xs:complexType>
</schema>

您不需要为编译器设置任何特殊选项,只需执行xjc并将其指向模式文件,然后它将编译源文件。

生成的类不使用JAXBElement作为方法参数。也就是说,它们看起来像这样:

protected DataBean value;

public DataBean getValue() {
    return value;
}

为什么会这样呢?我从元素定义中删除了nillable="true"属性,这解决了问题。 nillable="true"表示在此处允许显式空值。
<DataBean></DataBean> 

如果您删除此属性,如果服务实际上在那里写入null值,您的代码将遇到问题。但是,在生成WSDL之后,可能Axis2认为nillable应该在那里,尽管实现从未实际使用它。如果您很幸运,它不会使用它,并且一切都将正常工作,尽管您修改了WSDL。
希望这可以帮助您!如果不能,那么至少我今天学到了一些东西;-)

嗨!谢谢!我会试一下。 :) 希望它能正常工作。我会让你知道的。所以基本上,你是说Axis2不符合JAXWS标准,因此,wsimport无法生成由Axis2生成的WSDL,除非手动修改WSDL?我理解得对吗? - Arci
不是的。Axis2基本上符合JAX-WS标准,至少大部分是这样的。我没有进行详细测试,但我确信它实现了大部分部分并未实现一些部分;-)问题在于JAXB模式生成的某些边缘情况。应该在根源处进行修复(通过更改注释以不生成nillable=true的Web服务)。由于您无法执行此操作,因此本地解决方法是您可以获得的最佳解决方法。 - joergl
谢谢澄清!我曾经在某个地方读到过Axis2不是JAX-WS,所以当我得知我要连接的服务是JAX-WS时,我就远离它了。此外,在为Axis2生成客户端存根时,JAXB没有包含在数据绑定选项列表中。(我正在使用Eclipse。)数据绑定选项列表仅包括ADB、XMLBeans、JIBX和None。我应该选择哪个选项来使用JAXWS绑定? - Arci
1
这些都不是;-) Axis2也支持JAXB,但在其官方文档中未列出:http://axis.apache.org/axis2/java/core/tools/CodegenToolReference.html 那很差...好吧,这里有一篇文章,介绍如何在Axis2中使用JAXB http://www.ibm.com/developerworks/java/library/j-jws8/index.html 简短的答案是你应该使用:-d jaxbri - joergl
谢谢!:D 或许,我应该停止懒惰地使用客户端存根生成器(你好,IDE)。我会查看你的链接。 - Arci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接