Search code examples
jaxbeclipselinkmoxy

Make use of @XmlValue in subclass


I had this code working fine with EclipseLink 2.5.2, but moving to 2.6.0 breaks the XmlValue annotation:

The property or field value cannot be annotated with XmlValue since it is a subclass of another XML-bound class.

Base class look like this:

public abstract class Baseclass {

    @XmlAttribute
    private String baseValue;

    // ...
}

One of two subclasses (composite pattern, class B can have a list of BaseClass elements):

@XmlRootElement(name = "A")
public class A extends BaseClass {

    @XmlValue
    private String aValue;

}

And the usage:

public class Root {

    @XmlElements({
            @XmlElement(class = A.class),
            @XmlElement(class = B.class)
    })
    private BaseClass object;

}

Unfortunately the class layout can't be changed, because it's JPA persisted to a database. I tried to wrap the A and B classes with an XmlJavaTypeAdapter without success.
Is it possible to use the annotation in the way as before with EL 2.6 or through an adapter class?


Solution

  • I managed to solve the issue using a XmlAdapter.

    In the subclass replace the XmlValue annotation:

    @XmlPath(".")
    @XmlJavaTypeAdapter(AClassAdapter.class)
    private String aValue;
    

    And the adapter implementation:

    public class AClassAdapter extends XmlAdapter<AdaptedValue, String> {
    
        public static class AdaptedValue {
    
            @XmlValue
            public String value;
    
            public AdaptedValue() {
            }
    
            public AdaptedValue(String value) {
                this.value = value;
            }
        }
    
        @Override
        public String unmarshal(AdaptedValue v) throws Exception {
            return v.value;
        }
    
        @Override
        public AdaptedValue marshal(String v) throws Exception {
            return new AdaptedValue(v);
        }
    }
    

    The XmlPath(".") did the trick. Without it, the marshalled XML still has the value of aValue wrapped in <aValue> nodes.