Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Versioning" JAXB object?

Tags:

jaxb

We're building a many developer app using JAXB and keep stumbling on problems that all come back to a "version" mismatch between producers and consumers of JAXB objects.

Process hasn't alleviated the pain so I was thinking about something along the lines of CORBA object versioning for JAXB, maybe via a required final field whose values must match. As an added bonus I'd like to inject the version value as the Maven version # :-)

This is all using annotations, no xsd.

Thoughts?

Thanks.

----- Clarification -----

Think of this as a Serializable serialVersionUID that is added to the marshal stream when the object is marshaled and is required and whose value is checked when the object is unmarshaled.

Various check rules can be implemented, but in this case I only want equality. If the current version of a Foo is 1.1 and you send me data to unmarshal whose version is anything other than 1.1 I will reject it.

Help?

like image 619
Mike Summers Avatar asked Aug 31 '12 15:08

Mike Summers


1 Answers

You could do something like the following:

Foo

Add a version field to your root model object.

package forum12218164;

import javax.xml.bind.annotation.*;

@XmlRootElement
public class Foo {

    @XmlAttribute
    public static final String VERSION = "123";

    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

}

Demo

In your demo code leverage a StAX parser to check the version attribute before determining if it is safe to perform the unmarshal operation:

package forum12218164;

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Create the JAXBContext
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        // Create an XMLStreamReader on XML input
        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource xml = new StreamSource("src/forum12218164/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);

        // Check the version attribute
        xsr.nextTag(); // Advance to root element
        String version = xsr.getAttributeValue("", "VERSION");
        if(!version.equals(Foo.VERSION)) {
            // Do something if the version is incompatible
            throw new RuntimeException("VERSION MISMATCH");
        }

        // Unmarshal for StAX XMLStreamReader
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Foo foo = (Foo) unmarshaller.unmarshal(xsr);

        // Marshal the Object
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foo, System.out);
    }

}

VALID USE CASE

input.xml/Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo VERSION="123">
    <bar>ABC</bar>
</foo>

INVALID USE CASE

input.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo VERSION="1234">
    <bar>ABC</bar>
</foo>

Output

Exception in thread "main" java.lang.RuntimeException: VERSION MISMATCH
    at forum12218164.Demo.main(Demo.java:23)
like image 101
bdoughan Avatar answered Oct 07 '22 19:10

bdoughan