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?
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With