RMI o RMI IIOP?

In [INT2] si è visto come l'integrazione Object/RPC implichi l'invocazione RPC dei metodi degli oggetti distribuiti (EJB, CORBA, DCOM, …).

Si è visto come comunicare con l'EJB Facade (installato sull'Application Server JBoss) mediante il protocollo JNP e di come l'EJB Facade comunichi a sua volta con l'EJB Calculator (installato su Weblogic) mediante il protocollo T3.

Entrambi sono protocolli proprietari che offrono vantaggi in termini di prestazioni. Per utilizzarli bisogna referenziare gli opportuni jar: per T3 è necessario il weblogic.jar e per JNP i jar jboss.jar, jboss-j2ee.jar e jnpserver.jar.

RMI

RMI è un insieme di API potente e semplice, che permette di sviluppare applicazioni distribuite (vedere [MOKARMI-1, MOKARMI-2, …]).

Nell'ottica di questo articolo bisogna tenere presente che oggetti che utilizzano l'ORB di RMI potranno colloquiare solo con altri oggetti che utilizzino il medesimo ORB.

CORBA

Un'altra soluzione di sviluppo di architetture distribuite ad oggetti è CORBA.

CORBA ha una connotazione completamente opposta rispetto a RMI: maggiore interoperabilità pagata al prezzo di una maggiore complessità (vedere [MOKA_IIOP-3]). Con CORBA un'applicazione client Java può interagire con una serie di oggetti remoti scritti in altri linguaggi (C++, C, Delphi, Java o altri per i quali sia disponibile un mapping IDL) e viceversa. L'IDL (Interface Definition Language) è il metalinguaggio standard del mondo CORBA usato per descrivere le interfacce degli oggetti remoti e le strutture dati di scambio.

Mentre il "contratto" tra client e server in Corba è definito tramite un'interfaccia IDL, in RMI è "stipulato" mediante un'interfaccia Java. Questo implica che per usare RMI non occorre conoscere IDL perché l'unico linguaggio di sviluppo è esclusivamente Java. Fondamentalmente RMI è una tecnologia semplice ma chiusa (sia il client che il server devono essere scritti esclusivamente in Java) e quindi non è in grado di comunicare con applicazioni distribuite scritte in linguaggi diversi. Esportare EJB con protocolli RMI porta vantaggi in termini di prestazioni ma preclude ogni strada all'interoperabilità con altre tecnologie.

Se ad esempio un client CORBA C++ avesse bisogno del servizio di calcolo della lunghezza della stringa non potrebbe usufruirne non essendo in grado di utilizzare il protocollo T3 o JNP.

Il discorso è valido anche al contrario: se esistono servizi sviluppati in CORBA un client Java non è in grado di invocarli né con RMI, né con JNP e neanche con T3.

Complicando lo scenario dello scorso articolo potremmo introdurre un'applicazione CORBA che ha bisogno del servizio di calcolo della lunghezza della stringa (l'EJB Calculator).

Il nuovo scenario diventa il seguente:

Figura 1 - Nuovo possibile scenario d'integrazione
Figura 1 - Nuovo possibile scenario d'integrazione

In questo scenario bisogna permettere l'invocazione dell'EJB mediante protocollo IIOP.

IIOP

La specifica CORBA introduce un protocollo GIOP (General Inter-ORB Protocol) che definisce il formato dei messaggi e la rappresentazione dei dati per tutte le comunicazioni tra oggetti distribuiti su uno stesso ORB o su ORB di produttori differenti. GIOP si appoggia a sua volta ad un qualunque protocollo di trasporto, purché orientato alla connessione, per portare a destinazione i suoi messaggi.

Una particolare implementazione del protocollo GIOP, chiamata IIOP (Internet Inter-ORB Protocol), si avvale del protocollo TCP/IP per la realizzazione dello strato di trasporto dei messaggi tra oggetti remoti.

IIOP quindi è una sorta di "collante" che si appoggia su TCP/IP tra gli oggetti distribuiti su ORB diversi tra loro.

