Diego Macario
Diego Macario

Reputation: 1230

Is there anyway to use a superclass in Jaxb?

I´m modeling my project and I want to know if is possible to reduce the repetition of code in my unmarshal process.

I have two classes

public class Person {
  private String name;
  private String telephone

  // getter and setter
}


public class Company {
  private String name;
  private String telephone

  // getter and setter
}

My xml have this source.

<file>
  <person>
    <name>Test</name>
    <telephone>190</telephone>
  </person>
  <company>
    <name>Test2</name>
    <telephone>181</telephone>
  </company>
</file>

So I want to know what should I do to make a superclass being reconized by the others and by Jaxb.

Thanks

Upvotes: 0

Views: 596

Answers (1)

Ithamar Diaz
Ithamar Diaz

Reputation: 114

You could accomplish this with annotation @XmlSeeAlso.

@XmlSeeAlso({Person.class,Company.class})
public class  Contact {
private String name;
private String telephone
//getters and setters
}
public class Person extends Contact {

}


public class Company extends Contact{
}

you could then

JAXBContext.newInstance(Contact.class)

and it would allow for both classes to be handled by same code

Okay so below is what I did. I took your xml file(changed File to something diff as in this case FileTest2, excuse the horrible names), created the classes in composition style, and tested to make sure the unmarshal would work. I then marshaled it again to make sure I got the correct xml structure back, see below code.

    @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {
    private String name;
    private String telephone;

    public Person() {
        super();
    }

    public Person(String name, String telephone){
        this();
        setName(name);
        setTelephone(telephone);
    }

    public String getName(){
        return name;
    }
    public String getTelephone(){
        return telephone;
    }

    public void setName(String name){
        this.name=name;
    }

    public void setTelephone(String telephone){
        this.telephone=telephone;
    }
}

    @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Company {
    private String name;
    private String telephone;

    public Company() {
        super();
    }

    public Company(String name, String telephone){
        this();
        setName(name);
        setTelephone(telephone);
    }

    public String getName(){
        return name;
    }
    public String getTelephone(){
        return telephone;
    }

    public void setName(String name){
        this.name=name;
    }

    public void setTelephone(String telephone){
        this.telephone=telephone;
    }

}

    @XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class FileTest2 {

    private Person person;
    private Company company;

    public FileTest2() {
        super();
    }

    public FileTest2(Person person, Company company){
        this();
        setPerson(person);
        setCompany(company);
    }

    public Person getPerson() {
        return this.person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Company getCompany() {
        return this.company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }   
}

        @Test
    public void testUnMarshal() throws Exception {
        File xmlFile = null;
        try {
            xmlFile = getXmlFile();
        } catch (Exception e) {
        }
        if (xmlFile == null) {
            fail("file not found");
        }
        FileTest2 filetest = (FileTest2) JaxbUtil.unmarshal(
                xmlFile, filetest.class,
                FileTest2.class, Person.class, Company.class);
        if (filetest==null){
            fail("unmarshal failed");
        }
        assertEquals("Company name was not correctly handled","Test2",filetest.getCompany().getName());
        assertEquals("Company telephone was not correclty handled","181", filetest.getCompany().getTelephone());
        assertEquals("Person name was not correctly handled","Test",filetest.getPerson().getName());
        assertEquals("Person telephone was not correclty handled","190", filetest.getPerson().getTelephone());

    }

        @Test
    public void testMarshal() throws Exception {
        Person person = new Person("bob", "23");
        Company company = new Company("accountTemps", "99");
        FileTest2 filetest = new FileTest2(person, company);
        FileWriter fileWriter = new FileWriter("marshaledFileResults.xml");
        JaxbUtil.marshal(filetest, fileWriter, true, filetest.class,
                FileTest2.class, Person.class, Company.class);
    }

the testMarshal produced the following

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<fileTest2>
<person>
    <name>bob</name>
    <telephone>23</telephone>
</person>
<company>
    <name>accountTemps</name>
    <telephone>99</telephone>
</company>
</fileTest2>

So, what I think you want to know is how do you stop from having to repeat all that boilerplate needed for marshal and unmarshal. I accomplish this through my JaxbUtil class. I have all the boilerplate in there and I simply need to call the overloaded method I need for marshal or unmarshal passing in the classes to be bound and all the ugly boilerplate stuff stays away from my actual code.

Also for anyone that wanted to user custom adapters for multiple classes with similar class structures you could use generics in your custom adapter that extends XmlAdapter and use annotation @XmlJavaTypeAdapter so Jaxb uses your generic adapter for those classes.

Upvotes: 1

Related Questions