Using an adapter to marshal a class to a root element with MOXy or any other JAXB implementation

jaxb2, moxy

Solution

EclipseLink MOXy and other JAXB (JSR-222) providers do not apply an `XmlAdapter` to the root object being marshalled. You can explicitly call the adapter logic before doing a marshal or after doing an unmarshal.

Problem

I have a class which extends the CompositeConfiguration class from Apache Commons Configuration. I am trying to marshal it to XML using MOXy. I have created an XML adapter that converts the configuration to a list of simple name/value objects. I have tried using a number of variations on what I have below but am still stymied. I can see my adapter class being loaded and instantiated when I create the JAXB context but it is never called when I marshal the configuration object. Looking at the MOXy source code, I am beginning to suspect that it is impossible to specify an XML adapter for a Java class that is also a root element. Am I on the right track to getting this working or is there a completely different way to do this? XML adapter: ``` public class JAXBConfigurationAdapter extends XmlAdapter<Object, BetterBaseConfiguration> { @Override public Object marshal(final BetterBaseConfiguration javaObject) throws Exception { List<ConfigurationPropertyXmlType> jaxbConfiguration = new ArrayList<>(); Iterator<String> keys = javaObject.getKeys(); while (keys.hasNext()) { String key = keys.next(); ConfigurationPropertyXmlType property = new ConfigurationPropertyXmlType(); property.setKey(key); property.setValue(javaObject.getString(key)); jaxbConfiguration.add(property); } return jaxbConfiguration; } @Override public CompositeConfiguration unmarshal(final Object jaxbObject) throws Exception { BetterBaseConfiguration configuration = new BetterBaseConfiguration(); for (ConfigurationPropertyXmlType property : (List<ConfigurationPropertyXmlType>) jaxbObject) { configuration.setProperty(property.getKey(), property.getValue()); } return configuration; } } ``` Name/value class: ``` public class ConfigurationPropertyXmlType { private String key; private String value; public String getKey() { return key; } public String getValue() { return value; } public void setKey(final String key) { this.key = key; } public void setValue(final String value) { this.value = value; } } ``` EclipseLink mapping file: ``` <?xml version="1.0" encoding="UTF-8"?> <xml-bindings version="2.5" xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.eclipse.org/eclipselink/xsds/persistence/oxm http://www.eclipse.org/eclipselink/xsds/eclipselink_oxm_2_5.xsd" package-name="myapp.configuration"> <xml-schema element-form-default="QUALIFIED"> <xml-ns prefix="mynm" namespace-uri="http://mynamespace" /> </xml-schema> <java-types> <java-type name="myapp.configuration.BetterBaseConfiguration" > <xml-java-type-adapter value="myapp.configuration.JAXBConfigurationAdapter" type="myapp.configuration.BetterBaseConfiguration" /> <xml-root-element name="Configuration" /> </java-type> </java-types> </xml-bindings> ``` Desired output: ``` <?xml version="1.0" encoding="UTF-8"?> <configuration> <property> <name>some name</name> <value>some value</value> </property> </configuration> ```

Original source