user907810
user907810

Reputation: 3378

JAXB Marshaller : StringWriter output has a truncated tag value

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

Answers (1)

bdoughan
bdoughan

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

Related Questions