Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB Annotations - Mapping interfaces and @XmlElementWrapper

I am having trouble with JAXB annotations for a field that is a list whose generified type is an interface. When I have it declared such as:

@XmlAnyElement
private List<Animal> animals;

Every thing works correctly. But when I add a wrapper element, such as:

@XmlElementWrapper
@XmlAnyElement
private List<Animal> animals;

I find that the Java object marshals correctly, but when I unmarshal the document created by marshaling, my list is empty. I have posted below the code to demonstrate this problem.

Am I doing something wrong, or is this a bug? I have tried it with version 2.1.12 and 2.2-ea with the same result.

I am working through the example for mapping interfaces with annotations located here: https://jaxb.dev.java.net/guide/Mapping_interfaces.html

@XmlRootElement
class Zoo {

  @XmlElementWrapper
  @XmlAnyElement(lax = true)
  private List<Animal> animals;

  public static void main(String[] args) throws Exception {
    Zoo zoo = new Zoo();
    zoo.animals = new ArrayList<Animal>();
    zoo.animals.add(new Dog());
    zoo.animals.add(new Cat());

    JAXBContext jc = JAXBContext.newInstance(Zoo.class, Dog.class, Cat.class);
    Marshaller marshaller = jc.createMarshaller();

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    marshaller.marshal(zoo, os);

    System.out.println(os.toString());

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    Zoo unmarshalledZoo = (Zoo) unmarshaller.unmarshal(new ByteArrayInputStream(os.toByteArray()));

    if (unmarshalledZoo.animals == null) {
      System.out.println("animals was null");
    } else if (unmarshalledZoo.animals.size() == 2) {
      System.out.println("it worked");
    } else {
      System.out.println("failed!");
    }
  }

  public interface Animal {}

  @XmlRootElement
  public static class Dog implements Animal {}

  @XmlRootElement
  public static class Cat implements Animal {}
} 
like image 558
codefinger Avatar asked Jul 21 '09 13:07

codefinger


1 Answers

Should use @XmlElementRefs({ @XmlElementRef(type=Dog.class), @XmlElementRef(type=Cat.class)}) private List animals;

or use @XmlAnyElement(lax = true) only, and add Dog.class, Cat.class to JaxbContext

like image 138
Golyo Avatar answered Sep 30 '22 13:09

Golyo