javasoapjaxbwsimportjaxws-maven-plugin

How can I get the JAXB to generate empty tags for non-string elements?


Edit: I have re-formatted the question to hopefully make my intentions clearer.

I'm trying to map the java objects to XML using JAXB marshaller to create a soap request for a vendor SOAP service. I have few elements which need to present in the request even if they are empty or null. I use jaxws-maven-plugin plugin with wsimport goal in my pom.xml to generate sources from the WSDL files.

<plugin>
<groupId>com.helger.maven</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.6</version>
<executions>
    <execution>
        <goals>
            <goal>wsimport</goal>
        </goals>
        <configuration>
            <wsdlFiles>
                <wsdlFile>${project.basedir}/src/wsdl/sample/SomeSoapService.wsdl</wsdlFile>
            </wsdlFiles>
        </configuration>
        <id>wsimport-generate-cbs</id>
        <phase>generate-sources</phase>
    </execution>
</executions>
<dependencies>
    <dependency>
        <groupId>javax.xml</groupId>
        <artifactId>webservices-api</artifactId>
        <version>2.0</version>
    </dependency>
</dependencies>
<configuration>
    <sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
    <xnocompile>true</xnocompile>
    <xadditionalHeaders>true</xadditionalHeaders>
    <verbose>true</verbose>
    <extension>true</extension>
</configuration>

I've read and understood from here [ https://stackoverflow.com/questions/11215485/jax-ws-to-remove-empty-tags-from-request-xml ] that for the elements with xs:string type, an empty tag can be generated by setting an empty string "" as it's value. But it can't be done on the elements with types such as xs:dateTime, xs:boolean, xs:integer which will produce XMLGregorianCalendar, BigInteger, Boolean objects respectively. If I set their value as null, the elements will not be generated in marshaling process. Like others have pointed out, it can be achieved by adding nillable=true to the @XmlElement but that will require changing to the generated source which will be overwritten on the next build unless I remove the plugin from maven after the first build.

My current workaround is I changed the types of those particular elements that need to present in the request to xs:string in the WSDL files and passed the empty string to their corresponding java object fields.

My question is, is it possible to make changes in the WSDL side that will trigger jaxws:wsimport to add nillable=true in the generated @XmlElement fields? The reason I prefer to change the WSDL files instead of generated sources is that

  1. I already have some changes in WSDL files so that all of the changes can be in one place, easier to document.
  2. I would like to avoid changing the generated sources so that I can keep them out of Git repo and also prevent being overwritten on each build.

Following is the simplified version of the code.

First I have this generated java class for the complexType Currency.

// Generated    
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "currency", propOrder = {
    "crossCurrency",
    "amount"
})
public class Currency {

    @XmlElement(required = true)
    protected Boolean crossCurrency;
    @XmlElement(required = true)
    protected BigDecimal amount;
}

And I set the fields as null because they don't exist.

requestInputRq.setCurrency(new Currency());
requestInputRa.setOtherField("Some value");

That will generate <typ:Currency /> but I need it to be generated like below.

<typ:Currency>
    <typ:crossCurrency/>
    <typ:amount/>
</typ:Currency>

Solution

  • use the nillable attribute with @XmlElement and set it value to true

    Currency.java

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "currency", propOrder = {
        "isoCurrencyCode",
        "amount"
    })
    public class Currency {
    
        @XmlElement(required = true, nillable=true)
        protected Boolean crossCurrency;
        @XmlElement(required = true, nillable=true)
        protected BigDecimal amount;
    }
    

    output

    <typ:Currency>
        <typ:crossCurrency xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
        <typ:amount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
    </typ:Currency>
    

    WSDL

    add the nillable attribute and set it value to true in every requested element as following example,

    <xsd:element name="Currency" nillable="true" ... />