Generally when we do marshaling from JAVA object to XML through JAXB, the null values String or other objects not considered while marshalling and xml tag for these objects not generated.
If we need to get xml tags also for null values object then define these property in model class with attribute nillable=true.
@XmlElement(name = "description", nillable = true)
private String description;
After adding nillable=true property attribute this will generate output XML tag as below
<description xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
Problem Statement
Here problem is we don’t want the XML description tag with schema url and xsi:nil=”true” as above. We want only the empty tag for XML as below
<description />
Solutions
Here the problem is when any value in model class property is found as null the JAXB does not call any xmlAdaptor and generate tag with schema link with xsi:nil=”true”.
To solve this problem we can use third party JAXB provider EclipseLink JAXB (MOXy) . It’s required to make below changes on your application and model class.
- Add this EclipseLink MOXy dependency in you application
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.6.8</version>
</dependency>
- Add XmlNullPolicy on all the fields of model where need to generate empty tag for null values.
@XmlElement(name = "description", nillable = true)
@XmlNullPolicy(emptyNodeRepresentsNull = true, nullRepresentationForXml = XmlMarshalNullRepresentation.EMPTY_NODE)
private String description;
- Now we need to set below property in our JVM while marshaling through java object to XML.
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
There are following ways to add above property based on you application need.
Solution 1: In case of simple java application, you can add this line of code before marshaling
System.setProperty("javax.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
Solution 2: Create jaxb.properties file in your each model package/resource folder and add below property
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Note: Once you will run your code in your local machine it will generate empty tag but you will face problem when deploy application after making maven build because this property file will not add in your generated classes folder model packages. In this case you have to add below lines of code in pom.xml to copy jaxb.properties file in model package.
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources01</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/model package location</outputDirectory>
<encoding>UTF-8</encoding>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>jaxb.properties</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Solution 3: If your application is Spring boot then you can also pass the below arguments while deploying application.
-Djavax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
or
Add the property in application.properties/application.yml file
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
This solution will also help when you are having multiple packages for model classes and no need to include jaxb.properties in each package.
Conclusion
In this topic you learn about the steps to generate empty tags for XML incase null values for Java objects. you can also learn about the copy of jaxb.properties file in packages by maven. Incase of having multiple packages for model classes you can follow solutions to handle it.
Let me know about your thoughts on these solutions.
Happy Learning !!!