I am new with JAXB (and with Stackoverflow too!) and I ran into problems when trying to marshal and unmarshal an object which contains a list of enums implementing an interface. I had a look here and I tried a similar example:
public class testXML {
private static interface Animal {
public String getName();
}
@XmlRootElement
private static class Lion implements Animal {
@XmlElement
private String name;
public Lion() { name = "Lion"; }
@Override public String getName() {
return name;
}
}
@XmlRootElement
private static class Dog implements Animal {
@XmlElement
private String name;
public Dog() { name = "Dog"; }
@Override public String getName() {
return name;
}
}
@XmlRootElement
private static class Zoo {
@XmlElementRefs({
@XmlElementRef(name = "lion", type = Lion.class, required = true),
@XmlElementRef(name = "dog", type = Dog.class, required = true)
})
public List<Animal> animals;
public Zoo(Animal ... animals) {
this.animals = Arrays.asList(animals);
}
public Zoo() {
animals = null;
}
public Animal getAnimal(int i) {
return animals.get(i);
}
}
public static void main(String[] args) throws JAXBException {
File file = new File("testXML.xml");
JAXBContext context = JAXBContext.newInstance(
Zoo.class,
Lion.class,
Dog.class);
//SerializableParameter<ChannelParamEnum> result = new SerializableParameter(ChannelParamEnum.PARAM_CH_FGAIN, 1.0);
Zoo result = new Zoo(new Lion(), new Dog());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(result, file);
Zoo unmar = (Zoo)context.createUnmarshaller().unmarshal(file);
Animal anim = unmar.getAnimal(0);
System.out.println(anim);
}
}
This worked without problems. I then tried to switch Lion and Dog classes into enums and tried the following:
public class testXML {
private static interface Animal {
public String getName();
}
@XmlRootElement
private static enum Lion implements Animal {
SIMBA("Simba"),
MUFASA("Mufasa"),
SCAR("Scar");
private String name;
Lion(String name) { this.name = name; }
@Override public String getName() {
return name;
}
}
@XmlRootElement
private static enum Dog implements Animal {
PONGO("Pongo"),
PEGGY("Peggy");
private String name;
Dog(String name) { this.name = name; }
@Override public String getName() {
return name;
}
}
@XmlRootElement
private static class Zoo {
@XmlElementRefs({
@XmlElementRef(name = "lion", type = Lion.class),
@XmlElementRef(name = "dog", type = Dog.class)
})
public List<Animal> animals;
public Zoo(Animal ... animals) {
this.animals = Arrays.asList(animals);
}
public Zoo() {
animals = null;
}
public Animal getAnimal(int i) {
return animals.get(i);
}
}
public static void main(String[] args) throws JAXBException {
File file = new File("testXML.xml");
JAXBContext context = JAXBContext.newInstance(
Lion.class,
Dog.class,
Zoo.class);
Zoo result = new Zoo(Lion.SIMBA, Lion.SCAR, Dog.PONGO);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(result, file);
Zoo unmar = (Zoo)context.createUnmarshaller().unmarshal(file);
Animal anim = unmar.getAnimal(0);
System.out.println(anim);
}
}
This code fails at runtime in JAXBContext.newInstance with
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Invalid @XmlElementRef : Type "package.testXML$Lion" or any of its subclasses are not known to this context.
Obviously this is not my use-case, and I have to use enums instead of classes. I looked around a lot, but I didn't find an answer, so any help is greatly appreciated.
Thank you!
Finally I found the solution. It was enough to change
@XmlElementRefs({
@XmlElementRef(name = "lion", type = Lion.class),
@XmlElementRef(name = "dog", type = Dog.class)
})
with
@XmlElements({
@XmlElement(name="lion", type=Lion.class),
@XmlElement(name="dog", type=Dog.class)
})
Anyway, I still feel that I'm missing a lot as regards JAXB utilization.
I hope this help!