jaxbcxfjax-wswsdl2javajaxb-xew-plugin

Cxf Wsdl2java null entry in list disappear


I've created a webservice client with cxf with the xew plugin for list unwrapping

The problem is that the null in the list disappear. E.g.:

I have an Request with a List<String> with Strings and a null-entry

When the request now arrives at the server it only contains the Strings not the null entry. So there are only 2 entries in the example list.

Here a example of the wsdl:

[..]
<!-- the request -->
<xsd:element name="createGroup">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element maxOccurs="1" minOccurs="1" name="in0" nillable="true" type="xsd:string"/>
            <xsd:element maxOccurs="1" minOccurs="1" name="in1" nillable="true" type="ns2:ArrayOfRole"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>
[..]
<!-- the list which will be unwrapped -->
<xsd:complexType name="ArrayOfRole">
    <xsd:sequence>
        <xsd:element maxOccurs="unbounded" minOccurs="0" name="Role" nillable="true" type="xsd:String"/>
    </xsd:sequence>
</xsd:complexType>

I'm using maven to generate the ws client

<properties>
    <cxf.version>3.0.5</cxf.version>
    <jaxbBasic.version>0.6.5</jaxbBasic.version>
</properties>
[..]
<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration>
                <sourceRoot>src/main/java</sourceRoot>
                <defaultOptions>
                    <bindingFiles>
                        <bindingFile>${basedir}/jaxbBindings.xml</bindingFile>
                        <bindingFile>${basedir}/jaxwsBindings.xml</bindingFile>
                    </bindingFiles>
                    <extraargs>
                        <!-- xew plugin for unwrapping list wrappers types NOTE: the args need to be over the others otherwise there are compilation errors -->
                        <extraarg>-xjc-Xxew</extraarg>
                        <extraarg>-xjc-Xxew:instantiate lazy</extraarg>

                        <!-- Generate toString, equals, hashcode methods -->
                        <extraarg>-xjc-Xts:style:de.company.tostring.CustomToStringStyle.DEFAULT</extraarg>
                        <extraarg>-xjc-Xequals</extraarg>
                        <extraarg>-xjc-XhashCode</extraarg>
                    </extraargs>
                </defaultOptions>
                <wsdlRoot>${ws.dirAbsolute}</wsdlRoot>
                <includes>
                    <include>*.wsdl</include>
                </includes>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf.xjcplugins</groupId>
            <artifactId>cxf-xjc-ts</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jvnet.jaxb2_commons</groupId>
            <artifactId>jaxb2-basics</artifactId>
            <version>${jaxbBasic.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.jaxb-xew-plugin</groupId>
            <artifactId>jaxb-xew-plugin-fixed</artifactId> <!-- this is a custom version with a small modification see https://github.com/dmak/jaxb-xew-plugin/issues/44 -->
            <version>1.7-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-xjc</artifactId>
            <version>2.2.11</version>
        </dependency>
    </dependencies>
</plugin>

jaxbBindings.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
    <jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>

jaxwsBindings.xml

<jaxws:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
    <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
</jaxws:bindings>

A sample request:

final CreateGroup create = new CreateGroup();
create.setIn0("newgroup");
final List<String> roles = new ArrayList<String>();
roles.add("testrole");
roles.add(null);
roles.add("testrole2");
create.setIn1(roles);
final SamplePortType proxy = ..;
proxy.createGroup(create);

Is there a way that the null entry is still be present at the serverside?


Solution

  • The problem is that the jaxb-xew-plugin generates code that misses nillable = true for the XmlElement of the List.

    Generated by the plugin:

    @XmlElementWrapper(required = true, nillable = true)
    @XmlElement(name = "Role", namespace = "http://www.stackoverflow.com/example")
    protected List<String> in1;
    

    If you try, with added nillable=true, it will work:

    @XmlElementWrapper(required = true, nillable = true)
    @XmlElement(name = "Role", namespace = "http://www.stackoverflow.com/example", nillable = true)
    protected List<String> in1;
    

    So it seems the plugin is missing the nillable attribute for wrapped values.

    I think the problem lies in this code part, where the XmlElement is "lifted" to an outer element and the nillable attribute is left out.

    Adding the following code snippet to the mentioned code part will solve your problem and generate working code:

    JExpression nillable = getAnnotationMemberExpression(xmlElementOriginalAnnotation, "nillable");
    if (nillable != null) {
        xmlElementAnnotation.param("nillable", nillable);
    }
    

    The problem discussed in this question is solved as of version 1.7 of the jaxb-xew-plugin. This issue keeps track of that case, here are the releases.