JAXB fails to marshal null value when using XMLAdapter



I use Guava Optional fields in my source code and I wanted to marshal an object that uses Optional to xml, so I used JAXB for that.


I created a XMLAdapter for the same:



public abstract class OptionalAdpater<T> extends XmlAdapter<T, Optional<T>> {

@Override
public Optional<T> unmarshal(T v) throws Exception {
return Optional.of(v);
}

@Override
public T marshal(Optional<T> v) throws Exception {
if (v == null) {
return null;
}

return v.isPresent() ? v.get() : null;
}
}


But when I use this in my class



@XmlRootElement(name = "test")
public class Test {

private Optional<Integer> optionalValue = Optional.absent();

@XmlElement(name = "optional-value", type = Integer.class)
@XmlJavaTypeAdapter(type = Integer.class, value = OptionalIntegerAdapter.class)
public Optional<Integer> getOptionalValue() {
return optionalValue;
}

public void setOptionalValue(Optional<Integer> optionalValue) {
this.optionalValue = optionalValue;
}
}


JAXB fails with a NullPointerException. What I don't get is, if I don't use an optional type and just use boxed Integer and the value is null then JAXB skips marshalling that field, but doesn't work when I use an adapter with optional type.


Trace:



Exception in thread "main" java.lang.NullPointerException
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$17.print(RuntimeBuiltinLeafInfoImpl.java:717)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$17.print(RuntimeBuiltinLeafInfoImpl.java:711)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$StringImpl.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:149)
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:241)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:114)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:341)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:582)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:323)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:103)

No comments:

Post a Comment