Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Note:</strong> I'm the <a href="http://www.eclipse.org/eclipselink/moxy.php" rel="noreferrer"><strong>EclipseLink JAXB (MOXy)</strong></a> lead and a member of the <a href="http://jcp.org/en/jsr/detail?id=222" rel="noreferrer"><strong>JAXB (JSR-222)</strong></a> expert group.</p> <p>This use case is mapped using the <code>@XmlAnyElement</code> annotation and specifying a <code>DOMHandler</code>. There appears to be bug when doing this with the JAXB RI, but the following use case works with EclipseLink JAXB (MOXy).</p> <p><strong>BodyDomHandler</strong></p> <p>By default a JAXB impleemntation will represent unmapped content as a DOM node. You can leverage a <code>DomHandler</code> to an alternate representation of the DOM, In this case we will represent the DOM as a <code>String</code>.</p> <pre><code>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 BodyDomHandler implements DomHandler&lt;String, StreamResult&gt; { private static final String BODY_START_TAG = "&lt;body&gt;"; private static final String BODY_END_TAG = "&lt;/body&gt;"; 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(BODY_START_TAG) + BODY_START_TAG.length(); int endIndex = xml.indexOf(BODY_END_TAG); return xml.substring(beginIndex, endIndex); } public Source marshal(String n, ValidationEventHandler errorHandler) { try { String xml = BODY_START_TAG + n.trim() + BODY_END_TAG; StringReader xmlReader = new StringReader(xml); return new StreamSource(xmlReader); } catch(Exception e) { throw new RuntimeException(e); } } } </code></pre> <p><strong>Message</strong></p> <p>Below is how you would specify the <code>@XmlAnyElement</code> annotation on your <code>Message</code> class.</p> <pre><code>import javax.xml.bind.annotation.XmlAnyElement; import javax.xml.bind.annotation.XmlType; @XmlType(propOrder = { "body" }) public class Message { private String body; public String getBody() { return body; } @XmlAnyElement(BodyDomHandler.class) public void setBody(String body) { this.body = body; } } </code></pre> <p><strong>Output</strong></p> <p>Below is the output from running your <code>SerialziationTest</code>:</p> <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;Report&gt; &lt;message&gt; &lt;body&gt;Sample report message.&lt;/body&gt; &lt;/message&gt; &lt;/Report&gt; &lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;Report&gt; &lt;message&gt; &lt;body&gt; &lt;rootTag&gt; &lt;body&gt;All systems online.&lt;/body&gt; &lt;/rootTag&gt; &lt;/body&gt; &lt;/message&gt; &lt;/Report&gt; </code></pre> <p><strong>For More Information</strong></p> <ul> <li><a href="http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html" rel="noreferrer">http://blog.bdoughan.com/2011/04/xmlanyelement-and-non-dom-properties.html</a></li> <li><a href="http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html" rel="noreferrer">http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html</a></li> </ul> <p><strong>NOTE - Bug in JAXB RI</strong></p> <p>There appears to be a bug in the JAXB reference implementation, and the example code will result in a stack trace like the following:</p> <pre><code>Exception in thread "main" javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.internal.SAXException2: unable to marshal type "java.lang.String" as an element because it is missing an @XmlRootElement annotation] at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:317) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:243) at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:75) at forum12428727.SerializationTest.main(SerializationTest.java:20) Caused by: com.sun.istack.internal.SAXException2: unable to marshal type "java.lang.String" as an element because it is missing an @XmlRootElement annotation at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:216) at com.sun.xml.internal.bind.v2.runtime.LeafBeanInfoImpl.serializeRoot(LeafBeanInfoImpl.java:126) at com.sun.xml.internal.bind.v2.runtime.property.SingleReferenceNodeProperty.serializeBody(SingleReferenceNodeProperty.java:100) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:306) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:664) at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:141) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:306) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:561) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:290) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:462) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:314) ... 3 more </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload