Curso práctico de Corba en GNU/Linux

Lo primero es recomendar al lector que sea un poco paciente al enfrentarse por primera vez al c�digo de un servidor de CORBA. Este c�digo siempre es id�ntico al 90% en todos los casos, por lo que su comprensi�n una vez permite trabajar con CORBA con mucha soltura en sucesivos desarrollos de servidores CORBA.

El servidor CORBA es el programa que se encarga de crear el objeto CORBA y registrarlo dentro del ORB.

Como vamos a ver gran parte del c�digo de este servidor es id�ntico al del cliente, en especial las partes de inicializaci�n del ORB y de uso del servidor de nombres. Sin embargo dentro del servidor CORBA vamos a ver un elemento que no aparec�a en el cliente: el adaptador de objetos. Recordar al lector que el adaptador de objetos es el que mantiene control sobre los objetos que est�n registrados del ORB y el se encarga de encaminar las peticiones de los clientes hacia los objetos CORBA, entre otras funciones.

Como ya comentamos en entregas anteriores CORBA 2.2 introdujo la gran novedad del POA (Adaptador de Objetos Portable), que sustituy� al BOA (Adaptador de Objetos B�sico) que ten�a muchos problemas a la hora de portar aplicaciones entre diferentes ORB en el lado del servidor.

Nos vamos a centrar en este ejemplo en POA al haber quedado BOA obsoleto a partir de CORBA 2.2, ha desaparecido del estandar. POA es un adaptador de objetos cuyo uso puede ser muy sencillo pero que ofrece muchas posibilidades de dise�o de la aplicaci�n CORBA, puediendo llegar a soportar dise�os muy complejos. Quiz�s en alguna futura entrega del curso se cubra POA en profundidad en un art�culo dedicado a �l.

Pasamos pues a ver el c�digo del servidor CORBA, dentro del cual se crea el objeto CORBA Calculator y se da de alta en el ORB. A partir de ese momento cualquier cliente podr� acceder al objeto CORBA.

// ============================================================
// = Ejemplo de servidor CORBA con JavaORB                  =
// ============================================================

// Servidor con POA

public class ServerPOA
{
  public static void main( String args[] )
  {
    // 1.
    // Inicializamos el ORB
    org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);

    // 2.
    // Resolvemos la referencia al RootPOA
    org.omg.CORBA.Object objPoa = null;
    org.omg.PortableServer.POA rootPOA = null;
    try
    {
      objPoa = orb.resolve_initial_references("RootPOA");
    }
    catch ( org.omg.CORBA.ORBPackage.InvalidName ex )
    {}

    // 3.
                // Hacemos un narrow de referencia de objeto a referencia POA
    rootPOA = org.omg.PortableServer.POAHelper.narrow(objPoa);

    // 4.
    // Instanciamos un objeto Calculator
    CalculatorPOAImpl calc = new CalculatorPOAImpl();

    try
    {
      // 5.
      // Activamos el servant dentro del ORB
      byte[] servantId = rootPOA.activate_object(calc);

      // 6.
      // Obtenemos la referencia al servant
      org.omg.CORBA.Object ref = rootPOA.id_to_reference(servantId);

      // 6.
      // Accedemos al NamingService
      org.omg.CORBA.Object obj = null;
      org.omg.CosNaming.NamingContext naming = null;
      try
      {
        obj = orb.resolve_initial_references("NamingService");
        System.out.println("Locallizado el NamingService");
        naming = org.omg.CosNaming.NamingContextHelper.narrow(obj);
        System.out.println("Narrow del NamingService");
      }
      catch ( org.omg.CORBA.ORBPackage.InvalidName name )
      {
        System.out.println("No se ha podido obtener el NamingService");
        System.exit(0);
      }

      if ( naming == null )
      {
        System.out.println("No se ha encontrado el NamingService");
        System.exit(0);
      }

      // 7.
      // Construccion del nombre del objeto Calculator
      org.omg.CosNaming.NameComponent [] name = new org.omg.CosNaming.NameComponent[1];
      name[0] = new org.omg.CosNaming.NameComponent();
      name[0].id = "Calculator";
      name[0].kind = "Example";

      try
      {
        naming.bind(name,ref);
      }
      catch ( org.omg.CosNaming.NamingContextPackage.NotFound ex )
      {
        System.out.println("Objeto no encontrado");
        System.exit(0);
      }
      catch ( org.omg.CosNaming.NamingContextPackage.AlreadyBound ex )
      {
        System.out.println("Ya hay un objeto con ese nombre");
        naming.unbind(name);
        System.exit(0);
      }
      catch ( org.omg.CosNaming.NamingContextPackage.InvalidName ex )
      {
        System.out.println("Nombre inv�lido");
        System.exit(0);
      }
      catch ( org.omg.CosNaming.NamingContextPackage.CannotProceed ex )
      {
        System.out.println("No se ha podido continuar");
        System.exit(0);
      }

      // 8.
      // Activamos el gestor de invocaciones del POA
      rootPOA.the_POAManager().activate();
      System.out.println("El servidor est� preparado...");
      // 9.
      // Nos quedamos a la espera de peticiones sobre Calculator
      orb.run();
    }
    catch ( java.lang.Exception ex )
    {
      System.out.println("Se ha capturado una excepci�n");
      ex.printStackTrace();
    }

  }
}

