简体   繁体   中英

Why classes generated by wsimport requires JAXBElement<ClassName> parameters?

I have a WSDL file which is from an Axis2 Web Service. When I generate a client stub using wsimport given the WSDL file, the resulting classes require JAXBElement paramaters. Why is it like that?

Sample Method from one of the Generated Classes:

JAXBElement<DataBean> value;

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

I am expecting it to look like this (without the JAXBElement):

DataBean value;

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

The tutorials I saw on the net does not set the classes to JAXBElement. What could be the problem? Please take note that the server is an Axis2 web service and the WSDL file is auto-generated by Axis2. The assumption is I have no control over the server.

How can I make it in such a way that wsimport won't convert the parameters to JAXBElements?

Below is an excerpt from the WSDL file: (I ignored some of the tags to include only the essential tags)

<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>

As read on this page :

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

use a data binding file with this code :

<?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>

and use it in your wsimport ant task by filling the binding attribute (or -b flag argument if you use the runnable)

Cheers :)

To begin with: I don't think this can be done. That is, I don't think you can tell wsimport to generate the classes differently. However, I can tell you how to modify the WSDL in a way that generates the schema differently and that could still enable you to talk to the service.

I took the type definitions from the WSDL, adjusted the name of the complexType and added the a type for DataBean that was missing above. I pasted that to a schema and compiled the schema with xjc, the JAXB schema compiler, which is used by wsimport to generate classes from the type defintions. Here is the schema:

<?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>

You don't need any special options for the compiler, simply execute xjc and point it to the schema file, then it will compile the source files.

The generated classes do not use JAXBElement as method parameters. That is they look like that:

protected DataBean value;

public DataBean getValue() {
    return value;
}

Why is this? I removed the nillable="true" attributes from the element defintions and this did the trick. nillable="true" states that explicit null values are legal here:

<DataBean></DataBean> 

If you remove this attribute, your code will run into problems if the service actually writes null values in there. But after all the WSDL is generated and maybe Axis2 just thinks the nillable should be in there for some reason, although the implementation never actually uses it. If you are lucky, it does not and everything will work fine, although you modified the WSDL.

I hope this helps! If not, then at least I have learned something today ;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM