La especificación de CORBA 2.3 define el soporte de ejecución ORB en forma de pseudo-objetos ORB, el objeto Object, y el objeto de localidad restringida POA. Los pseudo-objetos proporcionan interfaces de igual forma que los objetos CORBA normales, pero no heredan de CORBA::Object, y las operaciones sobre dichas interfaces se implementan en librerías y no se pueden utilizar en invocaciones remotas, es decir, solamente pueden usarse en procesos locales. La definición de los pseudo-objetos se marca con las siglas PIDL en los comentarios IDL.
Los objetos POA son de localidad restringida, lo cual significa que se establece la correspondencia entre la interfaz y el lenguaje destino de acuerdo con las normas establecidas por el lenguaje, pero las referencias a objetos no pueden "externalizarse", bien ser convirtiéndolas en cadena de caracteres, o pasándolas en invocaciones remotas. Los objetos solamente pueden utilizarse en procesos locales.
A continuación vamos a ver cuál es la correspondencia de dichas interfaces con su implementación Java.
La interfaz ORB proporciona operaciones para soportar aplicaciones CORBA. Incluye
la conversión de referencias a objetos a Strings
, y viceversa,
y la resolución de referencias iniciales. Una de estas referencias iniciales
es la referencia a POA, necesaria par apermitir que los objetos estén
disponibles para ser invocados.
La interfaz ORB se implementa en Java de la siguiente forma:
package orb.omg.CORBA; public abstract class ORB {...}
Inicialización ORB. Antes de que una aplicación pueda usar las operaciones del interfaz ORB necesita una referencia a un pseudo-objeto ORB. Los ORBs en applets Java requieren diferentes inicializaciones para que las aplicaciones Java "se salten" las restricciones de seguridad. Dicha inicialización se realiza llamando a métodos estáticos de la clase ORB.
Operación IDL: ORB ORB_init(inout arg_list argv, in ORBid orb_identifier); Método Java por defecto: public static ORB init(); Método Java para aplicaciones: public static ORB init(String [] args, Properties props); Método Java para applets: public static ORB init (Applet app, Properties props);
El método por defecto init()
devuelve una referencia a
un único ORB. Los otros dos métodos se han diseñado específicamente
para usarlos en aplicaciones Java y applets, respectivamente. En ambos
casos se pueden pasar como parámetros una lista de propiedades. ORB reconocerá
cómo interpretar dos propiedades estándar:
org.omg.CORBA.ORBClass:
que contiene el nombre de una implementación
de clase de ORB.org.omg.CORBA.ORBSingletonClass:
que contiene el nombre de
una implementación ORB que actúa como una TypeCode factory.
Los typecodes pueden representar información de tipo sobre cualquier tipo IDL. Muchos tipos de datos IDL son estructurados y contienen otros tipos dentro de ellos. Estos son representados como TypeCodes anidados.
Conversión de referencias a objetos en Strings. Las referencias a objetos pueden ser externalizadas convirtiéndolas en strings. Una referencia a objeto convertida en string puede ser almacenada convenientemente en un fichero o "enviada" utilizando algún otro mecanismo que no sea CORBA, como por ejemplo e-mail. También puede ser reconvertida en una referencia real al mismo objeto. Las dos operaciones para convertir a String y viceversa una referncia a objeto son:
Operación IDL: string object_to_string(in CORBA::Object obj); Método Java: String object_to_string(org.omg.CORBa.Object obj); Operación IDL: object string_to_object(in string obj); Método Java: orb.omg.CORBA.Object string_to_object(String str);
La operación object_to_string()
convierte un IOR en un
String. La operación string_to_object()
realiza la
operación contraria.
Obtención de una referencia POA. ORB proporciona una operación para recuperar una referencia a la raíz de POA, necesaria para conseguir que los objetos estén disponibles para invocaciones remotas.
Operación IDL: CORBA::Object resolve_initial_references(in string name); Método Java: public abstract org.omg.CORBA.Object resolve_initial_references(String name);
Asumiendo que el pseudo-objeto ORB ha sido inicializado correctamente, una ferencia a la raiz POA podría obtenerse de la siguiente forma:
orb.omg.CORBA.Object obj= orb.resolve_initial_references("RootPOA"); org.omg.PortableServer.POA rootPOA = org.omg.PortableServer.POAHelper.narrow(obj);
Se debe notar que la raíz POA, al igual que cualquier POA de nueva creación, es inicialmente un estado contenedor y no procesará peticiones de entrada. Para habilitar el proceso de peticiones es necesario realizar una llamada activate() sobre su POAManager:
rootPOA.the_Manager().activate();
La interfaz POA se utiliza para crear referencias a objetos y hacer que dichas
referencias estén disponibles para invocaciones remotas. La interfaz
POA se define en el módulo PortableServer
.
IDL interfaz: module PortableServer { interface POA {//locality-constrained; Clase Java: package org.omg.PortableServer; public interface POA {...}
Creación de referencias. La interfaz POA proporciona dos operaciones para crear de forma explícita nuevas referencias a objetos.
Operaciones IDL: Object create_reference(in RepositoryID intf); Object create_reference_with_id(in ObjectID oid, in RepositoryID intf); Métodos Java: org.omg.CORBA.Object create_reference(String intf); org.omg.CORBA.Object create_reference_with_id(byte [] oid, String intf);
En ambos casos, el tipo del objeto debe especificarse en forma de RepositoryID.
Las nuevas referencias creadas no se asocian con ningún servant
todavía, lo cual significa que no son activadas. Mientras que el objeto
abstracto existe y su referencia puede ser exportada usando object_to_string()
o via el servicio de nombres, todavía es necesario asociar el objeto
con un servant.
Activación y desactivación implícita.
En muchos casos, la forma más conveniente de crear una referencia a objeto
consiste en activarla al mismo tiempo que la referencia es creada, en lugar
de llamar a una de las operaciones create_reference
y posteriormente
activar explícitamente el objeto llamando a activate_object()
o activate_object_with_id()
.
Operación IDL: Object servant_to_reference(in Servant servant); Método Java: org.omg.CORBA.Object servant_to_reference(Servant s);
Usando esta operación, una única llamada es suficiente:
MyServerImpl servant= new MyServerImpl(); org.omg.CORBA.Object obj= poa.servant_to_reference(servant);
Mediante la llamada a servant_to_reference()
se puede asociar
el objeto con el servant y simultáneamente crear una entrada en
su Active Object Map. A esto se le denomina activación implícita
y requiere las políticas IMPLICIT_ACTIVATION
y RETAIN
.
El servant especificado no debe estar actualmente activo o el POA debe
tener también fijada la política MULTIPLE_ID
. Se
debe notar que para que POA sea capaz de asignar un ID a un objeto para una
nueva referencia, la política de asingación de ID debe tener un
valor de SYSTEM_ID
.
Después de que un programa servidor haya inicializado su ORB, obtenido
una referencia a la raiz POA, y activar su objetos, el hijo de control principal
del servidor usualmente se queda esperando para esperar peticiones y procesarlas.
Esto se realiza normalmente llamando al método run()
de
ORB.
Un ejemplo de servidor sencillo podría ser éste:
public class Server { public static void main (String[] args) { //inicializar el ORB org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); try { //obtener la raiz POA org.omg.PortableServer.POA poa= org.omg.PortableServer.POAHelper.narrow( orb.resolve_initial_references("RootPOA")); //activar POA poa.the_POAManager().activate(); //activar de forma implícita un objeto orb.omg.CORB.Object o = poa.servant_to_reference(new myImpl()); //esperar peticiones orb.run(); } catch (Exception e) { e.printStackTrace(); } } }
Los objetos pueden desactivarse explícitamente mediante una llamada
a deactivate_object()
si POA tiene la política RETAIN
.
Los objetos se desactivan de forma implícita de varias formas: destruyendo
su POA con la operación destroy()
, desactivando su POA a
través de la operación deactivate()
de su POAManager,
o "cerrando" el ORB. En este último caso, la interfaz ORB proporciona
dos operaciones:
Operaciones IDL: void shutdown (in boolean wait_for_completion); void destroy(); Métodos Java: void shutdown(boolean wait_for_completionI; void destroy();
Mediante una llamada a shutdown()
sobre un pseudo-objeto ORB se
consigue que el ORB detenga el procesamiento de peticiones y se prepare para
su "destrucción". También se "destruyen" todos
su adaptadores de objetos. El parámetro Boolean indica si esta operación
debe retornar inmediatamente o solamente cuando el ORB se ha cerrado completamente.
Después de que ORB se haya cerrado, los únicos métodos
que pueden llamarse son operaciones de gestión de referencias a objetos.
El método destroy()
libera todos los recursos de un ORB.
Si el ORB no se ha cerrado cuando se llama a destroy()
, este método
iniciará el cierre.
La interfaz de invocación dinámica (DII: Dynamic Invocation Interface) permite a los clientes invocar operaciones sobre objetos sin conocimiento en tiempo de compilación sobre su tipo IDL, es decir, sin el código stub generado por el compilador IDL. Un cliente crea una petición (Request), que es el equivalente dinámico de una operación. Una Request contiene una referencia a objeto, un nombre de operación, e información de tipo y valores para los argumentos que son proporcionados por el cliente. Una vez inicializado con todos estos parámetros, una Request puede ser invocada, y tiene la misma semántica que la invocación de una operación usando código stub.
Request es una interfaz pseudo-IDL que proporciona las operaciones para inicializar una invocación de una petición de invocación de operación e invoca de forma dinámica una operación sobre un objeto. Las peticiones son creadas por el ORB.
Los métodos Java usados para crear una Request son:
Request _create_request( Context ctx, String operation, NVList arg_list, NamedValue result ); Request _creat_request ( Context ctx, String operation, NVList arg_list, NamedValue result, ExceptionLIst exclist, ContextList ctxlist );
Los dos métodos son idénticos, excepto que la segunda versión añade alguna información extra.
ctx
especifica el contexto de ejecución de la petición. Un
objeto context contiene una lista de propiedades consistentes en pares
de nombres y valoresoperation
determina el nombre de la operación a ser
invocadaarg_list
proporciona los argumentos para dicha operaciónresult
es un NamedValue cuyo valor está inicializado
para contener únicamente el tipo esperado como resultado de la operaciónexclist
es una lista de TypeCodes que indica las excepciones
del usuario que se declaran en las cláusulas raise de la operaciónctxlist
es una lista de Strings que se corresponden
con los nombres en la cláusula context de una declaración
de operaciónEl nuevo objeto creado Request
se devuelve como resultado del
método Java. Hay una operación adicional para crear objetos Request
parcialmente inicializados:
Request _request (String operation) throws SystemException
La pseudo-interfaz Request se corresponde con la clase abstracta Java
org.omg.CORBA.Request
.
El DII proporciona un mecanismo para invocar operaciones desde un cliente sin
conocimiento en tiempo de compilación sobre la interfaz. La Dynamic
Skeleton Interface (DSI) proporciona un mecanismo similar en el lado
del servidor. Permite al ORB invocar una implementación de un objeto
sin conocimiento en tiempo de compilación sobre la interfaz, es decir,
sin una clase skeleton. Para una implementación de objeto, las
llamadas a través de un skeleton generadas por un compilador y
las DSI no son distinguibles. La idea subyacente a DSI es invocar todas las
implementaciones de objetos a través de la misma operación general.
Esto se especifica en la clase abstracta DynamicImplementation
que contiene una operación, llamada por el ORB, para transportar la petición
original al servidor. Esta clase presenta un pseudo-objeto de tipo ServerRequest
para permitir al servidor acceder a la información sobre la operación
que está siendo invocada y sus argumentos. También usa referencias
a los contenidos de dicho objeto par devolver los resultados de la invocación.