13.2 CAMBIOS DE VERSIONES

 

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