A veces puede ser necesario hacer que un simple bean u objeto sea persistente. Es decir, escribir a disco todos los atributos de un objeto dado para volver a leerlo en otro momento y recuperarlo. El sistema clásico para hacer esto es utilizando la interfaz java.io.Serializable y utilizando un ObjectOutputStream para guardarlo y un ObjectInputStream para recuperarlo.
public class MiObjeto implements java.io.Serializable {
String nombre = "Mola";
Collection datos = new ArrayList();
}
Creamos un par de métodos estáticos en una clase externa:
public class IOTools {
public static void serialize(Object o, OutputStream os)
throws IOException {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(os);
oos.writeObject(o);
} finally {
if (oos != null) oos.close();
}
}
public static Object deserialize(InputStream os)
throws IOException, ClassNotFoundException {
ObjectInputStream oos = null;
try {
oos = new ObjectInputStream(os);
Object o = oos.readObject();
return o;
} finally {
if (oos != null) oos.close();
}
}
}
Y ahora podemos guardar y recuperar nuestros objetos de una manera muy simple:
// Grabar
MiObjeto o = new MiObjeto();
IOTools.serialize(o, new FileOutputStream("objeto.dat");
// Recuperar
MiObjeto o = (MiObjeto)IOTools.deserialize(new FileInputStream("objeto.dat");
Sin embargo, este sistema tiene algunas complicaciones que para mi gusto, lo hacen muy poco interesante:
- El objeto serializado se guarda en un formato binario, por lo que es ilegible y no se puede editar externamente.
- Si se cambia el código de la clase serializada y se recompila la misma, es posible que no se pueda recuperar lo grabado.
¿Y cuál es la solución para todo esto? XStream. Tras mucho (bueno, no tanto) buscar, he dado con la solución definitiva:
- Persistencia basada en XML, o sea texto plano: legible y editable.
- No hace falta modificar tus objetos a serializar (ni siquiera tienen que implementar java.io.Serializable)
- No requiere mapeos (como otros motores de persitencia basado en XML, como Castor)
- Si recompilas tu objeto a escribir, o incluso si modificas sus atributos, el Xml grabado seguirá siendo válido (aunque puedes perder información si cambias el nombre de un atributo, siempre puedes editar el Xml!)
- Controla referencias circulares. Es decir, es posible serializar un objeto con un atributo que es una referencia a si mismo.
- Es fácil, sencillo, extensible, configurable, muy rápido y MOLA
¿Y como se usa? Pues asÃ:
XStream x = new XStream();
// Grabar
MiObjeto o = new MiObjeto();
x.toXML(o, new FileOutputStream("objeto.xml"));
// Recuperar
MiObjeto o = (MiObjeto) x.fromXML(new FileInputStream("objeto.xml"));
Más sencillo, imposible. Además, podemos crear nuestras propias implementaciones de los conversores de objeto/xml y xml/objeto para ciertas clases, podemos persistir colecciones de objetos en el que se escribe un Xml en disco por cada objeto, podemos hacer alias de clases y cambiar etiquetas enteras por atributos para mejorar la legibilidad.
En resumidas cuentas, una herramienta muy recomendable.
Más información en: http://xstream.codehaus.org