El paso 1 es id�ntico al del cliente. Se inicializa el ORB. En el paso 2 ya empezamos a trabajar con POA. El adapator de objetos POA siempre tiene un POA ra�z llamado RootPOA y que el ORB conoce. Los objetos dentro del ORB se registran dentro de un POA determinado, pudiendo cada POA tener pol�ticas de gesti�n de dichos objetos diferentes. Dentro del ORB pueden existir varios POAs organizados en una estructura jer�rquica en �rbol.

En el caso m�s sencillo utilizamos s�lo el RootPOA, que tiene unas pol�ticas de gesti�n predefinidas, y en �l registramos a todos nuestros objetos. Si nuestra arquitectura es m�s compleja habr� que utilizar diferentes POAs con caracter�sticas diferentes, aunque la programaci�n de dichos servidores se complica bastante m�s que cuando s�lo utilizamos un �nico POA.

En la figura 2 podemos observar el POA de nuestra aplicaci�n y un ejemplo de como podr�a ser una arquitectura de POAs m�s complejo

Figura 2: Arquitectura de POAs

Por lo tanto en el paso 2 obtenemos la referencia al objeto RootPOA gracias a la funci�n resolve_initial_references() del ORB. Como esta funci�n nos devuelve un objeto CORBA gen�rico en el paso 3 debemos de pasar este objeto a una referencia real a POA gracias al narrow() del POAHelper.

En el paso 4 es donde creamos el objeto CORBA CalculatorPOA. La implementaci�n de este objeto la veremos en el siguiente apartado, aunque ya adelantamos que es muy sencilla. En terminolog�a POA a la implementaci�n de una interfaz IDL, que es lo que hace CalculatorPOA implementando la interfaz Calculator, se la conoce como servant. En nuestro caso CalculatorPOA es un servant.

En el paso 5 registramos este servant dentro del RootPOA gracias a la funci�n activate_object() de la API de POA.

Al activar nuestro objeto dentro del POA del ORB del servidor, recibe un identificador que nos devuelve dicha funci�n y almacenamos en servantId. En el paso 6 transformamos este identificador en una referencia a objeto, es la misma informaci�n vista de otra forma, con el objetivo de introducir esta referencia al objeto dentro del servidor de nombres.

Lo siguiente que tenemos que hacer es registrar esta referencia al objeto Calculator dentro del servidor de nombres, ya que es all� a donde va a acudir el cliente a buscar la referencia al objeto.

Para ello en el paso 7 se accede al servidor de nombres, paso id�ntico al 2 del cliente. El paso 8 es tambi�n id�ntico al 3 del cliente, con la excepci�n de que aqu� en vez de ejecutar resolve() sobre el servidor de nombres ejecutamos bind(), es decir, aqui unimos dentro del servidor de nombres la referencia al objeto Calculator con el nombre ("Calculator","Example").

En el paso 9 activamos el Manager del RootPOA. Este manager es el que se encarga de recibir las peticiones sobre los objetos registrados en este POA y distribuirlas al servant adecuado, es decir, enviarla a la implementaci�n de la interfaz IDL adecuada. En nuestro caso si se recibe una invocaci�n para Calculator, el manager se la enviar�a a CalculatorImpl.

Por �ltimo en el paso 10 se invoca el m�todo orb.run() que cede el control de la ejecuci�n al ORB para que puede comenzar a recibir invocaciones del cliente. De este m�todo solo se vuelve en el caso de que el ORB finalice, bien por salida provocada o por muerte.

Recordar al lector que aunque le haya resultado en algun momento un poco compleja o tediosa la lectura de este apartado, una vez entendidos estos pasos son siempre igual en cualquier servidor CORBA, independientemente del lenguaje que se utilice y de lo complejo de la aplicaci�n. La �nica parte que se complicar�a algo m�s ser�a la de creaci�n de POAs y sus pol�ticas asociadas. Todo lo dem�s es id�ntico siempre.

En la figura 3 podemos observar el momento en el que se registra el objeto CORBA CalculatorImpl dentro del adaptador de objetos del ORB, momento a partir del cual es conocido dentro de CORBA y puede ser accedido por cualquier cliente remoto.

Figura 3: Registro de objeto CORBA

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR

SIGUIENTE ARTÍCULO