|
Introduzione
Remote Method Invocation è il modello di programmazione
distribuita di Java introdotto con il JDK 1.1: grazie
alla organizzazione basata sulla suddivisione in stub-skeleton,
i metodi di un oggetto remoto possono essere invocati
da un client remoto senza che questo abbia la percezione
che l'oggetto sia invece eseguito utilizzando le risorse
del server remoto.
Rispetto all'analogo CORBA, RMI ha il vantaggio principale
della semplicità, ma vincola a dover utilizzare
strato client e server in Java, ad utilizzare sempre
il medesimo protocollo di comunicazione JRMP, rispettando
al contempo le modalità di interrogazione dei
metodi e di marshalling dei parametri. Per questo motivo
RMI offre semplicità ma non è in grado
di mantenere interoperabilità con piattaforme
differenti ovvero con applicazioni distribuite scritte
in linguaggi diversi.
L'altro soggetto principale coinvolto in questo scenario
è CORBA, il quale ha una connotazione completamente
opposta rispetto a RMI: maggiore interoperabilità
pagata al prezzo di una maggiore complessità.
Con CORBA una applicazione client Java può interagire
con una serie di oggetti remoti scritti in altri linguaggi
(C++, Delphi o altri per i quali sia disponibile un
mapping IDL) e viceversa.
Dato che Java è diventato il dominatore incontrastato
in ambito enterprise soprattutto nella realizzazione
di applicazioni distribuite, portabili, ed integrate,
si è fatta pressante la necessità di una
qualche forma di integrazione fra le due tecnologie.
Era però necessario che tale integrazione fosse
realizzata a patto di non alterare le due tecnologie,
specialmente la prima: l'introduzione di un ulteriore
modello aggiuntivo o un aumento del livello di complessità
in RMI avrebbe significato limitare l'arma vincente
di Java RMI, ovvero semplicità.
Fortunatamente le modifiche sono state effettuate in
gran parte all'interno di CORBA, grazie all'introduzione
di alcuni nuovi paradigmi (object by value ed IDL-to-Java)
garantendo al contempo sia la retro-compatibilità
che l'integrazione con RMI.
Per il lettore nuovo a queste tecnologie, si raccomanda
di approfondire sia RMI che CORBA, per poter comprendere
pregi e difetti di entrambe e valutare quando si debba
preferire l'una all'altra. Dato che tali argomentazioni
esulano dallo scopo di questo articolo, si rimanda alla
bibliografia riportata al fondo.
L'unione dei due mondi
L'integrazione del mondo Java RMI e di CORBA è
resa possibile grazie alla introduzione di RMI-IIOP
dove IIOP indica Internet Inter Orb Protocol. Si tratta
di un protocollo pensato in modo da garantire la comunicazione
sullo strato TCP (Internet) e di connettere ORB differenti
fra loro (IOP).
Sviluppato congiuntamente da IBM e SUN nel 1999, esso
rappresenta il matrimonio fra RMI e CORBA. Lo scenario
che si presentava prima della introduzione di RMI-IIOP
era quello raffigurato in figura 1: applicazioni distribuite
sviluppate in Java RMI e basate sul protocollo JRMP
(Java Remote Protocol), non erano in grado di interagire
con applicazioni scritte con tecnologie differenti e
viceversa.

Figura 1 - lo scenario delle applicazioni
distribuite prima di RMI-IIOP
L'introduzione
di RMI-IIOP ha pesantemente modificato le cose, permettendo
l'interoperabilità fra i due mondi. Se si osserva
la figura 2, si potrà notare come tale tecnologia
consenta la comunicazione fra applicazioni solo Java
RMI e RMI-IIOP e fra RMI-IIOP e CORBA. Di fatto non
è ancora possibile connettere direttamente una
applicazione Java RMI direttamente con una CORBA, ma
questo nella maggior parte dei casi non è un
problema, come avremo modo di vedere.

Figura 2 - RMI-IIOP unisce i due strati applicativi
Ogni
linea diretta nella figura rappresenta la possibilità
di un client di invocare un oggetto remoto in esecuzione
sul server.
Anche se può apparire piuttosto misterioso come
ciò sia possibile, in realtà è
dovuto ad una situazione molto semplice. Il protocollo
RMI-IIOP infatti è in grado di supportare in
modo trasparente entrambi JRMP e IIOP. Un server o un
client scritti per lavorare con RMI-IIOP non necessitano
di essere riscritti o ricompilati per supportare l'uno
o l'altro; per il client infatti è sufficiente
modificare alcuni parametri operativi della JVM o direttamente
all'interno del codice Java, mentre un oggetto remoto
(server-side) potrà essere esposto in modo da
supportare entrambi i protocolli grazie al cosiddetto
dual-export (vedi oltre).
La linea tratteggiata in figura 2 rappresenta una situazione
particolare: in determinate situazione può accadere
che una applicazione client RMI-IIOP non sia in grado
di invocare oggetti CORBA. Questo può avvenire
fondamentalmente per la differente semantica dei tipi
definiti dall'IDL CORBA che rappresenta un super set
di quelli RMI-IIOP. Può accadere quindi che in
determinate situazioni, tipicamente in tutti quei casi
in cui un client Java RMI-IIOP debba integrarsi con
oggetti CORBA preesistenti (legacy objects), non sia
possibile la comunicazione.
E' però vero che, grazie al compilatore rmic,
presente nel JDK, è possibile creare il file
IDL dagli oggetti Java RMI-IIOP: a partire dall'IDL
si potrà generare un oggetto CORBA ad esempio
in C++, oggetto che sarà invocabile da un client
C++ CORBA, ma anche, e senza nessuna limitazione, da
uno Java basato su RMI-IIOP.
Si potrebbe quindi dire che l'incompatibilità
sia un problema esclusivamente di implementazione tale
da non inficiare la comunicazione fra i due strati della
figura 2.

