Mohamed Said
Mohamed Said

Reputation: 543

Jaxb unmarshalling returns null and single objects

I'm trying to unmarshal an a xml file. Here's my files below.

XML file

<AccountInfo>
   <Account>
    <FirstName>FirstName1</FirstName>
    <LastName>LastName1</LastName>
    <Country>US</Country>
    <PhoneNumber>2022023111</PhoneNumber>
    <Email>[email protected]</Email>
    <Password>1222433123</Password>
    <PaymentMethod>
        <CardNumber>4111111111111111</CardNumber>
        <Month>12</Month>
        <Year>2017</Year>
        <CVV>098</CVV>
        <StreetAddress>test</StreetAddress>
        <Town>test</Town>
        <State>Virginia</State>
        <ZipCode>12365</ZipCode>
        <Country>US</Country>
    </PaymentMethod>
 </Account>
 <Account>
    <FirstName>FirstName1</FirstName>
    <LastName>LastName1</LastName>
    <Country>US</Country>
    <PhoneNumber>2022023111</PhoneNumber>
    <Email>[email protected]</Email>
    <Password>1222433123</Password>
    <PaymentMethod>
        <CardNumber>4111111111111111</CardNumber>
        <Month>12</Month>
        <Year>2017</Year>
        <CVV>098</CVV>
        <StreetAddress>test</StreetAddress>
        <Town>test</Town>
        <State>Virginia</State>
        <ZipCode>12365</ZipCode>
        <Country>US</Country>
    </PaymentMethod>
 </Account>
</AccountInfo>

JaxbHelper.java

 public static <T> T unmarshal(InputStream file, Class<T> unmarshalClass) 
 throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(unmarshalClass);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    T object = (T) jaxbUnmarshaller.unmarshal(file);
    return object;
}

AccountInfo.java

  @XmlRootElement(name = "AccountInfo")
  @XmlAccessorType(XmlAccessType.FIELD)
  @XmlSeeAlso({PaymentMethod.class})
  public class AccountInfo {

  @XmlElement(name = "FirstName")
  private String FirstName;
  @XmlElement(name = "LastName")
  private String LastName;
  @XmlElement(name = "Country")
  private String Country;
  @XmlElement(name = "PhoneNumber")
  private String PhoneNumber;
  @XmlElement(name = "Email")
  private String Email;
  @XmlElement(name = "Password")
  private String Password;
  @XmlElement(name = "PaymentMethod")
  private PaymentMethod paymentMethod;

  public AccountInfo() {
    setFirstName(null);
    setLastName(null);
    setCountry(null);
    setPhoneNumber(null);
    setEmail(null);
    setPassword(null);
    setPaymentMethod(null);
}

public AccountInfo(String FirstName, String LastName, String Country, String PhoneNumber, String Email, String Password, PaymentMethod paymentMethod) {
    setFirstName(FirstName);
    setLastName(LastName);
    setCountry(Country);
    setPhoneNumber(PhoneNumber);
    setEmail(Email);
    setPassword(Password);
    setPaymentMethod(paymentMethod);
}


public String getFirstName() {
    return FirstName;
}

public void setFirstName(String firstName) {
    this.FirstName = firstName;
}

public String getLastName() {
    return LastName;
}

public void setLastName(String lastName) {
    this.LastName = lastName;
}

public String getCountry() {
    return Country;
}

public void setCountry(String country) {
    this.Country = country;
}

public String getPhoneNumber() {
    return PhoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
    this.PhoneNumber = phoneNumber;
}

public String getEmail() {
    return Email;
}

public void setEmail(String email) {
    this.Email = email;
}

public String getPassword() {
    return Password;
}

public void setPassword(String password) {
    this.Password = password;
}

public PaymentMethod getPaymentMethod() {
    return paymentMethod;
}


public void setPaymentMethod(PaymentMethod paymentMethod) {
    this.paymentMethod = paymentMethod;
  }
}

How I consume the unmarshal

  List<T> accountInfo = (List<T>)ProcessClassHelper.unmarshal(xmlfile, Class.forName(Constants.ClassesDir +className));

I'm unsure what's causing the issue but the object is returned as single object even though there are multiple accounts and the returned data are null.

Thanks in advance.

Upvotes: 3

Views: 4249

Answers (1)

Thomas Fritsch
Thomas Fritsch

Reputation: 10127

Your Java classes don't match the structure of your XML file. As @Rhayene already commented, you need separate Java classes for AccountInfo and Account.

AccountInfo will contain only a list of Accounts:

@XmlRootElement(name = "AccountInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public class AccountInfo {

    @XmlElement(name = "Account")
    private List<Account> accounts;

    // + constructors, getters, setters
}

Account will contain all the properties which you had in in AccountInfo before.
(By the way: You should also follow the convention of field names beginning with lower-case letter. This will not break anything because the XML names are still specified by @XmlElement)

@XmlAccessorType(XmlAccessType.FIELD)
public class Account {

    @XmlElement(name = "FirstName")
    private String firstName;
    @XmlElement(name = "LastName")
    private String lastName;
    @XmlElement(name = "Country")
    private String country;
    @XmlElement(name = "PhoneNumber")
    private String phoneNumber;
    @XmlElement(name = "Email")
    private String email;
    @XmlElement(name = "Password")
    private String password;
    @XmlElement(name = "PaymentMethod")
    private PaymentMethod paymentMethod;

    // + constructors, getters, setters
}

Upvotes: 5

Related Questions