简体   繁体   中英

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 (eg 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 (eg 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.

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.

If you are using JAXB you would be persisting xml and not the java object. If you were persisting java object it would be serialization. Jaxb transformation tries to bind the xml values to the class attributes. As long as the transformation prerequisites work, there shouldn't be a problem. Other libraries like JIBX, try to access bytecode directly. The class version may be an issue in such a case.

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