Reputation: 2906
I am working on a Scala project, and we want to use XML to initialize our objects with JAXB (not Spring). I have a hierarchy where more data members get added in the subclasses. A simple example would look something like this:
class Animal
{
string name
}
class Cat extends Animal
{
int numLives
}
class Dog extends Animal
{
bool hasSpots
}
I would like to be able to initialize a list of animals from an XML block that looks something like this:
<Animals>
<Cat>
<name>Garfield</name>
<numLives>9</numLives>
</Cat>
<Dog>
<name>Odie</name>
<hasSpots>false</hasSpots>
</Dog>
</Animals>
How would we setup the annotations in the classes to be able to handle this?
Upvotes: 6
Views: 1820
Reputation: 149037
For this example you will want to make use of the @XmlElementRef
and @XmlRootElement
annotations. This corresponds to the XML schema concept of substitution groups. This will allow you to have a list of objects from an inheritance hierarchy differentiated by element.
Animals
This will serve as the root object for the domain model. It has a List
property annotated with @XmlElementRef
. This means it will match values based on the value of their @XmlRootElement
annotations.
package forum8356849;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Animals")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Cat.class, Dog.class})
public class Animals {
@XmlElementRef
private List<Animal> animals;
}
Animal
package forum8356849;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
class Animal
{
String name;
}
Cat
We will annotate the Cat
class with an @XmlRootElement
annotation. This is used in tandem with the @XmlElementRef
annotation on Animals
.
package forum8356849;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Cat")
class Cat extends Animal
{
int numLives;
}
Dog
We will also add an @XmlRootElement
annotation to the Dog
class.
package forum8356849;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Dog")
class Dog extends Animal
{
boolean hasSpots;
}
Demo
You can use the following class to see that everything works as expected. input.xml
corresponds to the XML provided in your question.
package forum8356849;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Animals.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum8356849/input.xml");
Animals animals = (Animals) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(animals, System.out);
}
}
For More Inforation
Upvotes: 3
Reputation: 2534
In such cases, I prefer creating an XSD schema and generating code from it, so you are on safe side. But to answer your question, yes, you can. The annotations are XMLElement, XMLAttribute, XMLRootElement.
Upvotes: 0