Getting Started

Version 6 by Robin Shen
on Feb 10, 2010 05:56.


compared with
Version 7 by Robin Shen
on Feb 10, 2010 06:04.


Key
These lines were removed. This word was removed.
These lines were added. This word was added.

View page history


There are 4 changes. View first change.

 We demonstrate usage of this tool with a simple tutorial. Assume a _Task_ class below with a _prioritized_ field indicating whether it is a prioritized task:
 {code}
 package example;
  
 public class Task {
  public boolean prioritized;
 }
 {code}
 With XStream, we can serialize object of this class to XML like below:
 {code}
 import com.thoughtworks.xstream.XStream;
  
 Task task = new Task();
 task.prioritized = true;
 String xml = new XStream().toXML(task);
 saveXmlToFileOrDatabase(xml);
  public class Test {
  public static void main(String args[]) {
 Task task = new Task();
  task.prioritized = true;
  String xml = new XStream().toXML(task);
  saveXmlToFileOrDatabase(xml);
  }
 }
 {code}
 The resulting XML will be:
 {code}
 <example.Task>
  <prioritized>true</prioritized>
 </example.Task>
 {code}
 And you can deserialize the XML to get back task object:
 {code}
 import com.thoughtworks.xstream.XStream;
 import com.thoughtworks.xstream.io.xml.DomDriver;
  
String xml = readXmlFromFileOrDatabase();
 Task task = (Task)(new XStream(new DomDriver()).fromXML(xml));
  public class Test {
  public static void main(String args[]) {
  String xml = readXmlFromFileOrDatabase();
  Task task = (Task)(new XStream(new DomDriver()).fromXML(xml));
  }
 }
 {code}
 Everything is fine. Now we find a prioritized flag is not enough, so we enhance the Task class to use a numeric priority field ranging from 1 to 10:
 {code}
 package example;
  
 public class Task {
  public int priority;
 }
 {code}
 However deserialization of previously saved xml is no longer possible since the new Task class is not compatible with previous version. XMT comes to rescue: it introduces class _VersionedDocument_ to version serialized XMLs and handles the migration. With XMT, serialization of task object can be written as:
 {code}
 package example;
 import com.pmease.commons.xmt.VersionedDocument;
  
Task task = new Task();
 task.prioritized = true;
 String xml = VersionedDocument.fromBean(task).toXML();
 saveXmlToFileOrDatabase(xml);
  public class Test {
  public static void main(String args[]) {
 Task task = new Task();
  task.prioritized = true;
  String xml = VersionedDocument.fromBean(task).toXML();
  saveXmlToFileOrDatabase(xml);
  }
 }
 {code}
 The resulting XML will be:
 {code}
 <?xml version="1.0" encoding="UTF-8"?>
  
 <example.Task version="0">
  <prioritized>true</prioritized>
 </example.Task>
 {code}
 Compared with the XML generated by directly using XStream, an additional attribute _version_ is added to the root element indicating version of associated class. The value is set to _0_ unless there are migration methods defined in the class as we will introduce below.
  
 When Task class is evolved to use numeric priority field, we add a migrate method like below:
 {code}
 package com.pmease.commons.xmt.bean;
  
 import java.util.List;
 import org.dom4j.Element;
 import com.pmease.commons.xmt.VersionedDocument;
  
 public class Task {
  private int priority;
  
  public int getPriority() {
  return priority;
  }
  
  public void setPriority(int priority) {
  this.priority = priority;
  }
  
  @SuppressWarnings("unused")
  private void migrate1(VersionedDocument dom, List<String> versions) {
  Element element = dom.getRootElement().element("prioritized");
  element.setName("priority");
  if (element.getText().equals("true"))
  element.setText("10");
  else
  element.setText("1");
  }
 }
 {code}
 Here method _migrate1_ migrates the XML from version 0 to 1. The XML to be migrated is passed as a _VersionedDocument_ object which implements dom4j _Document_ interface and you may use dom4j to migrate it to be compatible with current version of the class. The _versions_ parameter is used to handle the migration if class inheritance hierarchy is changed and will be introduced in [class hierarchy migration chapter].
 In this migration method, we read back the "prioritized" element of version 0, rename it as "priority", and then set the value as "10" if the task is originally a prioritized task; otherwise, set the value as "0".
  
 With this migration method defined, you can now safely deserialize the task object from XML:
 {code}
 package example;
  
 import com.pmease.commons.xmt.VersionedDocument;
  
 public class Test {
  public static void main(String args[]) {
  String xml = readXmlFromFileOrDatabase();
  Task task = (Task) VersionedDocument.fromXML(xml).toBean();
  }
 }
 {code}