Reputation: 3378
I want to marshall a java object to xml string. Therefore I have been given a schema from which I generate the JAXB classes. There is a set method(corresponding to an element of type hexbinary in schema) where I have to set a string. The string size is about 2566. After setting data into the object via the setter methods, I call the marshaller passing stringWriter argument.
But on printing stringWriter, I see that it is truncated. I don't see the entire 2566 characters.
What is wrong? Any ideas?
Thanx!
Update:
I think I found the problem. I have to find a suitable title as my reasoning of the problem was wrong!! The problem is the following: I have a "hexbinary" element in my schema. The generated class has a corresponding set/get method. To set the value I had used HexEncodeString method of apache commons package and realized that the marshaller shows 36383639 in the hexbinary tag for a String "hi" whose actual Hex encoding is 6869 :( Thus, the problem is the xml after marshalling has a tag value with # of chars greater than the original and not getting truncated like I thought before!
Thanks to Blaise Doughan's code. I have modified it and reproduced this problem.
First an example schema:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Root">
<xs:sequence>
<xs:element name="string" type="xs:string" minOccurs="0"/>
<xs:element name="a" type="xs:hexBinary" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
With this I generated the ObjectFactory class and Root class. I had to modify the ObjectFactory class to include JAXBElement so that I can pass this to the Marshaller. With these I took the Demo class of Blaise Doughan and modified it as:
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
// The object factory
ObjectFactory objFactory = new ObjectFactory();
Root root = new Root();
String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(val.getBytes());
System.out.println("val="+val);
System.out.println("getString ="+root.getString());
System.out.println("getArr="+new String(root.getArr()));
// Marshal the object to a StringWriter
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");
StringWriter stringWriter = new StringWriter();
marshaller.marshal(objFactory.createRoot(root),stringWriter);
// marshaller.marshal(root, stringWriter);
// Convert StringWriter to String
String xml = stringWriter.toString();
System.out.println(xml);
// Unmarshal the XML and check length of long String
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root unmarshalledRoot = (Root) unmarshaller.unmarshal(new StringReader(xml));
System.out.println(root.getString().length());
System.out.println(root.getString());
System.out.println(new String(root.getArr()).length());
System.out.println(new String(root.getArr()));
}
}
The output I get is:
val=6869
getString =hi
getArr=6869
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:Root xsi:schemaLocation="http://www.example.com/schema.xsd" xmlns:ns3="http://example.com/root" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>hi</string>
<arr>36383639</arr>
</ns3:Root>
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://example.com/root", local:"Root"). Expected elements are (none)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:631)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:236)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:231)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1038)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:467)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:448)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:626)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3103)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:922)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194)
at example.Demo.main(Demo.java:43)
Why is arr tag 36383639 and not 6869?
Upvotes: 3
Views: 26472
Reputation: 149047
NEW ANSWER
In your sample code val
is the hexBinary representation of str.getBytes()
. But the value you are setting on the arr
property is the bytes from the hex encoded String.
String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(val.getBytes());
I believe what you mean to do is the following:
String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(str.getBytes());
Which will produce the following output
val=6869
getString =hi
getArr=hi
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xsi:schemaLocation="http://www.example.com/schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>hi</string>
<a>6869</a>
</root>
Put another way
String str = new String("hi");
System.out.print("String: " + str);
System.out.println(" hexBinary: " + Hex.encodeHexString(str.getBytes()));
String val = Hex.encodeHexString(str.getBytes());
System.out.print("String: " + val);
System.out.println(" hexBinary: " + Hex.encodeHexString(val.getBytes()));
Will output:
String: hi hexBinary: 6869
String: 6869 hexBinary: 36383639
ORIGINAL ANSWER
I have not been able to reproduce the issue that you are seeing. I am using a String
size of 500000
. Below is what I have tried (does this sample work for you?). Is it possible that the truncation is due to the console you are writing the long String to?
Demo
package forum12146217;
import java.io.*;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
// Build a long String
StringBuilder stringBuilder = new StringBuilder();
for(int x=0; x<500000; x++) {
stringBuilder.append("a");
}
Root root = new Root();
root.setString(stringBuilder.toString());
System.out.println(root.getString().length());
// Marshal the object to a StringWriter
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");
StringWriter stringWriter = new StringWriter();
marshaller.marshal(root, stringWriter);
// Convert StringWriter to String
String xml = stringWriter.toString();
//System.out.println(xml);
// Unmarshal the XML and check length of long String
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root unmarshalledRoot = (Root) unmarshaller.unmarshal(new StringReader(xml));
System.out.println(unmarshalledRoot.getString().length());
}
}
Root
package forum12146217;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Root {
private String string;
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
Output
500000
500000
Upvotes: 1