260 likes | 389 Views
Práctica III: Java RMI con Serialización y Activation Framework. Persistencia. Caso práctico: JINI Necesitamos que el servicio de impresión esté siempre conectado de manera que, si existe algún “crash” de la máquina, el servicio arranque automáticamente.
E N D
Práctica III: Java RMI con Serialización y Activation Framework
Persistencia • Caso práctico: JINI • Necesitamos que el servicio de impresión esté siempre conectado de manera que, si existe algún “crash” de la máquina, el servicio arranque automáticamente. • Por otra parte, el servicio de control de entrada no tiene por qué estar arrancado todo el rato; se espera que JINI lo pueda para y rearrancar “on demand”. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Serialization • Proceso de conversión de un conjunto de instancias referenciadas entre sí a un flujo lineal de bytes (byte stream) para que: • puedan enviarse por un socket, • puedan almacenarse en un fichero, • puedan ser manipulados como un stream más. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Opción 1: invocación remota Servidor - Cliente • Prestaciones • Vulnerable a fallos parciales • ¡¡¡Volvemos al problema de RPC y stateless servers!!! Sistemas Distribuidos - Nebrija - Justo Hidalgo
Opción 2: envío de copias de la instancia de C a S • Los dos objetos son independientes entre sí. • El mecanismo de copia ha de crear DEEP COPIES. • Si un objeto se envía dos veces en métodos remotos diferentes, son dos copias distintas (¡pensad en las DEEP COPIES!) Sistemas Distribuidos - Nebrija - Justo Hidalgo
Usos de la Serialización • Como mecanismo de persistencia: • se utiliza el stream “FileOutputStream” para almacenar objetos en ficheros. • Como mecanismo de copia: • se utiliza el ByteArrayOutputStream que se puede almacenar en memoria para después crear duplicados. • Como mecanismo de comunicación: • capturar o enviar el stream mediante sockets. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Cómo hacer que una clase sea Serializable • Ha de implementar la interfaz Serializable, • Asegurarse de que el estado local es serializado apropiadamente, • Asegurarse de que el estado de la superclase se serializa apropiadamente, • Sobrecargar equals() y hashCode(). Sistemas Distribuidos - Nebrija - Justo Hidalgo
Implementar interfaz Serializable • Obvio y fácil. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Estado local serializado correctamente (I) • Los atributos de una clase serializable han de ser o primitivos o serializables. public class ArrayList extends AbstractList implements List, Cloneable, Serializable { private Object elementData[]; private int size; … } • Si eso no se cumple: • Campos declarados como transient. • Implementar métodos writeObject/readObject. • Declaración de serialPersistentFields. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Estado local serializado correctamente (II): transient • Vamos, ignorar la variable al serializar. • Útil si la variable no afecta al estado del objeto. • Útil si la variable no es serializable, para evitar excepciones al serializar. public class ArrayList extends AbstractList implements List, Cloneable, Serializable { private transient Object elementData[]; private int size; … } Sistemas Distribuidos - Nebrija - Justo Hidalgo
Estado serializado (III): [write|read]Object • La variable no es serializable, pero QUEREMOS SERIALIZARLA. • Implementamos dos métodos: • private void writeObject(java.io.ObjectOutputStream out) throws IOException • private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException public class ArrayList extends AbstractList implements List, Cloneable, Serializable { private transient Object elementData[]; private int size; private synchronized void writeObject(java.io.ObjectOutputStream stream) throws java.io.IOException { stream.defaultWriteObject(); stream.writeInt(elementData.length); for(int i = 0; i < size; i++) stream.writeObject(elementData[i]); } } Sistemas Distribuidos - Nebrija - Justo Hidalgo
Estado serializado (IV):serialPersistentFields • Declaración explícita de qué variables serializar, mediante un atributo static final: private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(“size”, Integer.TYPE), …}; Sistemas Distribuidos - Nebrija - Justo Hidalgo
Superclase serializada adecuadamente • Si la superclase es Serializable, OK. • Si no, hay que almacenar su estado: • serialPersistentFields • writeObject/readObject. • ¿Qué pasa si la superclase no la conozco en detalle? • Además, las clases no serializables, para poder serlo, han de tener un constructor con cero argumentos (¡¡!!) REFACTORING Sistemas Distribuidos - Nebrija - Justo Hidalgo
Sobrecarga de equals() y hashCode() • Primero: • ByteArrayOutputStream memoryOutputStream = new ByteArrayOutputStream( ); • ObjectOutputStream serializer = new ObjectOutputStream(memoryOutputStream); • serializer.writeObject(serializableObject); • serializer.flush( ); • Después: • ByteArrayInputStream memoryInputStream = new ByteArrayInputStream(memoryOutputStream.toByteArray( )); • ObjectInputStream deserializer = new ObjectInputStream(memoryInputStream); • Object deepCopyOfOriginalObject = deserializer.readObject( ); • Y ahora... • serializableObject.equals(deepCopyOfOriginalObject) • public class Money extends ValueObject { • private int _cents; • ... • } • en este caso debería de devolver true, pero devuelve false • igual ocurre con hashCode, pues dos instancias iguales deben devolver el mismo hashCode. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Ejemplo 1: clases preserializables • Envío de objetos mediante sockets Sistemas Distribuidos - Nebrija - Justo Hidalgo
Ejemplo 2: utilización de read/writeObject • Se utiliza una matriz simétrica, por lo que optimizamos espacio modificando los métodos readObject y writeObject. • No hay superclases. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Ejemplo 3: superclase no serializable • La superclase necesita un constructor sin argumentos. • Los atributos de la superclase que no son serializados han de ser accesibles desde la superclase. Sistemas Distribuidos - Nebrija - Justo Hidalgo
Activation Framework • RMI Activation Framework. • Es un servicio que se ocupa del ciclo de vida de un objeto Java, que puede o no estar en memoria principal • Concepto CORBA: Objeto vs. Servant. Sistemas Distribuidos - Nebrija - Justo Hidalgo
AF: RMI Activation Daemon (rmid) • Es un proceso que asegura que los servicios “activables” están disponibles cuando se necesitan. • Los servicios “activables” se comunican con rmid para registrarse: devuelven una referencia remota pero sin implementación activa. • Rmid puede arrancar los servicios en la misma JVM o en una nueva. Sistemas Distribuidos - Nebrija - Justo Hidalgo
AF: RMI Activation Daemon (rmid): arquitectura del proceso • El servicio activable corre en un proceso hijo de rmid. • Si rmid cae, al tener un log, cuando sea rearrancado arrancará los servicios que tuviera activos. • Por tanto, un servicio ha de desrregistrarse explícitamente. Sistemas Distribuidos - Nebrija - Justo Hidalgo
AF: Creando un servicio activable • Interfaz Java: MyRemoteInterface • public interface MyRemoteInterface extends java.rmi.Remote • Como todos. • Clase de implementación: • public class ActivatableImplementation extends Activatable implements examples.activation.MyRemoteInterface • Ya no extiende UnicastRemoteObject. • Añade un ActivationId y un MarshalledObject (representación serializada del objeto) al constructor. Sistemas Distribuidos - Nebrija - Justo Hidalgo
AF: Creando un servicio activable • Creación de la clase “setup”: • Crea toda la información necesaria para la clase activable, sin que sea necesario instanciar el objeto remoto. Se lo pasa al rmid. • Crea un grupo de activación. • Crea una descripción de activación (clase, dónde está e información serializada que pueda necesitar -no ahora-. • Registra en rmid y en rmiregistry. Sistemas Distribuidos - Nebrija - Justo Hidalgo
AF: Compilación y ejecución • Compilar interfaces remotas, clases, etc. • Rmic • Arrancar rmiregistry. • Arrancar el activation daemon, rmid: • rmid -J-Dsun.rmi.activation.execPolicy=none • Setup: • java -Djava.security.policy=<path>/policy -Djava.rmi.server.codebase=file:///<path> examples.activation.Setup • Cliente • java -Djava.security.policy=<path>\policy examples.activation.Cliente <server> Sistemas Distribuidos - Nebrija - Justo Hidalgo
Bibliografía • Serialización: • http://www.oreilly.com/catalog/javarmi • Activation Framework: • http://java.sun.com/j2se/1.3/docs/guide/rmi/activation Sistemas Distribuidos - Nebrija - Justo Hidalgo