Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Altering the XML header produced by the JAXB marshaller

Tags:

java

jaxb

I am currently using the following code to marshal an object into an xml string

    JAXBContext context;

    try {
        context = JAXBContext.newInstance(heartbeat.getClass());
        StringWriter writer = new StringWriter();
        Marshaller marshaller = context.createMarshaller();

        heartbeat.setHeader(header);
        heartbeat.setHeartbeatEvent(event);

        marshaller.marshal(heartbeat, writer);
        String stringXML = writer.toString();
        return stringXML;

    } catch (JAXBException e) {
        throw new RuntimeException("Problems generating XML in specified "
                + "encoding, underlying problem is " + e.getMessage(),
                e);
    }

Which produces the following header

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

My desired output is the following

<?xml version=\"1.0\"?>

By adding this to the marshaller

marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE);
marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml version=\"1.0\"?>");

I receive

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><?xml version="1.0"?>

and changing the JAXB_FRAGMENT property to TRUE removes the header entirely. I have been following the JAXB - Remove 'standalone="yes"' from generated XML thread attempting to solve the problem but I have had no luck so far. Can someone please give me some insight on how to get my desired header from the JAXB marshaller?

like image 646
JME Avatar asked Aug 26 '13 19:08

JME


People also ask

What is JAXB Marshaller?

JAXB provides a fast and convenient way to marshal (write) Java objects into XML and unmarshal (read) XML into objects. It supports a binding framework that maps XML elements and attributes to Java fields and properties using Java annotations.

Is JAXB Marshaller thread safe?

All other objects, including Marshaller and Unmarshaller, are not thread-safe and must not be shared. The static helper methods in the JAXB class can be used from several threads, of course.

How do you ignore a field in XML response?

Ignore XML Attribute. You can specify ignore="true" or ignore="false". The default value is false. Specifying ignore="false" has no effect on the attribute value assigned when an object of the type specified in the rule is created and no effect on the constraints.


2 Answers

In JAXB 3.0.1 the above mentioned constants cause a PropertyException:

 jakarta.xml.bind.PropertyException: name: com.sun.xml.bind.xmlDeclaration value: false

In this case, the XML preamble can be configured with these marshaller constants:

marshaller.setProperty("org.glassfish.jaxb.xmlHeaders", "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
  • https://eclipse-ee4j.github.io/jaxb-ri/3.0.0/docs/ch05.html
like image 135
plejaden Avatar answered Nov 15 '22 15:11

plejaden


When marshalling to an OutputStream using a combination of the following produces the expected output.

    marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml version=\"1.0\"?>");
    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

The problem you are seeing occurs when you marshal to a Writer, which appears to be a bug in the JAXB reference implementation. You can raise an issue at the link below:

  • https://java.net/jira/browse/JAXB/

You could always do:

JAXBContext context;

try {
    context = JAXBContext.newInstance(heartbeat.getClass());
    StringWriter writer = new StringWriter();
    writer.append("<?xml version=\"1.0\"?>");
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

    heartbeat.setHeader(header);
    heartbeat.setHeartbeatEvent(event);

    marshaller.marshal(heartbeat, writer);
    String stringXML = writer.toString();
    return stringXML;

} catch (JAXBException e) {
    throw new RuntimeException("Problems generating XML in specified "
            + "encoding, underlying problem is " + e.getMessage(),
            e);
}

EclipseLink JAXB (MOXy) also supports the com.sun.xml.bind.xmlHeaders and it works correctly when marshalling to a Writer (I'm the MOXy lead)

  • http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
like image 24
bdoughan Avatar answered Nov 15 '22 15:11

bdoughan