Hola a todos, vamos a ver qué ocurre
cuando cambiamos de versión el programa que se encarga de serializar objeto,
cuando nos referimos a cambiar de versión nos estamos refiriendo a actualizar
el programa, mejorarlo, modificar, etc..
Conflicto
versiones serialización
Supongamos que tenemos un emisor y un
receptor. El emisor quiere enviar por la red un objeto que se encuentra dentro
de un programa Java al receptor, esto es uno de los objetivos de la
serialización el poder enviar objetos Java a través de la red. Si queremos que
esto sea posible tanto el emisor que se encarga de serializar el objeto como el
receptor que va a leer el objeto serializado que le llega por la red deben
tener la misma versión del programa Java.
Cuando nosotros creamos un programa
Java aunque nosotros no lo veamos este programa tiene una huella que podemos
asemejarlo a un número identificativo único para este programa Java, este
número identificativo o huella se denomina SHA
lo que se denomina la huella del programa. Esta huella la crea el compilador
Java realizando cálculos complejos en función de las clases, subclases,
métodos, etc., que tiene una clase, el compilador analiza cómo está construida
esa clase y en función de cómo está construida genera esa huella, esta huella
consiste en una sucesión de bytes que se denomina serialVersionUID.
En resumen, si el emisor quiere enviar
un objeto a través de la red al receptor ambos tienen que tener una copia
idéntica del programa Java con el mismo serialVersionUID.
Si esto es así el emisor envía el objeto al receptor sin ningún problema. Ahora
bien, en el mundo del software no hay día que se actualicen las aplicaciones
eso lo podemos ver casi a diario con las actualizaciones del sistema operativo
de nuestro equipo, en los móviles no hay día que no se actualicen tres o cuatro
aplicaciones, esto puede llegar a ser un problema a la hora de serializar los
objetos, por ejemplo, si el programa cambia añadimos nuevos métodos, cambiamos
el nombre de la clase, etc., si este cambio que se ha producido en el programa
no lo distribuimos a todos los receptores que van a recibir un objeto
serializado se van a encontrar con un problema. ¿El motivo? Cada vez que el
programa serializado tiene alguna modificación también cambia la huella, el serialVersionUID. Con lo cual si el
programa del emisor no es exactamente igual que el del receptor quiere decir
que cada programa va a tener un serialVersionUID
diferente generado automáticamente por el compilador de Java, en este caso el
emisor enviará el objeto serializado y el receptor no lo podrá leer.
Vamos a ver esto con el ejemplo del apartado anterior en el cual serializaremos el objeto pero después de serializar el objeto vamos a cambiar algo en el programa e intentaremos leer el archivo serializado para ver que si se ha modificado algo no es posible. Recordamos el ejemplo anterior que lo que hacía era escribir un fichero y a la misma vez leerlo, las tres líneas de código que se encargan de serializar el objeto son las siguientes:
El archivo se guarda en la siguiente ruta:
En la carpeta serialización no hay nada:
Luego las líneas que leen este archivo:
Si ejecutamos el programa, se nos genera el archivo dentro de la carpeta serialización y a la misma vez nos muestra el contenido en la consola de Java porque así lo tenemos programado:
Supongamos que somos el receptor y que
necesitamos leer este objeto, este fichero, comentamos las líneas encargadas de
serializar el objeto:
//ObjectOutputStream
escribiendo_fichero = new ObjectOutputStream(new
FileOutputStream("C:/Users/usuario/Desktop/serializacion/empleado.txt"));
//escribiendo_fichero.writeObject(personal);
//escribiendo_fichero.close();
Si ejecutamos:
Podemos leer perfectamente el fichero
porque ya está serializado.
Vamos a probar otra cosa, volvemos a
descomentar las líneas comentadas, borramos el fichero que se ha generado en la
carpeta serialización, supongamos que somos el emisor pero antes de serializar
el programa vamos a hacer un cambio, por ejemplo, la variable sueldo la vamos a modificar por sueldos, ejecutamos el programa
comprobamos que funciona correctamente, se ha generado de nuevo el fichero y se
lee por consola.
Supongamos que ahora somos el receptor, éste no ha recibido la actualización del programa, comentamos de nuevo las tres líneas que se encargan de serializar el objeto y volvemos a modificar la variable sueldos por sueldo, como estaba en un principio. Si ejecutamos de nuevo:
Nos muestra un error indicando que hay
una incompatibilidad ya que el serialVersionUID
es diferente y el programa no es capaz de leer el objeto serializado.
¿Cuál
sería la solución?
La solución pasa por declarar nosotros
mismos en nuestro programa el serialVersionUID
no permitir que el compilador Java genere automáticamente este SHA. Esto se
hace creando una constante de clase tipo long y estática:
private static final long serialVersionUID =
1L;
Esto implica que tanto el programa del
emisor como el programa del receptor tienen declarado en cualquier punto del
código esta constante de clase da igual que el programa del emisor cambie o se
actualice y no se haya informado al receptor de estas modificaciones porque la
huella no es generada automáticamente y no cambia al modificar algo del
programa, sino, que la huella sigue siendo la misma para ambas partes tanto
para el emisor como el receptor.
Para declarar esta constante de clase hay que fijarnos primero en algunas advertencias que tienen algunas clases cuando las creamos:
Si dejamos el ratón sobre esta advertencia nos aparece el siguiente aviso:
Nos indica que no hemos declarado esta
constante de clase estas advertencias suelen aparecer en clases que pueden ser serializadas
y ser susceptibles de ser cambiadas.
Si nos situamos sobre la palabra clase que esta subrayada en amarillo nos aparece el siguiente recuadro:
Podemos hacer que Eclipse nos añada
por defecto la constante de clase o que se genere esta constante. La diferencia
entre una y otra, la primera se añade la constante de clase, sin más. La segunda
se genera pero con el valor que el compilador Java le asigna automáticamente.
Vamos a verlo mediante la práctica
añadimos la constante por defecto:
class Empleado implements Serializable{
/**
*
*/
private
static final
long serialVersionUID
= 1L;
Esto lo tendríamos que hacer en todas
las clases que aparece está advertencia en el programa, como ya se ha comentado
ante cualquier modificación del programa aunque el receptor no le llegue esa
modificación podrá leerlo.
Si pulsamos para que nos lo genere con
el código:
class Empleado
implements Serializable{
/**
*
*/
private
static final
long serialVersionUID
= -8955202801287243683L;
Nos genera automáticamente el código
que le asigna el compilador, vamos a quedarnos con esta numeración, vamos a
borrar la constante y hacemos algunos cambios en la aplicación, por ejemplo,
modificamos de nuevo la variable sueldo
por sueldos, si volvemos a añadir
esta constante para que nos genere la numeración automática:
class Empleado implements Serializable{
/**
*
*/
private
static final
long serialVersionUID
= 3109986469893388233L;
Observamos que la numeración es
diferente, asigna una numeración en función de los cambios que hemos realizado
en el programa.
De forma que al haber serializado la
clase y el haber hecho cambios el receptor al ejecutar el objeto podrá leerlo
sin errores.
Hasta aquí el bloque de la
Serialización os espero en el próximo bloque. Hasta pronto!
13.1 TRANSFIRIENDO OBJETOS <<
>> 14.1 CLASE FILE I
No hay comentarios:
Publicar un comentario