Java object into XML conversion using JAXB - annotation issue - java

public class RequestXml // this pojo for RequestXML
{
private Contact[] Contact;
public Contact[] getContact ()
{
return Contact;
}
#XmlElement(name="Contact")
public void setContact (Contact[] Contact)
{
this.Contact = Contact;
}
}
another pojo
public class Contact // this class is for contact
{
private String content;
private String role;
public String getContent ()
{
return content;
}
#XmlElement(name="content")
public void setContent (String content)
{
this.content = content;
}
public String getRole ()
{
return role;
}
#XmlElement(name="role")
public void setRole (String role)
{
this.role = role;
}
}
As I am getting result like below while marshalling
<Contact role="firstUser"/>
<Contact role="secondUser"/>
<Contact role="LastUser"/>
As below is the expected output:
<Contact role="firstUser">aaaa</Contact>
<Contact role="secondUser">bbbb</Contact>
<Contact role="LastUser">cccc</Contact>
Please help me on this.

For marshalling the field as content, use the #XmlValue annotation. For marshalling it as attribute, use the #XmlAttribute. This is how the Contract POJO looks like, along with my test:
#XmlRootElement
public class RequestXml {
private Contact[] contact;
#XmlElement(name = "Contact")
public Contact[] getContact() {
return contact;
}
public void setContact(Contact[] Contact) {
this.contact = Contact;
}
}
public class Contact {
private String content;
private String role;
public Contact(String content, String role) {
this.content = content;
this.role = role;
}
#XmlValue
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
#XmlAttribute
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
The test:
public class JaxbTest {
#Test
public void testObjectToXml() throws JAXBException {
RequestXml requestXml = new RequestXml();
requestXml.setContact(new Contact[]{new Contact("aaa", "bbb")});
JAXBContext jaxbContext = JAXBContext.newInstance(RequestXml.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(requestXml, System.out);
}
}
This provides the following output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<requestXml>
<Contact role="bbb">aaa</Contact>
</requestXml>
EDIT: Also, see What is the difference between using #XmlElement before field and before getter declaration? for the difference of annotating getters/setters and fields.

Related

Why am i getting null in java from xml even though value is present in xml?

Im trying to build java object for xml by
java code
JAXBContext jaxbContext = JAXBContext.newInstance(Enfinity.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Enfinity enfinity = (Enfinity) jaxbUnmarshaller.unmarshal(xmlFile);
xml
<?xml version="1.0" encoding="UTF-8"?>
<enfinity xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt" xsi:schemaLocation="http://www.intershop.com/xml/ns/intershop/customer/impex/7.3 b2b_customer.xsd http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt dt.xsd" major="6" minor="1" family="enfinity" branch="enterprise" build="1.0.299">
<customer id="34627">
<customer-type>SMB</customer-type>
<company-name>xxxxx & xxxxx</company-name>
<industry>Retail</industry>
<enabled>1</enabled>
<approval-status>1</approval-status>
<custom-attributes>
<custom-attribute name="CustomerPriceLevel" dt:dt="string">4</custom-attribute>
<custom-attribute name="FreeFreightThreshold" dt:dt="string">300.00</custom-attribute>
<custom-attribute name="ECOMCustomerId" dt:dt="string">xxxxxx</custom-attribute>
<custom-attribute name="BlockCreditCardPayment" dt:dt="boolean">true</custom-attribute>
<custom-attribute name="CustomLoad" dt:dt="string">true</custom-attribute>
</custom-attributes>
<users>
<user business-partner-no="xxxx">
<business-partner-no>xxxxx</business-partner-no>
<profile>
<first-name>xxxx</first-name>
<last-name>xxxx</last-name>
<email>xxx</email>
</profile>
<user-groups>
<user-group id="IG_SMBCustomers"/>
<user-group id="IG_RecurringUsers"/>
<user-group id="52"/>
</user-groups>
</user>
<user business-partner-no="xxxxx">
<business-partner-no>xxxxx</business-partner-no>
<profile>
<credentials>
<login>xxxxx.com</login>
<password encrypted="1">xxxxx</password>
<enabled>1</enabled>
<reminder-email>xxxxxx.com</reminder-email>
<password-creation-date>2019-03-28T06:37:29-07:00</password-creation-date>
</credentials>
<creation-date>2019-02-28T03:45:43-08:00</creation-date>
<phone-home>xxxxxx</phone-home>
<email>xxxxxxxxx.com</email>
<last-name>xxxxx</last-name>
<first-name>xxxxxx</first-name>
<custom-attributes>
<custom-attribute name="RoleID" dt:dt="string">APP_B2B_BUYER</custom-attribute>
</custom-attributes>
</profile>
</user>
</users>
when I try to get login from user tag even though value is there im getting null my poji looks like
Customer
package com.poc.highline;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "customer")
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
#XmlElement (name = "id")
String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement (name = "customer-type")
String customerType;
public String getCustomerType() {
return customerType;
}
public void setCustomerType(String customerType) {
this.customerType = customerType;
}
#XmlElement (name = "company-name")
String companyName;
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
#XmlElement (name = "industry")
String industry;
public String getIndustry() {
return industry;
}
public void setIndustry(String industry) {
this.industry = industry;
}
#XmlElement (name = "enabled")
String enabled;
public String getEnabled() {
return enabled;
}
public void setEnabled(String enabled) {
this.enabled = enabled;
}
#XmlElement (name = "approval-status")
String approvalStatus;
public String getApprovalStatus() {
return approvalStatus;
}
public void setApprovalStatus(String approvalStatus) {
this.approvalStatus = approvalStatus;
}
#XmlElement (name = "custom-attributes")
List<customAttributes> customAttributes;
public List<customAttributes> getCustomAttributes() {
return customAttributes;
}
public void setCustomAttributes(List<customAttributes> customAttributes) {
this.customAttributes = customAttributes;
}
#XmlElement (name = "users")
List<Users> users;
public List<Users> getUsers() {
return users;
}
public void setUsers(List<Users> users) {
this.users = users;
}
#XmlElement (name = "preferred-invoice-to-address")
PreferredInvoiceAddress invoiceAddress;
public PreferredInvoiceAddress getInvoiceAddress() {
return invoiceAddress;
}
public void setInvoiceAddress(PreferredInvoiceAddress invoiceAddress) {
this.invoiceAddress = invoiceAddress;
}
#XmlElement (name = "addresses")
List<Addresses> addresses;
public List<Addresses> getAddresses() {
return addresses;
}
public void setAddresses(List<Addresses> addresses) {
this.addresses = addresses;
}
}
This is users POJO class
Users
package com.poc.highline;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "users")
#XmlAccessorType(XmlAccessType.FIELD)
public class Users {
#XmlElement(name="user")
List<User> user;
public List<User> getUser() {
return user;
}
public void setUser(List<User> user) {
this.user = user;
}
}
this is the user POJO class
user
package com.poc.highline;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "user")
#XmlAccessorType(XmlAccessType.FIELD)
public class User {
#XmlElement(name = "business-partner-no")
String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement(name = "profile")
String profile;
public String getProfile() {
return profile;
}
public void setProfile(String profile) {
this.profile = profile;
}
#XmlElement(name = "credentials")
String credentials;
public String getCredentials() {
return credentials;
}
public void setCredentials(String credentials) {
this.credentials = credentials;
}
String login;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Im getting value in id but not in other variable refer the watchList
enfinity Enfinity (id=30)
customer ArrayList<E> (id=32)
[0] Customer (id=43)
addresses ArrayList<E> (id=45)
approvalStatus "1" (id=46)
companyName "xxxxx & xxxxx" (id=49)
customAttributes ArrayList<E> (id=50)
customerType "SMB" (id=51)
enabled "1" (id=52)
id null
industry "Retail" (id=53)
invoiceAddress PreferredInvoiceAddress (id=54)
users ArrayList<E> (id=56)
[0] Users (id=58)
user ArrayList<E> (id=60)
[0] User (id=62)
credentials null
email null
id "xxxxx" (id=65)
login null
profile "\n " (id=66)
[1] User (id=63)
credentials null
email null
id "xxxxx" (id=67)
login null
profile "\n " (id=68)
please help thanks in advance.
You are getting null for the Id of your customer because it's not an #XmlElement. Use #XmlAttribute instead.
For clarification:
<customer id="1">
<name>somename</name>
<customer>
id: #XmlAttribute
name: #XmlElement
somename: #XmlValue
Check https://howtodoinjava.com/jaxb/jaxb-annotations/ or other Jaxb tutorials for other annotations.
Edit:
For login and email, you have to annotate them with #XmlAttribute as well.

I can't read attributes with namespace (ns2) using JAXB to parse XML in Java

I have to read data from this XML file:
<SENT_112 xmlns:ns2="http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd" xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd">
<Carrier><ns2:TraderInfo><ns2:IdSisc>PL957271726800000</ns2:IdSisc><ns2:TraderName>FIRMA SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ</ns2:TraderName>
<ns2:TraderIdentityType>NIP</ns2:TraderIdentityType>
<ns2:TraderIdentityNumber>9572717268</ns2:TraderIdentityNumber>
</ns2:TraderInfo>
<ns2:TraderAddress><ns2:Street>Arysztacka</ns2:Street><ns2:HouseNumber>91A</ns2:HouseNumber><ns2:City>Cieszyn</ns2:City><ns2:Country>PL</ns2:Country><ns2:PostalCode>43-400</ns2:PostalCode></ns2:TraderAddress></Carrier>
</SENT_112>
My main class is using JAXB:
JAXBContext jc = JAXBContext.newInstance(SENT_112.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
SENT_112 sent_112 = (SENT_112) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(sent_112, System.out);
Carrier.java
public class Carrier implements java.io.Serializable {
private int nrCarrier;
//private String sentnumber;
private String IdSisc;
private String tradername;
private String traderidentitytype;
private String traderidentitynumber;
private String street;
private String housenumber;
private String city;
private String country;
private String postalcode;
//Contrutors
//Getters and Setters
//ToString Method
SENT_112.java
#XmlRootElement(name="SENT_112")
public class SENT_112 {
#XmlElement(name="Carrier")
private List<Carrier> carrier;
public List<Carrier> getCarrier() {
return carrier;
}
PACKAGE-INFO.JAVA
#XmlSchema(
namespace = "http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.przedlak.entity;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
And my Code return that
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SENT_112 xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd">
<Carrier>
<nrCarrier>0</nrCarrier>
</Carrier>
</SENT_112>
What is wrong with my Code? I need read all information.
If you want to get all information, write your classes appropriately i.e. to retrieve all data. Change Carrier.java to :
Carrier.java
#XmlRootElement(name="Carrier")
#XmlAccessorType(XmlAccessType.FIELD)
public class Carrier implements java.io.Serializable
{
#XmlElement( name = "TraderInfo" )
private TraderInfo traderInfo;
#XmlElement( name = "TraderAddress" )
private TraderAddress traderAddress;
private int nrCarrier;
public int getNrCarrier() {
return nrCarrier;
}
public void setNrCarrier(int nrCarrier) {
this.nrCarrier = nrCarrier;
}
public TraderInfo getTraderInfo() {
return traderInfo;
}
public void setTraderInfo(TraderInfo traderInfo) {
this.traderInfo = traderInfo;
}
public TraderAddress getTraderAddress() {
return traderAddress;
}
public void setTraderAddress(TraderAddress traderAddress) {
this.traderAddress = traderAddress;
}
}
Then define two classes for TraderAddress, TraderInfo as:
TraderInfo
#XmlRootElement(name="TraderInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class TraderInfo
{
#XmlElement( name = "IdSisc")
private String IdSisc;
#XmlElement( name = "TraderName")
private String tradername;
#XmlElement( name = "TraderIdentityType")
private String traderidentitytype;
#XmlElement( name = "TraderIdentityNumber")
private String traderidentitynumber;
public String getIdSisc() {
return IdSisc;
}
public void setIdSisc(String idSisc) {
IdSisc = idSisc;
}
public String getTradername() {
return tradername;
}
public void setTradername(String tradername) {
this.tradername = tradername;
}
public String getTraderidentitytype() {
return traderidentitytype;
}
public void setTraderidentitytype(String traderidentitytype) {
this.traderidentitytype = traderidentitytype;
}
public String getTraderidentitynumber() {
return traderidentitynumber;
}
public void setTraderidentitynumber(String traderidentitynumber) {
this.traderidentitynumber = traderidentitynumber;
}
}
TraderAddress.java
#XmlRootElement(name="TraderInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class TraderAddress
{
#XmlElement( name = "Street")
private String street;
#XmlElement( name = "HouseNumber")
private String houseNumber;
#XmlElement( name = "City")
private String city;
#XmlElement( name = "Country")
private String country;
#XmlElement( name = "PostalCode")
private String postalCode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getHouseNumber() {
return houseNumber;
}
public void setHouseNumber(String houseNumber) {
this.houseNumber = houseNumber;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
}
With this setup, you should get full xml from marshalling:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SENT_112 xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_112.xsd">
<Carrier>
<TraderInfo>
<IdSisc>PL957271726800000</IdSisc>
<TraderName>FIRMA SPÓÅ?KA Z OGRANICZONÄ„ ODPOWIEDZIALNOÅšCIÄ„
</TraderName>
<TraderIdentityType>NIP</TraderIdentityType>
<TraderIdentityNumber>9572717268</TraderIdentityNumber>
</TraderInfo>
<TraderAddress>
<Street>Arysztacka</Street>
<HouseNumber>91A</HouseNumber>
<City>Cieszyn</City>
<Country>PL</Country>
<PostalCode>43-400</PostalCode>
</TraderAddress>
<nrCarrier>0</nrCarrier>
</Carrier>
</SENT_112>

JAXB object containment to xml

I am trying to print the xml from java using jaxb.
The code I have is as follows:
public class MyXMLGenerator {
public static void main(String[] args) throws Exception {
JAXBPojo jaxbPojo = new JAXBPojo();
jaxbPojo.setName("setName");
jaxbPojo.setId(345);
JAXBContext jc = JAXBContext.newInstance(JAXBPojo.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(jaxbPojo, System.out);
}
}
#XmlRootElement
public class JAXBPojo {
private int id;
private String name;
private Date dob;
#XmlElement(namespace="ddd")
private Address address;
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 Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public Address getAddress() {
return address;
}
public void setAddress() {
address = new Address();
address.setHouseName("setHouseName");
address.setStateName("setStateName");
address.setLocalityName("setLocalityName");
address.setAreaName("setAreaName");
address.setCityName("setCityName");
}
}
#XmlElement
public class Address {
private String houseName;
private String streetName;
private String localityName;
private String areaName;
private String cityName;
private String districtName;
private String stateName;
private String countryName;
public String getHouseName() {
return houseName;
}
public void setHouseName(String houseName) {
this.houseName = houseName;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getLocalityName() {
return localityName;
}
public void setLocalityName(String localityName) {
this.localityName = localityName;
}
public String getAreaName() {
return areaName;
}
public void setAreaName(String areaName) {
this.areaName = areaName;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getDistrictName() {
return districtName;
}
public void setDistrictName(String districtName) {
this.districtName = districtName;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
}
I get this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxbPojo xmlns:ns2="ddd">
<id>345</id>
<name>setName</name>
</jaxbPojo>
But when I supply value for address class in the main method, I do get the address as well in the output like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxbPojo>
<address>
<areaName>setAreaName</areaName>
<cityName>setCityName</cityName>
<houseName>setHouseName</houseName>
<localityName>setLocalityName</localityName>
<stateName>setStateName</stateName>
</address>
<id>345</id>
<name>setName</name>
</jaxbPojo>
what changes do I have to do to get it working in the current case where I get values for address class in jaxbpojo?
Thanks in advance...
I am not exactly sure what you want but I would change setAddress to:
public void setAddress(Address address) {
this.address = address;
}
main to :
public static void main(String[] args) throws Exception {
JAXBPojo jaxbPojo = new JAXBPojo();
jaxbPojo.setName("setName");
jaxbPojo.setId(345);
Address address = new Address();
address.setHouseName("setHouseName");
address.setStateName("setStateName");
address.setLocalityName("setLocalityName");
address.setAreaName("setAreaName");
address.setCityName("setCityName");
jaxbPojo.setAddress(address);
JAXBContext jc = JAXBContext.newInstance(JAXBPojo.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(jaxbPojo, System.out);
}

how create xml from java object using jaxb

How can i create following type xml in java using jaxb
<myInfo>
<firstName>MyfirstName</firstName>
<lastName>MyLstNme</lastName>
<contactList>
<contact>
<id>001</id>
<name>name1</name>
<contact/>
<contact>
<id>002</id>
<name>name2</name>
<contact/>
<contact>
<id>003</id>
<name>name3</name>
<contact/>
</ContactList>
</myInfo>
Bean Classes are..
#XmlRootElement(name = "myInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class MyInfo {
#XmlElement(name = "firstName")
public String firstName;
#XmlElement(name = "lastName")
public String lastName;
#XmlElement(name = "contactList")
public ContactList contactList;
...getter setter
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "contactList")
public class ContactList {
#XmlElement(name = "contact", type = Contact.class)
public List<Contact> list = new ArrayList<Contact>();
public ContactList() {
}
public ContactList(List<Contact> list) {
this.list = list;
}
...getter setter
}
#XmlRootElement(name = "Contact")
public class Contact {
#XmlElement(name = "id")
public String id;
#XmlElement(name = "name")
public String name;
...getter setter
And Exception
objData ToXML 2 counts of IllegalAnnotationExceptions
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
==
Class has two properties of the same name "id"
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.getId()
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.id
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
Class has two properties of the same name "name"
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.getName()
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
this problem is related to the following location:
at public java.lang.String java8javafx8.Contact.name
at java8javafx8.Contact
at public java.util.List java8javafx8.ContactList.list
at java8javafx8.ContactList
at public java8javafx8.ContactList java8javafx8.MyInfo.contactList
at java8javafx8.MyInfo
How create Bean Class and Bean List Class??
Ok hear you go:
Make one class call MyInfo as:
#XmlRootElement(name="myInfo")
public class MyInfo {
private String firstName;
private String lastName;
private List<Contact> contactList = new ArrayList<Contact>(0);
public MyInfo(){}
public MyInfo(String fName, String lName){
this.firstName = fName;
this.lastName = lName;
}
#XmlElement(name = "firstName")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#XmlElement(name="lastName")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<Contact> getContactList() {
return contactList;
}
#XmlElement(name = "contactList")
public void setContactList(List<Contact> contactList) {
this.contactList = contactList;
}
}
write another class called Contact as:
public class Contact {
private int id;
private String name;
public Contact(){}
public Contact(int id, String name){
this.id = id;
this.name = name;
}
#XmlElement(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Marshell it with JAXB (create XML) as:
public class Test {
public static void main(String[] args){
Contact c1 = new Contact(1, "first");
Contact c2 = new Contact(2, "second");
MyInfo info = new MyInfo("Shekhar", "Khairnar");
info.getContactList().add(c1);
info.getContactList().add(c2);
try {
JAXBContext jaxbContext = JAXBContext.newInstance(MyInfo.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(info, System.out);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
In above eg. I just print the xml output on console you can write in a file also.
out put will be:
<myInfo>
<firstName>Shekhar</firstName>
<lastName>Khairnar</lastName>
<contactList>
<id>1</id>
<name>first</name>
</contactList>
<contactList>
<id>2</id>
<name>second</name>
</contactList>
You can do the following:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class MyInfo {
private String firstName;
private String lastName;
#XmlElementWrapper
#XmlElement(name="contact")
private List<Contact> contactList;
// getters & setters
}
Things to note:
JAXB is configuration by exception so you only need to annotate where you want the XML representation to differ from the default.
By default JAXB treats public fields and properties as mapped. If you want to treat only fields as mapped you should specify #XmlAccessorType(XmlAccessType.FIELD).
The mapped fields can be private.
#XmlElementWrapper is used to add a grouping element to a collection.
When #XmlElement is used on a collection it applies to each item in the collection.

#XmlRegistry - how does it work?

I have found some examples of JAXB2 #XmlRegistry over the internet but no good in-depth tutorials that talk about the concept of using #XmlRegistry with #XmlElementDecl, wonder if its a concept not much explored in general.
Anyways here is my question, first some sample classes that I am using to unmarshall an xml using JAXB:
The main class I am trying to unmarshal using JAXB - Employee.java
package com.test.jaxb;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import com.test.jaxb.dto.Address;
#XmlRootElement
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;
}
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
#SuppressWarnings("unused")
#XmlRegistry
public static class XMLObjectFactory {
#XmlElementDecl(scope = Employee.class, name= "id")
JAXBElement<String> createEmployeeId(String value) {
return new JAXBElement<String>(new QName("id"), String.class, "100");
}
#XmlElementDecl(scope = Employee.class, name= "name")
JAXBElement<String> createName(String value) {
return new JAXBElement<String>(new QName("name"), String.class, "Fake Name");
}
#XmlElementDecl(scope = Employee.class, name= "email")
JAXBElement<String> createEmail(String value) {
return new JAXBElement<String>(new QName("email"), String.class, value);
}
#XmlElementDecl(scope = Employee.class, name= "addresses")
JAXBElement<List> createAddresses(List value) {
return new JAXBElement<List>(new QName("addresses"), List.class, value);
}
}
}
The child class - Address.java
package com.test.jaxb.dto;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import com.test.jaxb.Employee;
#XmlRootElement
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;
}
#SuppressWarnings("unused")
#XmlRegistry
private static class XMLObjectFactory {
#XmlElementDecl(scope = Employee.class, name= "addressLine1")
JAXBElement<String> createAddressLine1(String value) {
return new JAXBElement<String>(new QName("addressLine1"), String.class, value);
}
#XmlElementDecl(scope = Employee.class, name= "addressLine2")
JAXBElement<String> createAddressLine2(String value) {
return new JAXBElement<String>(new QName("addressLine2"), String.class, value);
}
#XmlElementDecl(scope = Employee.class, name= "addressLine3")
JAXBElement<String> createAddressLine3(String value) {
return new JAXBElement<String>(new QName("addressLine3"), String.class, value);
}
}
}
The xml to be unmarshalled - employee.xml
<?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>
Unmarshalling Code :
package com.test.jaxb;
import java.io.FileReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class ObjectFactoryTest {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("resources/employee.xml");
JAXBContext context = JAXBContext.newInstance(Employee.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(reader);
System.out.println(obj);
}
}
When I unmarshal the employee xml using above code, the address list does not get populated. The resulting employee object only has a blank list of adresses. Is there anything wrong with my mappings?
To find out what is going on and see if the employee objects are actually being created using the Object Factory (having the #XMLRegistry annotation), I changed the value of id and name in factory methods, however that had no effect in the output, which tells me JAXB is not actually using the ObjectFactory, why?
Am I going aboout this all wrong? Any help would be appreciated.
#XmlRegistry - how does it work?
#XmlRegistry is used to mark a class that has #XmlElementDecl annotations. To have your JAXB implementation process this class you need to ensure that it is included in the list of classes used to bootstrap the JAXBContext. It is not enough for it to be a static inner class of one of your domain model classes:
JAXBContext context = JAXBContext.newInstance(Employee.class, Employee.XMLObjectFactory.class);
#XmlElementDecl - how does it work?
If the value of the field/property is going to be a JAXBElement then you need to leverage #XmlElementDecl. A JAXBElement captures information that is can be useful:
Element name, this is necessary if you are mapping to a choice structure where multiple elements are of the same type. If the element name does not correspond to a unique type then you would not be able to round-trip 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 modified the model from you post a bit. I have introduced an XmlObjectFactory class that has two #XmlElementDecl. Both specify a name of address. I have leveraged the scope property so that for properties within the Employee class the #XmlElementDecl corresponding to the Address class with be used.
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 annotation will cause the value of the property to be matched on its root element name. Possible matches will include classes mapped with #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 class and input.xml from my original answer can be used to run this example.
ORIGINAL ANSWER
I'm not sure how you are attempting to use #XmlRegistry, so I will focus on the following part of your post:
When I unmarshal the employee xml using above code, the address list
does not get populated. The resulting employee object only has a blank
list of adresses. Is there anything wrong with my mappings?
Your list of Address objects is wrapped in a grouping element (addresses), so you need to use the #XmlElementWrapper annotation to map this use case. Below 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>
You have to take a List object of Address. In that object, you will have to add the object which contains data like addressline1. addressline2 and so on.
i.e.
List addrObjList = new List();
addrObjList.add(object); // Bind an object containing data and add one by one

Categories

Resources