Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jaxb Inheritance using Substitution but not to root Element

Tags:

java

jaxb

moxy

I was going through the Blaise's Blog http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html for Jaxb Inheritance using Substitution.

I want to implement the same but not to the root element. I am looking this type of XML as a output.

   <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <configuration>
      <customer>
        <address>
            <street>1 A Street</street>
        </address>
        <address>
            <street>2 B Street</street>
        </address>
        <phoneNumber>
            <mobileNo>xxx-xxx-xxxx</mobileNo>
         </phoneNumber>
     </customer>
 </configuration>

Following is the Configuration.java

    import javax.xml.bind.annotation.XmlRootElement;

    @XmlRootElement
     public class Configuration {

    private Customer customer;

    public Customer getCustomer() {
        return customer;
    }

     public void setCustomer(Customer customer) {
        this.customer = customer;
     }

    @Override
    public String toString() {
        return "\n Customer[ customer="+customer+"]";
     }

     }

Customer.java

     public class Customer {
private List<ContactInfo> contactInfo;

@XmlElementRef
public List<ContactInfo> getContactInfo() {
    return contactInfo;
}

public void setContactInfo(List<ContactInfo> contactInfo) {
    this.contactInfo = contactInfo;
}

    }

Address.java

  public class Address extends ContactInfo {
private String street;

public String getStreet() {
    return street;
}

public void setStreet(String street) {
    this.street = street;
}

}

PhoneNumber.java

    public class PhoneNumber extends ContactInfo{
private String mobileNo;

public String getMobileNo() {
    return mobileNo;
}

public void setMobileNo(String mobileNo) {
    this.mobileNo = mobileNo;
}

   }

Demo.java

     import java.util.ArrayList;
     import java.util.List;

     import javax.xml.bind.JAXBContext;
     import javax.xml.bind.Marshaller;

      public class Demo {
    public static void main(String[] args) throws Exception {
    Configuration configuration = new Configuration();
    Customer customer = new Customer();
    List<ContactInfo> contacts = new ArrayList<ContactInfo>();

    Address address = new Address();
    address.setStreet("1 A Street");
    contacts.add(address);

    Address address1 = new Address();
    address1.setStreet("2 B Street");
    contacts.add(address1);

    PhoneNumber phone = new PhoneNumber();
    phone.setMobileNo("408 431 8829");
    contacts.add(phone);

    customer.setContactInfo(contacts);

    configuration.setCustomer(customer);

    JAXBContext jc = JAXBContext.newInstance(Configuration.class);
    Marshaller marshaller = jc.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(configuration, System.out);
    }
 }

Presently I am getting following Exception

    Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException:     1 counts of IllegalAnnotationExceptions
    Invalid @XmlElementRef : Type "class Address" or any of its subclasses are not known to this context.

Could anybody help me out on this?

Thanks, Kwatra

like image 928
kwatra Avatar asked Jun 21 '13 18:06

kwatra


1 Answers

Issue #1 - The Subclasses

A JAXB (JSR-222) implementation can not auto discover subclasses. You can solve the first exception by using an @XmlSeeAlso annotation on the ContactInfo class to reference the subclasses:

@XmlSeeAlso({Address.class, PhoneNumber.class})
public class ContactInfo {
}

Or you can reference them when you create the JAXBContext.

 JAXBContext jc = JAXBContext.newInstance(Configuration.class, Address.class, PhoneNumber.class);

Issue #2 - The Mapping

When using @XmlElementRef you need to pair it with @XmlRootElement. If you don't want to go this route you could use @XmlElements instead.

@XmlElements({
    @XmlElement(name="address", type=Address.class),
    @XmlElement(name="phoneNumber", type=PhoneNumber.class)
})
public List<ContactInfo> getContactInfo() {
    return contactInfo;
}
  • http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html
like image 131
bdoughan Avatar answered Oct 16 '22 16:10

bdoughan