JAXB and inheritance works when marshaling; but not unmarshaling

Viewed 1076

I want to marshal / unmarshal objects of a class that inherits form another one.

I start with the class Thing:

import java.util.List;

public class Thing {
  private List<String> strings;

  public List<String> getStrings() {
    return strings;
  }

  public void setStrings(List<String> strings) {
    this.strings = strings;
  }
}

I extend this class and annotate it with JAXB-annotations.

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class JaxbThing extends Thing {

  // @XmlElementWrapper(name = "list")
  @XmlElementWrapper(name = "strings")
  @XmlElement(name = "string")
  public List<String> getStrings() {
    return super.getStrings();
  }

  public void setStrings(List<String> string) {
    super.setStrings(string);
  }
}

Then I run the following marshalling/unmarshalling program:

import java.io.File;
import java.util.Arrays;
import javax.xml.bind.*;

public class Main {
  public static void main(String[] args) {
    JaxbThing t = new JaxbThing();
    t.setStrings(Arrays.asList("a", "b", "c"));
    try {
      File f = new File("jaxb-file.xml");

      JAXBContext context = JAXBContext.newInstance(JaxbThing.class);

      Marshaller m = context.createMarshaller();
      m.marshal(t, f);

      Unmarshaller um = context.createUnmarshaller();
      JaxbThing t2 = (JaxbThing) um.unmarshal(f);

      System.out.println(t2.getStrings());  // I expect to see [a, b, c]

    } catch (JAXBException e) {
      e.printStackTrace();
    }
  }
}

The content of the XML file is:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxbThing>
    <strings>
        <string>a</string>
        <string>b</string>
        <string>c</string>
    </strings>
</jaxbThing>

Everything seems to be correct. But the result of the unmarshaling is surprising to me, because the console shows:

[
    ]

When I expected to see [a, b, c]

If I annotate the strings property in this way:

  @XmlElementWrapper(name = "list")
  // @XmlElementWrapper(name = "strings")
  @XmlElement(name = "string")
  public List<String> getStrings() {
    return super.getStrings();
  }

Then the console shows the expected [a, b, c].

I guess that JAXB unmarshaler is using class Thing instead of JaxbThing to unmarshal the XML file content. In fact if I annotate the class Thing with @XmlTransient I get the expected result.

However I do not understand this behavior of JAXB.

Can anyone explain me it, please? Thank you in advance.

2 Answers
Related