RMI-IIOP

RMI-IIOP è stato sviluppato da Sun e IBM che hanno collaborato con l'OMG per sviluppare una nuova versione di RMI in grado di comunicare non solo attraverso il protocollo proprietario Sun JRMP, ma anche con il protocollo IIOP.

Tramite l'utilizzo di RMI-IIOP è possibile "gettare un ponte" tra RMI e CORBA.

Vediamo quindi come esporre un EJB al fine di essere invocabile mediante protocollo IIOP.

Riprendendo l'esempio del client dell'EJB Calculator dello scorso articolo:

public class CalculatorTestClient {
  . . . . .
  public void test(String jndiName) {
    try {
      Context ctx = new InitialContext();
      //look up jndi name
      Object ref = ctx.lookup(jndiName);
      Object obj = PortableRemoteObject.narrow(ref, CalculatorHome.class);
      CalculatorHome home = (CalculatorHome) obj;
      Calculator calculator = home.create();
      System.out.println("Risultato: " +
        calculator.getStringLength("Ciao a tutti!"));
      …
    }
  }
}

Per esporre un EJB mediante IIOP nel caso di Weblogic, bisogna specificare il flag -iiop come opzione dell'utility weblogic.ejbc (l'utility Bea che permette di compilare ed effettuare il deploy degli EJB). In questo modo vengono generati gli stub per il protocollo IIOP e non per T3.

Il client può quindi invocare l'EJB mediante IIOP specificando le seguenti proprietà JNDI:

  • java.naming.factory.initial= com.sun.jndi.cosnaming.CNCtxFactory

