@XmlRegistry - how does it work?
@XmlRegistry used to indicate a class with @XmlElementDecl annotations. In order for your JAXB implementation process to use this class, you need to make sure that it is included in the list of classes used to load the JAXBContext . It is not enough to be the static inner class of one of the classes in your domain model:
JAXBContext context = JAXBContext.newInstance(Employee.class, Employee.XMLObjectFactory.class);
@XmlElementDecl - how does it work?
If the field / property value is JAXBElement , you need to use @XmlElementDecl . A JAXBElement captures information that may be useful:
- The name of the element, this is necessary if you map the selection structure, where several elements of the same type. If the element name does not match the unique type, you cannot round the document.
JAXBElement can be used to represent an element with xsi:nil="true" .
XmlObjectFactory
@XmlElementDecl also allows you to specify a scope. I have a little changed the model of you. I introduced the XmlObjectFactory class, which has two @XmlElementDecl . Both indicate the name address . I used the scope property so that @XmlElementDecl corresponding to the address class is used for the properties in the Employee class.
package forum11078850; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlElementDecl; import javax.xml.bind.annotation.XmlRegistry; import javax.xml.namespace.QName; @XmlRegistry public class XmlObjectFactory { @XmlElementDecl(scope = Employee.class, name = "address") JAXBElement<Address> createAddress(Address value) { return new JAXBElement<Address>(new QName("address"), Address.class, value); } @XmlElementDecl(name = "address") JAXBElement<String> createStringAddress(String value) { return new JAXBElement<String>(new QName("address"), String.class, value); } }
Employee
The @XmlElementRef will cause the property value to be mapped to the name of its root element. Possible matches will include classes mapped to @XmlRootElement or @XmlElementDecl .
package forum11078850; import java.util.List; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.*; @XmlRootElement @XmlType(propOrder = { "id", "name", "email", "addresses" }) public class Employee { private int id; private String name; private String email; private List<JAXBElement<Address>> addresses; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElementWrapper @XmlElementRef(name="address") public List<JAXBElement<Address>> getAddresses() { return addresses; } public void setAddresses(List<JAXBElement<Address>> addresses) { this.addresses = addresses; } }
ObjectFactoryTest
package forum11078850; import java.io.FileReader; import javax.xml.bind.*; public class ObjectFactoryTest { public static void main(String[] args) throws Exception { FileReader reader = new FileReader("src/forum11078850/input.xml"); JAXBContext context = JAXBContext.newInstance(Employee.class, XmlObjectFactory.class); Unmarshaller unmarshaller = context.createUnmarshaller(); Object obj = unmarshaller.unmarshal(reader); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(obj, System.out); } }
The address and input.xml from my original answer can be used to run this example.
ORIGINAL RESPONSE
I'm not sure how you are trying to use @XmlRegistry , so I will focus on the following part of your post:
When I format the xml employee using the above code, the address list is not populated. The resulting employee object has only a blank address list. Is there something wrong with my comparisons?
Your list of address objects is wrapped in an address element, so you need to use the @XmlElementWrapper annotation to match this use case. The following is a complete example:
Employee
package forum11078850; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement @XmlType(propOrder = { "id", "name", "email", "addresses" }) public class Employee { private int id; private String name; private String email; private List<Address> addresses; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElementWrapper @XmlElement(name = "address") public List<Address> getAddresses() { return addresses; } public void setAddresses(List<Address> addresses) { this.addresses = addresses; } }
Address
package forum11078850; public class Address { private String addressLine1; private String addressLine2; private String addressLine3; public String getAddressLine1() { return addressLine1; } public void setAddressLine1(String addressLine1) { this.addressLine1 = addressLine1; } public String getAddressLine2() { return addressLine2; } public void setAddressLine2(String addressLine2) { this.addressLine2 = addressLine2; } public String getAddressLine3() { return addressLine3; } public void setAddressLine3(String addressLine3) { this.addressLine3 = addressLine3; } }
ObjectFactoryTest
package forum11078850; import java.io.FileReader; import javax.xml.bind.*; public class ObjectFactoryTest { public static void main(String[] args) throws Exception { FileReader reader = new FileReader("src/forum11078850/input.xml"); JAXBContext context = JAXBContext.newInstance(Employee.class); Unmarshaller unmarshaller = context.createUnmarshaller(); Object obj = unmarshaller.unmarshal(reader); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(obj, System.out); } }
Input.xml / output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <employee> <id>1</id> <name>Vaishali</name> <email> Vaishali@example.com </email> <addresses> <address> <addressLine1>300</addressLine1> <addressLine2>Mumbai</addressLine2> <addressLine3>India</addressLine3> </address> <address> <addressLine1>301</addressLine1> <addressLine2>Pune</addressLine2> <addressLine3>India</addressLine3> </address> </addresses> </employee>