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