JAXB 2.x : Marshalling puts element value twice into the XML
-
25-10-2019 - |
Question
For some reason, all values of an element gets written twice. My test case is very simple:
package test;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class TestBean {
private String name = null;
@XmlElement(name="lastname")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Then I marshall the document to the filesystem into an XML:
TestBean object = new TestBean();
object.setName("abc ");
Class<?> clazz = object.getClass();
JAXBContext context = JAXBContext.newInstance(clazz);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
m.marshal(object, new File("test.xml"));
And the resulting XML is:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<lastname>abc abc </lastname>
</root>
For simplicity I removed the package-info.java file with the namespace definitions.
The implementation I am using is org.eclipse.persistence.moxy 2.1.2: the jaxb.properties file in the package folder contains this line:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Thanks for any hints.
Solution
This is a known MOXy issue that has been fixed in the EclipseLink 2.3.0 stream. An EclipseLink 2.3.0 download can be obtained here:
The workaround for EclipseLink 2.1.2 is to use another access type, or to annotate the corresponding field with @XmlTransient:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class TestBean {
@XmlTransient
private String name = null;
@XmlElement(name="lastname")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
OTHER TIPS
I tried your test and it gives the correct output for me:
<root>
<lastname>abc </lastname>
</root>
It could be the JAXB2 implementation (moxy in your case vs native JDK1.6 based JAXB2 for my test).