Asunto: Re: Enviar un objeto al canal de eventos
Fecha: Tue Dec 14 09:47:12 1999
De: Fernando Bellas Permuy <fer@cesat.es>
Jose Manuel Cantera Fonseca wrote:
>
> Creo que no hace falta serializar el objeto como string.
Cierto. Puedes insertar el array de bytes directamente en el any y
enviarlo. Ej.: (modelo push/push) el publicador ....
// Obtener el estado del mensaje a notificar. "msg" es una instancia
// de "DListMsg", una clase serializable que utilizo para este
ejemplo.
byte[] state = Serializator.toByteArray(msg);
// Crear un "any", e insertarle el estado.
org.omg.CORBA.Any message = orb.create_any();
StateHelper.insert(message, state);
try {
// Enviar el mensaje al canal de eventos (vía "push").
pushConsumer.push(message);
} catch (Exception exception) {
...
}
"State" se define en IDL como:
typedef sequence<octet> State;
En la clase PushConsumerImpl : (subscriptor) ...
public void push (org.omg.CORBA.Any msg) throws Disconnected
{
// Extraer el estado de la modificación a partir del "any".
byte[] state = StateHelper.extract(msg);
// Recuperar el mensaje (tipo de modificación) a partir del
// estado.
DListMsg myMsg = (DListMsg)(Serializator.fromByteArray(state));
// ...
}
La clase "Serializator" utiliza el API de serialización de Java para
serializar y deserializar objetos:
public class Serializator {
// Obtiene el estado (byte[]) a partir del objeto.
public static byte[] toByteArray (Object object)
{
try {
ByteArrayOutputStream byteStream =
new ByteArrayOutputStream();
ObjectOutputStream objectStream =
new ObjectOutputStream(byteStream);
objectStream.writeObject(object);
objectStream.flush();
return byteStream.toByteArray();
} catch (Exception exception) {
...
}
// Devuelve el objeto a partir su estado (byte[]).
public static Object fromByteArray (byte[] state)
{
try {
ByteArrayInputStream byteStream =
new ByteArrayInputStream(state);
ObjectInputStream objectStream =
new ObjectInputStream(byteStream);
return objectStream.readObject();
} catch (Exception exception) {
...
}
}
}
> >
> > No obstante, date cuenta que serializar objetos de un determinado
> > lenguaje de programación limita el uso, flexibilidad y compatibilidad de
> > tu programa con otras implementaciones en otros lenguajes de
> > programación.
> >
Si te interesa heretorgeneidad de lenguajes (posiblemente la razón por
la que utilizas CORBA), puedes consierdar varias alternativas:
1. Definir un struct CORBA (o similar) por cada objeto que desees pasar
en el canal de eventos. Tus clases podrían tener métodos del tipo:
toIDL y fromIDL
para obtener el estado de un objeto como un struct CORBA y para
recuperar su
estado, respectivamente. O variaciones de esta misma idea ...
2. Implementar un pequeño framework basado en los patrones de diseño
"Memento" y "Factory" (Gang of Four). Los objetos que quieras enviar
poque canal de
eventos podrían implementar un interfaz Java similar a:
public interface Storable {
public String toString ();
}
el método toString devuelve un String, que contiene el estado de la
clase como un string y un identificador de la clase (para luego poder
construir
una instancia).
Adicionalmente necesitas tener un gestor de objetos almacenables
(típicamente una clase utilidad). Ej.:
public StorageManager
private static java.util.Hashtable factories = new Hashtable;
public static Storable fromState (String state);
public static void registerFactory (String classId,
StorableFactory factory);
}
El método registerFactory permite asociar identificadores de
clase con su factoría correspondiente. StorableFactory podría tener
un aspecto
como este:
public interface StorableFactory {
public Storable createStorableObject (String state);
}
Por cada clase que necesites pasar en el canal de enventos, necesitas
implementar
la factoría correspondiente.
Podrías implementar la misma idea para otros lenguajes (ej.: C++). La
solución es interoperable dado que todo se envía como caracteres. Una
solución
"parecida" a este la empleamos hace tiempo en un proyecto con
CORBA/C++.
La ventaja de 1 es (fundamentalmente) que todo está definido en IDL, y
por tanto, evitas
hacer métodos que hagan marshalling/unmarshalling a parti de strings. Su
desventaja es que
obliga ha escribir ese struct por cada clase, lo que puede resultar
excesivo (ej.: si el
número de clases que quieres pasar por valor es grande, y el código lo
desarrollan personas
agenas al mundo CORBA).Este es el motivo por el que empleamos la segunda
solución en el
proyecto que te comento, en el que además el framework daba apoyo para
implementar
de manera sencilla los interfaces anteriores. Pero vaya, la solución que
emplees depende
de tu caso particular.
Fernando Bellas Permuy
Estudio de Ingeniería Telemática CESAT.
Almirante Francisco Moreno, 5, Planta Baja.
Ciudad Universitaria. 28040 Madrid.
Tel : +34-91-4590001
Fax : +34-91-4597555
E-mail : fer@cesat.es