Figura 3 - Tramite Java IDL si può
connettere il
mondo Java direttamente con CORBA
In
quei casi in cui non sia possibile riscrivere l'oggetto
CORBA ed il mapping non permetta a RMI-IIOP di interagire
con tali oggetto, come valida alternativa si può
pensare di abbandonare completamente RMI e passare a
Java IDL (vedi [JIDL]). Tramite Java IDL, una delle
tecnologie introdotte con Java2, è possibile
accedere ad un oggetto CORBA direttamente da Java, senza
passare per altri protocolli bridge intermediari. E'
anche possibile fare il viceversa, ovvero esporre un
oggetto Java al mondo CORBA, ma per tale scenario è
sicuramente preferibile utilizzare RMI-IIOP.
Il punto di forza di RMI-IIOP è dato dal fatto
che lascia inalterata la semantica di RMI (ed anche
la sintassi, eccezion fatta per alcune piccole modifiche
del codice), aggiungendo alcune importanti modifiche
a CORBA in modo da aumentarne le funzionalità:
in CORBA infatti è stata introdotta con la versione
2.3 della specifica il passaggio dei parametri per valore
(object by value) già presente in RMI tramite
il concetto di serializzazione dei parametri ed il Java-to-IDL
mapping che consente il mapping dei tipi Java sui tipi
CORBA.
Queste introduzioni, specie la prima, non devono essere
sottovalutate, dato che sono di fatto variazioni molto
profonde, accettate da OMG non senza qualche timore.
Creare un oggetto remoto
La realizzazione di un oggetto remoto conforme con lo
standard RMI-IIOP è molto simile a quello di
quello basato sul protocollo JRMP. A parte alcune piccole
differenze nel codice, che saranno affrontate successivamente,
il processo di compilazione prevede l'utilizzo del parametro
-iiop da passare al compilatore rmic. In tal modo il
compilatore produce stub e skeleton conformi a IIOP
invece che solamente a JRMP.

Figura 4 - il processo di sviluppo di un oggetto
Java RMI-IIOP
Ovviamente
il passaggio a RMI-IIOP comporta alcune importanti differenze
funzionali dovute alla presenza di CORBA: ad esempio
in questo caso non è disponibile il garbage collector
distribuito come in RMI.
A parte questo il programmatore non dovrebbe avere altra
considerazione della differente architettura sottostante.
Questo è il punto in cui la teoria Java RMI finisce
e ci si addentra nel mondo di CORBA: dato che l'obiettivo
di questo articolo non è quello di fare una trattazione
approfondita su tale tecnologia, si rimanda alla bibliografia
per maggiori approfondimenti in merito.
Da un punto di vista implementativo per realizzare un
oggetto remoto la prima cosa da fare è estendere
dalla classe PortableRemoteObject al posto della Remote
di RMI.
Si supponga ad esempio di voler creare un oggetto remoto
che restituisca l'ora locale del server in cui viene
eseguito. Nella versione RMI questo oggetto potrebbe
essere così definito
public
class MyRemoteClock implements MyRemoteClockRemote {
public String getRemoteDate() throws RemoteException{
return new Date().toString();
}
}
che
in RMI-IIOP dovrebbe essere trasformato
public
class MyRemoteClock
extends
PortableRemoteObject
implements MyRemoteClock {
public String getRemoteDate() throws RemoteException{
return new Date().toString();
}
}
L'altra
modifica lato server da effettuare riguarda la procedura
di registrazione dell'oggetto nel registry. Dato che
in questo caso infatti viene utilizzato JNDI (vedi [JNDI])come
sistema di name service, al posto della istruzione
naming.rebind(<nome-oggetto>,
<istanza-oggetto>);
si
dovrà utilizzare
naming.rebind(<nome-oggetto>,
<istanza-oggetto>);
Infine
dopo aver generato stub e skeleton con il comando
rmic
-iiop MyRemoteClock
si
dovrà procedere ad attivare il registry, utilizzando
il comando tnameserv (al posto di rmiregistry).
Su lato client invece si dovranno effettuare solo le
modifiche relative al differente modo di effettuare
il lookup dell'oggetto remoto, basato su JNDI invece
che sul rmiregistry. In questo caso si dovrà
scrivere
InitialContext
ic = new InitialContext(env)
Object obj = ic.lookup(nome-oggetto);
MyRemoteClock mrc = (MyRemoteClock) PortableRemoteObject.narrow(obj,
MyRemoteClock.class);
A
questo punto il client potrà utilizzare l'oggetto
mrc in modo del tutto analogo al caso RMI, ignorando
se l'implementazione sia data da un oggetto Java RMI
o da uno CORBA scritto in C++.
Conclusione
Come si è potuto vedere RMI-IIOP offre in modo
del tutto trasparente l'interazione fra Java RMI e CORBA.
Il motivo per cui di recente se ne parla sempre più
spesso è dovuto al suo utilizzo nell'ambito EJB.
Molti application server infatti implementano i bean
in esecuzione all'interno del container, con oggetti
CORBA, piuttosto che con oggetti Java. Questo, sebbene
non abbia nessuna ripercussione sui bean ne sul client,
gli oggetti CORBA sono creati al momento del deploy,
permette un sostanziale aumento delle performance, nonché
l'interazione di EJB con tecnologie differenti.
Bibliografia
[JIDL] - "Java + IDL = CORBA" di Lorenzo Bettini,
MokaByte 22, Settembre 1998, www.mokabyte.it/1998/09
[JNDI] - "Java Naming and Directory Interface API"
e seguenti, di Giovanni Puliti, MokaByte 66, Settembre
2002, www.mokabyte.it/2002/09
|