简体   繁体   中英

Supporting multiple xsd versions

Let me explain my scenario I have a web application that takes xml requests and responds. I have used jaxb to parse the request, convert it to my applications dao object, process the request and then reconvert the dao result to jaxb object and return that. Now i have to support multiple versions (different xml versions can come as request and i have to respond with suitable xml response). I generate java files for jaxb object -> dao object convertor and reverse. Problem is that before conversion to my dao object the jaxb object is created and then validated before passing it to my convertor. I am not sure what design pattern to apply here. Might be adaptor pattern. Please suggest? Also throw light if i may have to generate the jaxb marshalling and un-marshalling code too?

Hopefully I understood well your problem. So you already have:

xml 1 ---> jaxb objects 1 ---> converter 1 ---> entity objects

And now you need to acomodate a new xml format.

For this you can either write a new converter to support the new format:

xml 2 ---> jaxb objects 2 ---> converter 2 ---> entity objects

or write some xml adapters to adapt the new jaxb objects to the first format:

xml 2 ---> jaxb objects 2 ---> adapter ---> jaxb objects 1 ---> converter 1 ---> entity objects

I would suggest the first approach: to write a new converter so the new format is not dependent of the first one (in case might need to retire first format).

The converter mixes itself with the jaxb objects as a wrapper around the entity objects together with the @XmlJavaTypeAdapter for complex types. A very simple example:

public class XmlPerson {
    private Person person;

    public XmlPerson(Person person) {
        this.person = person;
    }

    public XmlPerson() {
        this.person = new Person();
    }

    public Person getPerson() {
    }

    public String getFirstName() {
        return person.getFristname();
    }

    public void setFirstname(String firstName) {
        person.setFirstName(firstName);
    }

    ....

    @XmlJavaTypeAdapter(XmlAddressAdapter.class)
    public Address getAddress() {
        return person.getAddress();
    }

    public void setAddress(Address address) {
        person.setAddress(address);
    }
}

The @XmlJavaTypeAdapter should itself adapt(convert) from an Address to a XmlAddress .

public class XmlAddressAdapter extends XmlAdapter<XmlAddress, Address> {
    @Override
    public Address unmarshal(XmlAddress xmlAddress) throws Exception {
        return xmlAddress.getAddress();
    }

    @Override
    public XmlAddress marshal(Address address) throws Exception {
        return address != null ? new XmlAddress(address) : null;
    }
}

Also throw light if i may have to generate the jaxb marshalling and un-marshalling code too?

You just need to pass the xml objects to the marshaller and validate the xsd with the unmarshaller as yoou might already be doing:

Marshal:

   JAXBContext jaxbContext = JAXBContext.newInstance(XmlPerson.class);
   Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
   jaxbMarshaller.marshal(xmlPerson, output);

Unmarshal:

JAXBContext jaxbContext = JAXBContext.newInstance(targetClass);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

SchemaFactory sf = SchemaFactory.newInstance(
                    javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(XmlInvoice.class.getResource("/yourXsd.xsd"));
jaxbUnmarshaller.setSchema(schema);

Object unmarshalResult = jaxbUnmarshaller.unmarshal(inputStream);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM