Marshaling object with StringBuffer attributes
When marshaling an object via JAXB with a StringBuffer attribute, that attribute becomes blank. I wrote a small program to demonstrate the problem:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class JaxbTest {
private String valueOne;
private StringBuffer valueTwo;
public static void main(String[] args) throws Exception {
JaxbTest object = new JaxbTest();
object.setValueOne("12345");
object.setValueTwo(new StringBuffer("54321"));
JAXBContext context = JAXBContext.newInstance(JaxbTest.class);
Marshalle开发者_JAVA百科r marshaller = context.createMarshaller();
marshaller.marshal(object, System.out);
}
@XmlElement
public String getValueOne() {
return valueOne;
}
public void setValueOne(String valueOne) {
this.valueOne = valueOne;
}
@XmlElement
public StringBuffer getValueTwo() {
return valueTwo;
}
public void setValueTwo(StringBuffer valueTwo) {
this.valueTwo = valueTwo;
}
}
The output is as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><jaxbTest><valueOne>12345</valueOne><valueTwo/></jaxbTest>
Does anyone know why "valueTwo" is not being marshaled correctly? BTW, i am using java 1.6.0_22.
Thanks in advance!!!
I would recommend using JAXB's XmlAdapter for this use case:
- http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
It is likely that JaxB does not know how to serialize a StringBuffer. What I would do to solve this kind of issues, is to have a pair of getters/setters:
the one you currently have
one which returns a String and annotated with @XmlElement
import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement public class JaxbTest {
private String valueOne;
private StringBuffer valueTwo;
public static void main(String[] args) throws Exception {
JaxbTest object = new JaxbTest();
object.setValueOne("12345");
object.setValueTwo(new StringBuffer("54321"));
JAXBContext context = JAXBContext.newInstance(JaxbTest.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(object, System.out);
}
@XmlElement
public String getValueOne() {
return valueOne;
}
public void setValueOne(String valueOne) {
this.valueOne = valueOne;
}
public StringBuffer getValueTwo() {
return valueTwo;
}
public void setValueTwo(StringBuffer valueTwo) {
this.valueTwo = valueTwo;
}
@XmlElement
public String getValueTwoString() {
return valueTwo!=null?valueTwo.toString():null;
}
public void setValueTwoString(String valueTwo) {
this.valueTwo = new StringBuffer(valueTwo);
}
}
I am not completely sure, but I think that if you use @XmlElement(name="valueTwo") on the getValueTwoString() method, you should get exactly what you want.
When I have marshaling issues with simple types, I tend to create an extra getter (and possibly setter) to simplify it. Then I add an @XmlIgnore to the main field and set the name of the new field to that of the old one. Example below:
@XmlRootElement
public class JaxbTest {
private String valueOne;
private StringBuffer valueTwo;
public static void main(String[] args) throws Exception {
JaxbTest object = new JaxbTest();
object.setValueOne("12345");
object.setValueTwo(new StringBuffer("54321"));
JAXBContext context = JAXBContext.newInstance(JaxbTest.class);
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(object, System.out);
}
@XmlElement
public String getValueOne() {
return valueOne;
}
public void setValueOne(String valueOne) {
this.valueOne = valueOne;
}
@XmlIgnore
public StringBuffer getValueTwo() {
return valueTwo;
}
public void setValueTwo(StringBuffer valueTwo) {
this.valueTwo = valueTwo;
}
@XmlElement(name="valueTwo")
public String getValueTwoString() {
return valueTwo.toString();
}
public void setValueTwoString(String valueTwo) {
this.valueTwo = new StringBuffer(valueTwo);
}
}
Thanks for all the prompt and wonderful answers!!
I got this problem when using the servicemix-exec component in ServiceMix 4.2, which is caused by this ExecResponse class. It is using a StringBuffer for the "outputData" and "errorData" attribute.
精彩评论