- `java.naming.provider.url= corbaloc::

<<SERVER>>

:7001` (dove con `

<<SERVER>>

` si indica il nome o l'indirizzo IP del Server)

  • java.naming.provider.url= corbaloc::<<SERVER>>:7001 (dove con <<SERVER>> si indica il nome o l'indirizzo IP del Server)

A partire dalla versione 3 è possibile esportare un EJB in IIOP anche con JBoss che integra l'ORB di JacORB (vedere [JACORB]).

Con la 3.0.x bisogna specificare nel file DD proprietario il tag <configuration-name> specificando come valore IIOP Stateless SessionBean.

<session>
  <ejb-name>CalculatorBean</ejb-name>
  <jndi-name>MokaCalculator</jndi-name>
  <configuration-name>IIOP Stateless SessionBean</configuration-name>
</session>

Con la versione 3.2.x invece bisogna specificare l'attributo <invoker-proxy-binding-name>.

<session>
  <ejb-name> CalculatorBean </ejb-name>
  <jndi-name> MokaCalculator </jndi-name>
  <configuration-name>Standard Stateless SessionBean</configuration-name>
  <invoker-bindings>
    <invoker>
      <invoker-proxy-binding-name>iiop</invoker-proxy-binding-name>
    </invoker>
  </invoker-bindings>
</session>

Il client può quindi invocare l'EJB mediante IIOP specificando le seguenti proprietà JNDI:

  • java.naming.factory.initial= com.sun.jndi.cosnaming.CNCtxFactory

- `java.naming.provider.url= corbaloc::

<<SERVER>>

:3528/JBoss/Naming/root`

  • java.naming.provider.url= corbaloc::<<SERVER>>:3528/JBoss/Naming/root

Di default il client utilizza l'ORB di SUN.

È possibile fare in modo che il client utilizzi un diverso ORB mediante le proprietà org.omg.CORBA.ORBClass e org.omg.CORBA.ORBSingletonClass.

Ad esempio per utilizzare l'ORB di JacORB (sempre a parità di bytecode!) si deve includere nel classpath il jar di JacORB e specificare le seguenti proprietà:

  • java.naming.factory.initial= com.sun.jndi.cosnaming.CNCtxFactory

- `java.naming.provider.url= corbaloc::

<<SERVER>>

:3528/JBoss/Naming/root`

  • java.naming.provider.url= corbaloc::<<SERVER>>:3528/JBoss/Naming/root
  • -Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB
  • -Dorg.omg.CORBA.ORBSingletonClass=org.jacorb.orb.ORBSingleton

È inoltre necessario configurare il Security Manager sul client specificando le proprietà di sicurezza java.security.manager e java.security.policy al fine di permettere al network classloader lo scaricamento degli stub (di default il network classloader è disabilitato causando un ClassCastException con il PortableRemoteObject.narrow()).

Il file di policy usato per gli esempi non pone nessun vincolo di sicurezza per semplicità.

// Standard extensions get all permissions by default
grant codeBase "file:${java.home}/lib/ext/-" {
  permission java.security.AllPermission;
};
// default permissions granted to all domains
grant {
  permission java.security.AllPermission;
};

Ora vediamo i benefici che derivano dalla scelta di aver esportato il nostro oggetto remoto attraverso un protocollo interoperabile quale IIOP. Si vuole realizzare un semplice client CORBA scritto in linguaggio C++ che comunichi con l'EJB Calculator installato su JBoss.

Per fare questo verrà utilizzato l'implementazione CORBA Open Source chiamata MICO (vedere [MICO]).

Si è scelto MICO come implementazione di CORBA/C++, sia per la sua semplicità che per il fatto che è liberamente disponibile per una grande varietà di piattaforme software/hardware.

Il nostro scenario di integrazione presenta rispetto ad una applicazione "pure Corba" la seguente "singolarità": di norma infatti, il punto di partenza di una qualunque applicazione Corba è la definizione in linguaggio IDL delle interfacce degli oggetti remoti che vengono esposti attraverso CORBA. Tuttavia nel nostro caso, già disponiamo delle interfacce dell'oggetto remoto EJB Calculator, precisamente si tratta della Home Interface e della Remote Interface definite (in linguaggio Java) per il nostro EJB. La prima cosa da fare sarà quindi trasformare queste definizioni di interfacce Java nelle corrispondenti definizioni IDL che useremo per realizzare il nostro client Corba C++. Tale trasformazione si basa su una recente aggiunta alle specifiche Corba che stabilisce appunto la mappatura java-to-idl necessaria per tradurre le specifiche degli oggetti remoti del mondo Java (RMI, EJB) nelle equivalenti interfacce IDL.

Vediamo in dettaglio la sequenza delle operazioni necessarie per la realizzazione del Client C++:

  • si parte dai files .class delle interfacce Home e Remote del nostro Calculator EJB
  • questi file .class vengono dati in ingresso ad un compilatore java-to-idl, come ad esempio l'rmic (disponibile con il JDK) avviato con l'opzione -idl.
rmic -idl -noValueMethods -classpath ${J2EE_JAR}:. -d . \
  it.mokabyte.eai.my.ejb.Calculator it.mokabyte.eai.my.ejb.CalculatorHome
  • si ottengono così numerosi files idl, che contengono oltre alle interfacce corrispondenti alla home e remote interface dell'EJB, anche le definizioni IDL di alcuni tipi di dati fondamentali definiti in java.lang, come Throwable ed Exception, nonché di alcune interfacce fondamentali definite in javax.ejb, come ad esempio EJBObject.
  • si utilizza il compilatore idl-to-c++ fornito con MICO per compilare tutti i files IDL suddetti
$MICO_HOME/idl/idl -I. -I${MICO_HOME}/include/mico -DprimaryKey=_primaryKey \
  it/mokabyte/eai/my/ejb/Calculator.idl
$MICO_HOME/idl/idl -I. -I${MICO_HOME}/include/mico -DprimaryKey=_primaryKey \
  it/mokabyte/eai/my/ejb/CalculatorHome.idl
...
  • i files oggetto ottenuti dalla compilazione si linkano insieme unitamente ad una semplice funzione main come la seguente:
//Code Example: mainClient.cc
#include <fstream>

#include <unistd.h>
#include <stdlib.h>

// Inclusione dei file generate dall'IDL
#include <it/mokabyte/eai/my/ejb/Calculator.h>
#include <it/mokabyte/eai/my/ejb/CalculatorHome.h>

using namespace std;

void run(CORBA::ORB_ptr orb, const char* home_url)
{
  // Look up dell'EJB Home specificato dal corbaname URL
  CORBA::Object_var home_obj = orb->string_to_object(home_url);

  assert(!CORBA::is_nil(home_obj));

  // effettuo la narrow
  it::mokabyte::eai::my::ejb::CalculatorHome_var home =
    it::mokabyte::eai::my::ejb::CalculatorHome::_narrow(home_obj.in());

  assert(!CORBA::is_nil(home));

  // ottengo il remote reference
  it::mokabyte::eai::my::ejb::Calculator_var calc = home->create();

  CORBA::String_var home_ior = orb->object_to_string(calc);
  // stampo lo IOR
  cout << "Calculator IOR is: " << home_ior << endl;

  CORBA::WStringValue* msg1 = new CORBA::WStringValue(L"Hello CORBA World");

  // invoco il metodo remoto
  wcout << L"Lunghezza del messaggio: " << msg1->_boxed_in() << L" = " <<
    calc->getStringLength(msg1) << endl;

  // NOTA: Per interoperare con le stringhe Java (contenenti
  // caratteri a 16 bit) è necessario utilizzare anche in C++
  // le stringhe Wide. Si noti inoltre che per stamparle bisogna utilizzare lo
  // stream wcout anziché cout.

  calc->remove();
}

// funzione main
int main(int argc, char* argv[])
{
  int exit_code = 0;
  CORBA::ORB_var orb;

  try {
    // Inizializzo l'ORB
    orb = CORBA::ORB_init(argc, argv);
    run(orb, argv[1]);
  }
  catch(const CORBA::Exception& ex) {
    ….
  }
  return exit_code;
}

CORBA Servant C++

Fino ad ora si è analizzato come è possibile interrogare EJB mediante il protocollo IIOP sviluppando sia client Java RMI-IIOP che CORBA C++.

Analizziamo adesso il caso duale, cioè supponiamo che il servizio di calcolo della lunghezza di una stringa, precedentemente esposto con un EJB (CalculatorBean) sia disponibile mediante un Servant CORBA scritto in C++.

Figura 2 - Servizio esposto mediante Server CORBA C++
Figura 2 - Servizio esposto mediante Server CORBA C++

Il vantaggio offerto dall'architettura CORBA si manifesta infatti nella possibilità di far interoperare programmi realizzati in linguaggi di programmazione diversi su piattaforme eterogenee. Uno scenario di questo tipo non rappresenta affatto un puro esercizio accademico, ma viene incontro a necessità molto sentite nel mondo aziendale.

Alcuni motivi che inducono ad utilizzare un approccio multilinguaggio sono i seguenti:

  • facilmente si incontra il caso in cui una società disponga già 'in casa' di alcune librerie scritte in C/C++, già abbondantemente testate ed impiegate all'interno di sistemi esistenti, e non si abbia nessuna intenzione di riscrivere (testare nuovamente!) questo codice in Java
  • è possibile che ad utilizzare linguaggi diversi da Java siano altri fornitori o partner che per vari motivi realizzano in C++ dei sottosistemi che è necessario integrare col proprio sistema
  • è possibile realizzare in C/C++ alcune parti del proprio sistema che prevedano una elaborazione computazionalmente molto intensiva

Negli esempi allegati è disponibile il "gemello" del Servant C++ scritto in linguaggio Java per coloro che non sono pratici di C++ o che semplicemente sono interessati al lato client del nostro scenario di integrazione (magari perché gli oggetti CORBA C++ sono già stati realizzati oppure vengono realizzati da qualcun altro). Questo server CORBA Java può quindi essere utilizzato per le vostre prove di integrazione esattamente come se fosse il server C++.

Il client CORBA è infatti del tutto inconsapevole del linguaggio scelto sul lato server per implementare un oggetto CORBA.

Indipendentemente dal fatto che il Server CORBA venga implementato in Java o in C++, il punto di partenza è costituito dalla definizione dell'interfaccia che dovrà avere l'oggetto che dobbiamo rendere disponibile attraverso CORBA. Tale interfaccia viene descritta in linguaggio IDL come segue:

// file calcolatrice.idl
module eai
{
  interface Calcolatrice
  {
    short strlen_calc(in string msg);
  };
};

Una volta definita l'interfaccia IDL del nostro oggetto, dobbiamo compilarla attraverso un apposito compilatore IDL ottenendo così alcuni files nel linguaggio di programmazione desiderato (Java, C++..) contenenti definizioni di classi di supporto che ci permetteranno di esportare l'oggetto. A titolo esemplificativo, riportiamo nella tabella seguente alcuni estratti dei files generati dalla compilazione IDL nel caso della traduzione in C++ e in Java.

| IDL (calcolatrice.idl) | C++ ottenuto dal compilatore IDL di MICO | Java ottenuto dall'IDLJ | |---|---|---| | module eai{ interface Calcolatrice { short strlencalc(in string msg); };}; | namespace eai {class Calcolatrice : virtual public CORBA::Object {virtual CORBA::Short Calcolatrice::strlencalc(const char* msg) throw (CORBA::SystemException) =0;} | package eai;public interface CalcolatriceOperations { short strlen_calc (String msg);} |

Il costrutto IDL module si mappa nel costrutto Java package e nel costrutto C++ namespace.

Ciascuna operazione definita in modo language independent nell'interface IDL Calcolatrice viene mappata in una omonima member function C++ ed analogamente in un metodo Java come esemplificato nella tabella precedente per strlen_calc. Esistono per ogni linguaggio regole precise che prescrivono come mappare ciascun parametro delle operazioni IDL nei diversi linguaggi di programmazione, a seconda del suo tipo e della direzione in cui viene passato (in, out, inout, return).

Per quanto riguarda il nostro esempio, al valore di ritorno (di tipo IDL short) corrisponde il tipo Java short e il tipo C++ CORBA::Short.

Per quanto riguarda invece il parametro d'ingresso al tipo IDL string corrisponde la classe Java String e un puntatore a caratteri per C++.

Per eseguire la compilazione dell'interfaccia IDL in MICO, si deve eseguire il comando:

$MICO_HOME/idl/idl calcolatrice.idl

Questo produrrà come risultato i files calcolatrice.h e calcolatrice.cc che contengono le classi Stub e Skeleton da linkare insieme nell'eseguibile. In aggiunta a questi sarà a carico nostro realizzare una classe C++ (nella terminologia CORBA è detta 'Servant') che implementi le operazioni definite nell'interfaccia IDL ed una funzione main() che faccia le opportune inizializzazioni, crei il servant e si ponga in attesa di richieste per l'oggetto creato.

Per realizzare l'eseguibile del CORBA server C++ è dunque necessario compilare e linkare insieme i seguenti files:

  • mainServer.cc: contiene il main () del programma
  • calcolatrice.cc: è il file generato dal compilatore IDL
  • CalcolatriceImpl.cc: contiene l'implementazione del nostro oggetto CORBA

Una semplice classe C++ che realizza l'interfaccia IDL Calcolatrice è mostrata di seguito:

// file CalcolatriceImpl.h
#include "calcolatrice.h"

class CalcolatriceImpl: public POA_eai::Calcolatrice
{
public:
  CalcolatriceImpl(){};
  virtual ~CalcolatriceImpl(){};
  virtual CORBA::Short strlen_calc(const char* msg) throw
    (CORBA::SystemException) ;
};

// file CalcolatriceImpl.cc
#include <cstring>
#include "CalcolatriceImpl.h"

CORBA::Short CalcolatriceImpl::strlen_calc(const char* msg) throw
  (CORBA::SystemException)
{
  return (strlen(msg));
}

Riportiamo quindi il codice della funzione main() che provvede a inizializzare l'ORB e a "pubblicare" il nostro oggetto Corba.

//file mainServer.cc
#include <CORBA.h>
#include <coss/CosNaming.h>
#include "CalcolatriceImpl.h"
#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char* argv[])
{
  try {
    // Inizializzazione dell'ORB
    CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

    // ottengo un reference al root POA
    CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
    PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(obj.in());

    // ottengo il POA Manager
    PortableServer::POAManager_var poa_manager = rootPOA->the_POAManager();

    // ottengo un reference al context root del Naming Service
    CosNaming::NamingContext_var rootContext =
      CosNaming::NamingContext::_narrow(
        orb->resolve_initial_references("NameService"));

    // creo il servant
    CalcolatriceImpl servant;

    // attivo l'oggetto CORBA
    PortableServer::ObjectId_var oid = rootPOA->activate_object(&servant);

    // ottengo il reference all'oggetto CORBA
    CORBA::Object_var ref = rootPOA->id_to_reference(oid.in());

    // creo il Naming Context di nome logico "eai" e effettuo il bind
    CosNaming::Name name;
    name.length(1);
    name[0].id = (const char *) "eai";
    name[0].kind = (const char *) "";

    CosNaming::NamingContext_var nc1;
    try
    {
      nc1 = rootContext -> bind_new_context(name);
    }
    catch(const CosNaming::NamingContext::AlreadyBound&)
    {
      CORBA::Object_var obj = rootContext->resolve(name);
      nc1 = CosNaming::NamingContext::_narrow(obj.in());
    }

    // effettuo il bind dell'oggetto remoto
    name.length(2);
    name[0].id = (const char *) "eai";
    name[0].kind = (const char *) "";
    name[1].id = (const char *) "calcolatrice";
    name[1].kind = (const char *) "";
    rootContext->rebind(name, ref.in());

    // attivo il POA Manager
    poa_manager->activate();
    // mi metto in attesa di richieste
    orb->run();
  }
  catch(const CORBA::Exception& e) {
    cout << "eccezione!!! " << endl;
    return 1;
  }
  return 0;
}

Una volta effettuate le necessarie compilazioni possiamo avviare il Naming Service ed il nostro server Corba: per fare questo utilizziamo le seguenti istruzioni:

$MICO_HOME/coss/naming/nsd -ORBGIOPVersion 1.2 -ORBIIOPVersion 1.2 \
  -ORBIIOPAddr inet:<<SERVER>>:1666 &

./server -ORBIIOPAddr inet:$HOST_D:1777 -ORBGIOPVersion 1.2 -ORBIIOPVersion \
  1.2 -ORBInitRef NameService=corbaloc:iiop:<<SERVER>>:1666/NameService

Così facendo abbiamo messo in ascolto il Naming Service sulla porta 1666 ed il nostro server Corba sulla porta 1777.

Ora che il server Corba è pronto per essere contattato, abbiamo bisogno di un client.

Il Client CORBA Java

Analogamente a quanto visto con MICO, bisogna compilare l'interfaccia IDL utilizzando ad esempio il compilatore IDLJ presente nel JDK.

idlj -fclient calcolatrice.idl

Tale compilazione genera le seguenti classi Java necessarie al client:

  • _CalcolatriceStub.java: la classe stub che permette al client di comunicare con l'ORB
  • CalcolatriceHelper.java: fornisce funzionalità ausiliarie come il metodo narrow() che permette la conversione dell'Oggetto CORBA al tipo appropriato
  • CalcolatriceHolder.java: viene utilizzata nei casi di parametri IDL out o inout
  • Calcolatrice.java, CalcolatriceOperations.java: insieme forniscono "traduzione" Java dell'interfaccia IDL

Ottenuti i Java bisogna provvedere alla loro compilazione.

Si riporta di seguito il codice del client:

public class CalculatorTestClient {
  . . . . .
  public void test(String args[]) {
    try{
      // create and initialize the ORB
      ORB orb = ORB.init(args, null);
      // si ricava il root naming context(NameService=persistente
      // TNameService=transient)
      org.omg.CORBA.Object objRef =
        orb.resolve_initial_references("NameService");
      NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

      // nome logico dell'oggetto remoto
      NameComponent nc[] = { new NameComponent("eai", ""),
        new NameComponent("calcolatrice", "")
      };
      // Lookup + narrow dell'oggetto remoto
      Calcolatrice obj= CalcolatriceHelper.narrow(ncRef.resolve(nc));

      // invocazione del metodo remoto
      System.out.println("Risultato: " + obj.strlen_calc("Hello!"));

    } catch (Exception e) {
      ...
    }
  }
}

A questo punto è possibile compilare il client e mandarlo in esecuzione.

Per specificare dove trovare il Naming Server e su quale porta TCP è in ascolto è possibile usare la modalità proprietaria SUN mediante le proprietà ORBInitialPort e ORBInitialHost.

Nella modalità standard CORBA invece bisogna avvalersi della proprietà ORBInitRef:

%JAVA_HOME%\bin\java -classpath %CLASSPATH%
it.mokabyte.eai.my.client.corba.CalculatorTestClient
-ORBInitRef NameService=corbaloc:iiop:<<SERVER>>:1666/NameService

È utile infine notare come sia possibile utilizzare le API JNDI per localizzare l'oggetto CORBA invece della API del CORBA Naming Service.

Per fare questo si deve specificare oltre alla proprietà java.naming.factory.initial e java.naming.provider.url precedentemente spiegate, anche la proprietà java.naming.corba.orb inizializzata con l'oggetto ORB che si utilizza.

Di conseguenza la relativa narrow può essere eseguita mediante il metodo javax.rmi.PortableRemoteObject.narrow() al posto del metodo narrow della classe Helper CalcolatriceHelper.narrow().

ORB orb = ORB.init(args, null);
properties = new Properties();
properties.put("java.naming.corba.orb", orb);
properties.put(Context.INITIAL_CONTEXT_FACTORY,
  "com.sun.jndi.cosnaming.CNCtxFactor");
properties.put(Context.PROVIDER_URL,
  "corbaloc::<<SERVER>>:3528/JBoss/Naming/root");
Context ctx = new InitialContext(properties);
// Lookup + narrow dell'oggetto remoto
Object obj = PortableRemoteObject.narrow(ctx.lookup("eai/calcolatrice"),
  CalcolatriceHome.class);
// invocazione del metodo remoto
System.out.println("Risultato: " + obj.strlen_calc("Hello!"));

Conclusioni

In questo articolo si è visto come è possibile sfruttare l'interoperabilità offerta dal protocollo IIOP per la comunicazione tra applicazioni eterogenee.

Risorse

Scarica gli esempi descritti nell'articolo

Bibliografia

  • [INT1] S.Rossini: Integrazione di applicazioni Enterprise (I) MokabyteN.71-Aprile 2003
  • [INT2] S.Rossini: Integrazione di applicazioni Enterprise (II) MokabyteN.72-Maggio 2003
  • [MOKA_RMI-1] G.Puliti: "Remote Method Invocation", Mokabyte N16 Febbraio 1998
  • [MOKA_RMI-2] S.Rossini: "Networking in Java Parte V: RMI", Mokabyte N43, Luglio 2000
  • [MOKA_GIOP] A.Bemporad: "GIOP/IIOP l'autostradaCorba", Mokabyte N.25, 10mbre 1998
  • [MOKA_CORBA] L.Bettini: "Java+IDL=CORBA", Mokabyte N.22, Settembre 1998
  • [MOKA_IIOP-1] S. Rossini: "RMI-IIOP I parte", Mokabyte N.44, Settembre 2000
  • [MOKA_IIOP-2] S. Rossini: "RMI-IIOP II parte", Mokabyte N.45, Ottobre 2000
  • [MOKA_IIOP-3] G. Puliti: "RMI over IIOP", Mokabyte N.70, Gennaio 2003
  • [JACORB] http://www.jacorb.org
  • [MICO] http://www.mico.org