Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB and different versions of the class

I wonder if there is any support for different versions of class in JAXB. My thoughts about it: xml is kind of persistence object of class (serialized value) but class object can be changed due to development (e.g. extending the functionality). Is there any way to know which version of class is stored in persistence (read: xml) using only JAXB API?

For me it seems convenient to store class version - like it's done in standard java serialization mechanism (I mean serialVersionUID) and provide functionality to map xml on class even in case of different version (e.g. adding in XmlAdapter information about version of class stored in xml). By default, if version of class in xml and in runtime differs - throw InvalidClassException.

Example: We have class Test as follows:

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {

    private Long time;

    private Test () {}; 
}

assuming that time is UNIX time in millis.

This code was released on production and this class was persisted in the database as xml. Next release shows that it was not good choice to use Long as time representation and it was changed to Date:

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {

    private Date time;

    private Test () {}; 
}

Now there are two ways - either to migrate persisted data or to write xml adapter which will handle Long time and apply it to the Date time.

If we choose the second way it would be great if JAXB API provides class version which were stored in xml (assuming if no class version is specified in class = 0 version) and we add new version of class explicitly (either by annotation or by static field):

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
@XmlClassVersion(value = 1)
public class Test {

    private Date time;

    private Test () {}; 
}

or

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class Test {

    private static final long xmlSerialVersionUID = 1;

    private Date time;

    private Test () {}; 
}

and JAXB will provide XmlAdapter as follows:

public abstract class XmlAdapter<ValueType,BoundType> {
    protected XmlAdapter() {}
    public abstract BoundType unmarshal(ValueType v, long classVersion) throws Exception;

    public abstract ValueType marshal(BoundType v, long classVersion) throws Exception;
}

In order to support multiple versions, of course, we need to implement such adapter and handle different versions explicitly. Clearly, then, JAXB will add special information about class in xml and will generate xml on the latest class version.

NOTE: the point of the example above that we have 2 different representations of class in the persistence simultaneously but still can map them to the version of class available in the runtime.

like image 664
se.solovyev Avatar asked Nov 13 '22 08:11

se.solovyev


1 Answers

JAXB stands for "Java Architecture for XML Binding", so, it's about binding objects fields values to XML elements/attributes, and not about serializing java objects. In you read for example this article, you see that it says

javax.xml.bind, contains classes and interfaces for performing operations such as unmarshalling, marshalling, and validation

Java object serialization is another thing, and it's related to the serialVersionUID that you mention in your question.

like image 200
MarcoS Avatar answered Nov 16 '22 03:11

MarcoS