Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB use String as it is

Tags:

jaxb

jaxb2

I use REST and i was wondering if i can tell jaxb to insert a string field "as-it-is" into the outgoing xml. Certainly i count unpack it before returning, but i would like to save this step.

@XmlRootElement(name="unnestedResponse")
public class Response{
 @Insert annotation here ;-)
 private String alreadyXml;
 private int otherDate; ...
}

Is there a possability to tell JAXB to just use the String as it is without escapting? I want that the client does not have to parse my response and then parse this field.

greetings, m

like image 846
mkuff Avatar asked Oct 29 '12 12:10

mkuff


People also ask

Is JAXB deprecated?

JAXB is one of the APIs in the Java EE platform (formerly Java EE), part of the Java Web Services Development Pack (JWSDP), and one of the foundations for WSIT. It was also part of the Java SE platform (in version Java SE 6-10). As of Java SE 11, JAXB was removed. For details, see JEP 320.

When should JAXB be used?

JAXB stands for Java Architecture for XML Binding. It provides mechanism to marshal (write) java objects into XML and unmarshal (read) XML into object. Simply, you can say it is used to convert java object into xml and vice-versa.


2 Answers

You can use the @XmlAnyElement and specify a DomHandler to keep a portion of the XML document as a String.

Customer

import javax.xml.bind.annotation.*;

@XmlRootElement
public class Customer {

    private String bio;

    @XmlAnyElement(BioHandler.class)
    public String getBio() {
        return bio;
    }

    public void setBio(String bio) {
        this.bio = bio;
    }

}

BioHandler

import java.io.*;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.stream.*;

public class BioHandler implements DomHandler<String, StreamResult> {

    private static final String BIO_START_TAG = "<bio>";
    private static final String BIO_END_TAG = "</bio>";

    private StringWriter xmlWriter = new StringWriter();

    public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
        return new StreamResult(xmlWriter);
    }

    public String getElement(StreamResult rt) {
        String xml = rt.getWriter().toString();
        int beginIndex = xml.indexOf(BIO_START_TAG) + BIO_START_TAG.length();
        int endIndex = xml.indexOf(BIO_END_TAG);
        return xml.substring(beginIndex, endIndex);
    }

    public Source marshal(String n, ValidationEventHandler errorHandler) {
        try {
            String xml = BIO_START_TAG + n.trim() + BIO_END_TAG;
            StringReader xmlReader = new StringReader(xml);
            return new StreamSource(xmlReader);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

}

For More Information

  • http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html
like image 163
bdoughan Avatar answered Sep 20 '22 18:09

bdoughan


Following bdoughan's answer did not work for me as I encountered errors during marshalling when the text contained the '& character (e.g. in URLs or when using HTML entities such as e.g. " ").

I was able to resolve this by changing the custom DomHandler's marshal method to

public Source marshal(String et, ValidationEventHandler veh) {
    Node node = new SimpleTextNode(et);
    return new DOMSource(node);
}

where SimpleTextNode implements the Node interface as follows:

class SimpleTextNode implements Node {
    
    String nodeValue = "";
    
    @Override    
    public SimpleTextNode(String nodeValue) {
        this.nodeValue = nodeValue;
    }
    
    @Override
    public short getNodeType() {
        return TEXT_NODE;
    }

    // the remaining methods of the Node interface are not needed during marshalling
    // you can just use the code template of your IDE...

    ...
}

PS: I would have loved to leave this as a comment to bdoughan's answer, but unfortunately I have way too little reputation :-(

like image 28
Jay Avatar answered Sep 21 '22 18:09

Jay