Imperative
Imperative

Reputation: 3183

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?

Upvotes: 1

Views: 1449

Answers (2)

Jan Tomášek
Jan Tomášek

Reputation: 175

In my case, the solution was to add @XmlValueExtension (in addition to @XmlValue) as suggested here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=461990

Upvotes: 0

Imperative
Imperative

Reputation: 3183

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.

Upvotes: 4

Related Questions