RMI
o RMI IIOP ?
In [INT2] si è visto come l'integrazione Object/RPC
implichi l'invocazione RPC dei metodi degli oggetti
distributi (EJB, CORBA, DCOM,
).
Si è visto come comunicare con l'EJB Facade (installato
sull'Application Server JBoss) me-diante 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 utiliz-zarli 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 distribui-te (vedere
[MOKA_RMI-1,MOKA_RMI-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 interoperabili-tà 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 lin-guaggi
(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 cono-scere
IDL perchè l'unico linguaggio di sviluppo è
eclusivamente Java. Fondamentalmente RMI è una
tecnologia semplice ma chiusa (sia il client che il
server devono essere scritti esclusiva-mente in Java)
e quindi non è in grado di comunicare con applicazioni
distribuite scritte in lin-guaggi 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 bisogna del
servizio di calcolo della lunghezza della stringa non
potrebbe usufruirne non essendo in grado di utilizzare
il protocolo 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
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 defini-sce 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 desti-nazione
i suoi messaggi.
Una particolare implementazione del protocollo GIOP,
chiamata IIOP (Internet Inter-ORB Pro-tocol), si avvale
del protocollo TCP/IP per la realizzazione dello strato
di trasporto dei messag-gi tra oggetti remoti.
IIOP quindi è una sorta di "collante"
che si appogia 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 proprieta-rio 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 de-ploy 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.CNCtxFactor
- 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> specifi-cando 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.CNCtxFactor
· java.naming.provider.url= corbaloc::<<SERVER>>:3528/JBoss/Naming/root
Di
default il client utilizza l'ORB si SUN.
E' possbile 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
partià di bytecode!) si deve includere nel classpath
il jar di JacORB e specificare le seguenti proprietà:
- java.naming.factory.initial=
com.sun.jndi.cosnaming.CNCtxFactor
- 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
E'
inoltre necesario configurare il Security Manager sul
client specificando le proprietà di sicu-rezza
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 Clas-sCastException 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 at-traverso un protocollo
interoperabile quale IIOP. Si vuole realizzare un semplice
client COR-BA 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 (ve-dere [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 seguen-te
"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 attra-verso
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 de-finizioni 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 fon-damentali definiti in java.lang,
come Throwable ed Exception, nonché di alcune
interfacce fondamentali defnite in javax.ejb, come
ad esempio EJBOBject.
- si
utilizza il compilatore idl-to-c++ fornito con MICO
per compilare tutti i files IDL sud-detti
$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 svi-luppando
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.jpg - Figura 2: Servizio esposto mediante Server
CORBA C++ >>
Il
vantaggio offerto dall'architettura CORBA si manifesta
infatti nella possibilità di far intero-perare
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 utlizzare 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 siste-ma
-
è possibile realizzare in C/C++ alcune parti
del proprio sistema che prevedano una elebo-razione
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 no-stro 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
uti-lizzato 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 im-plementare
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 ap-posito compilatore
IDL ottenendo così alcuni files nel linguaggio
di programmazione desidera-to (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 ge-nerati
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 strlen_calc(in
string msg); };}; namespace eai {class Calcolatrice
: virtual public CORBA::Object {virtual CORBA::Short
Calcolatrice::strlen_calc(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 co-me esemplificato nella tabella precedente per
strlen_calc. Esistono per ogni linguaggio regole precise
che prescrivono come mappare ciascun parametro delle
operazioni IDL nei diversi lin-guaggi 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 rea-lizzare una classe C++
(nella terminologia CORBA è detta 'Servant')
che implementi le opera-zioni definite nell'interfaccia
IDL ed una funzione main() che faccia le opportune inizializza-zioni,
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 in-sieme 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 mettoin 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 paramtri IDL out o inout
- Calcolatrice.java,CalcolatriceOperations.java:
insieme forniscono "traduzione" Java dell'interfaccia
IDL
Ottenuti
i Java bisogna provvedere alla lora 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 usa-re
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
E' 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 specificando 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 è 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
[INT1] 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
|