CORBA, CORBA Services, IDL, idlj, orbd, tnameserv, stub, skeleton, servant, OMG, object marshalling, IIOP
CORBA (Common Object Request Broker Architecture), dezvoltată de Object Management Group, este o tehnologie ce oferă o arhitectură independentă de platformă şi de limbajul de programare pentru a dezvolta aplicaţii distribuite, orientate pe obiecte.
Obiectele CORBA se pot afla oriunde, comunicând prin intermediul unei reţele de calculatoare, presupunând că maşinile pe care se găsesc sunt conectate la Internet, fiind vizibile în acest spaţiu printr-o adresă publică. CORBA reprezintă astfel un standard ce permite interacţiunea între (colecţii de) obiecte distribuite (şi eterogene) în cadrul unei aplicaţii.
CORBA pune la dispoziţie un mediu pentru dezvoltarea de aplicaţii distribuite, soluţie adoptată atunci când datele folosite sunt distribuite (în baze / depozite de date aflate pe maşini diferite), când procesarea este distribuită (în sisteme de tip Grid / Cloud) sau când utilizatorii sunt distribuiţi.
Caracteristicile sistemelor distribuite pot fi sistematizate astfel:
Criteriu | Sisteme Nedistribuite | Sisteme Distribuite |
---|---|---|
comunicaţie | rapidă | lentă |
erori | obiectele sunt distruse împreună | obiectele sunt distruse separat |
acces concurent | doar prin fire de execuţie | da |
securitate | da | nu |
Ţinând cont de faptul că în cadrul aceluiaşi proces comunicaţia între obiecte este semnificativ mai rapidă decât în cazul unei aplicaţii distribuite, trebuie evitată o interacţiune foarte strânsă între obiecte în cadrul proiectării aplicaţiilor ce utilizează prelucrarea paralelă.
Într-un sistem tradiţional, producerea unei erori implică distrugerea tuturor obiectelor create în cadrul procesului respectiv. Pe de altă parte, în cadrul aplicaţiilor distribuite, programatorul trebuie să ia în calcul situaţia în care disponibilitatea obiectelor este diferită (existenţa lor fiind autonomă), aceasta fiind dependentă de comportamentul procesului în care rulează.
Dacă pentru o aplicaţie nedistribuită există posibilitatea de a alege între unul sau mai multe fire de execuţie, garantând un acces secvenţial al obiectelor, respectiv implicând necesitatea folosirii unor mecanisme de sincronizare pentru controlul accesului concurent, în situaţia unui sistem ce rulează pe mai multe maşini, obiectele pot fi accesate de mai mulţi clienţi în mod implicit, astfel încât mecanismele de sincronizare trebuie implementate obligatoriu.
Securitatea este un aspect care trebuie luat în calcul atunci când obiectele sunt distribuite, interacţiunea între acestea trebuind să aibă la bază mecanisme de autentificare spre a se respecta drepturile de accesare ale acestora.
CORBA defineşte o arhitectură pentru obiecte distribuite, bazată pe conceptul de cerere a unui serviciu pus la dispoziţie de un obiect distribuit. Serviciile pe care le oferă un obiect distribuit sunt specificate în interfaţa sa, descrisă într-un limbaj de definire al interfeţei dezvoltat de OMG (IDL – Interface Definition Language). Obiectele vor fi identificate prin referinţele la ele, având tipurile specificate în interfaţa corespunzătoare.
Clientul deţine o referinţă către un obiect distribuit (rezident pe server), definit printr-o interfaţă. Serviciul (distribuit) ORB (Object Request Broker) transmite cererea obiectului distribuit pe server şi întoarce rezultatul la client. Pentru a implementa acest comportament, serviciul localizează obiectul în reţea, comunică cererea către acesta, aşteptă rezultatul, pentru ca în momentul în care este disponibil să îl transmită către aplicaţia care l-a solicitat. Aşadar, ORB realizează transparenţa atât faţă de locaţia unde se află implementat obiectul care pune la dispoziţie serviciile cât şi faţă de limbajul de programare în care se scrie cererea (acesta putând fi diferit faţă de limbajul de programare în care este implementat serviciul obiectului), realizând corespondenţa necesară.
Specificaţia CORBA are drept obiectiv portabilitatea atât a clientului cât şi a implementării obiectelor. În acest sens, este definit un API atât pentru clienţii unui obiect distribuit cât şi pentru implementarea obiectului CORBA. Acest obiectiv ar presupune că se poate rescrie cu uşurinţă codul dezvoltat pentru accesarea unui serviciu CORBA al unui producător, astfel încât să poată funcţiona în alte contexte similare. În realitate, aplicaţii de tip client sunt portabile, însă adaptarea în cazul implementărilor obiectelor este mai dificilă pentru a asigura interoperabilitatea cu mai multe produse CORBA.
Pentru asigurarea interoperabilităţii, este definit un protocol IIOP (Internet Inter-ORB Protocol) ce permite clienţilor folosind un produs CORBA realizat de un producător să poată comunica cu obiecte din cadrul altui produs CORBA dezvoltat de orice alt producător. IIOP funcţionează peste orice implementare TCP/IP.
În cadrul unui sistem distribuit, interoperabilitatea este mai importantă decât portabilitatea. Astfel, IIOP este folosit şi în alte sisteme decât în cele care implementează API-ul CORBA. Deoarece toate aceste sisteme folosesc IIOP ca protocol de transport, deşi utilizează API-uri diferite, pot interacţiona între ele.
Un aspect important în arhitectura CORBA este reprezentat de definirea unui set de servicii distribuite, cunoscute sub numele de COS (CORBA Services), care suportă integrarea şi interacţiunea dintre obiecte distribuite. Ele sunt implementate ca obiecte distribuite CORBA, definite prin interfeţe IDL.
Serviciu | Descriere |
---|---|
ciclu de viaţă al obiectului | defineşte procesele de creare, ştergere, mutare şi copiere a obiectelor CORBA |
serviciu de nume | defineşte modul în care se pot asocia obiectelor CORBA nume simbolice |
serviciu de evenimente | decuplează comunicarea între obiecte CORBA |
serviciu de legături | stabileşte legături (cu multiplicităţi şi tipuri asociate) între obiecte CORBA |
serviciu de externalizare | realizează transformarea obiectelor CORBA în / din surse externe |
serviciu de tranzacţii | coordonează atomicitatea accesului la obiecte CORBA |
control al accesului concurent | oferă servicii de blocare a accesului la obiecte CORBA pentru asigurarea mecanismului de serializare |
serviciu de proprietăţi | stabileşte asocierea perechilor de tip nume-valoare cu obiecte CORBA |
serviciu de identificare | găseşte obiecte CORBA pe baza proprietăţilor care descriu serviciul oferit |
serviciu de interogări | permite realizarea de interogări cu obiecte CORBA |
CORBA este o specificaţie implementată de mai mulţi producători pentru diferite limbaje de programare. Pentru Java, au fost dezvoltate Java ORB (distribuită împreună cu SDK-ul Java, având unele funcţionalităţi lipsă), VisiBroker for Java (dezvoltată de Borland), Orbix Web (de la Iona Technologies), WebSphere (server de aplicaţii realizat de IBM).
În cele ce urmează, implementarea unei aplicaţii distribuite folosind tehnologia CORBA va fi ilustrată pe cazul particular al aplicaţii implementând un serviciu de rezervare, a cărui funcţionalitate a fost descrisă pe larg în laboratorul anterior.
Prin limbajul de definire a interfeţelor dezvoltat în cadrul OMG (IDL – Interface Definition Language) se permite specificarea obiectelor distribuite prin operaţiile suportate, fără a se oferi detalii cu privire la modul în care acestea sunt realizate. Prin urmare, nu se vor specifica în IDL stări ale obiectului sau algoritmi. Implementarea unui obiect CORBA este realizată într-un limbaj de programare, interfaţa fiind doar o punte de legătură (un contract) între codul care foloseşte obiectul (dependent doar de interfață) şi codul care defineşte obiectul. Interfaţa poate fi considerată un contract în sensul garantării unei anumite funcţionalităţi (prin parametrii de intrare şi de ieşire) fără a oferi detalii despre modul de implementare.
Interfaţa în care este specificat comportamentul obiectului distribuit este independentă de limbajul de programare. IDL defineşte corespondenţe pentru mai multe limbaje de programare, permiţând deci ca implementarea unui obiect să se poată face în limbajul de programare adecvat pentru obiectul respectiv. Totodată, acelaşi lucru este posibil şi pentru client.
Pot fi definite astfel, independent de limbajul de programare, interfeţe modularizate pentru obiecte, specificând atribute şi metode suportate de acestea. De asemenea, pot fi indicate excepţiile pe care le poate genera o anumită operaţie. Fiecare operaţie este definită prin tipul de date al valorii întoarse precum şi prin tipurile de date ale parametrilor.
IDL suportă tipuri de date de bază (boolean
, char
, octet
, short
, long
, float
, double
, string
) sau construite (struct
, union
, enum
, sequence
), obiecte definite sau tipul any
pentru obiecte cu tipul de date stabilit dinamic (la momentul utilizării).
Corespondenţa între tipuri de date IDL şi cele din limbajul de programare Java sunt descrise mai jos:
IDL | Java |
---|---|
boolean | boolean |
char / wchar | char |
octet | byte |
short / unsigned short | short |
long / unsigned long | int |
long long / unsigned long long | long |
float | float |
double | double |
string / wstring | String |
De asemenea, există o corespondenţă între anumite structuri IDL şi structuri Java.
IDL | Java |
---|---|
module | package |
interface | interface |
operation | method |
attribute | pair of methods |
exception | exception |
Un concept întâlnit frecvent atunci când se vorbeşte despre corespondenţa tipurilor de date este cel de tipare inversă (eng. marshalling), adică de transformare a unei structuri specifice unui limbaj de programare într-un format CORBA IIOP, astfel încât să poată fi transmisă prin reţea.
Pentru aplicaţia considerată, un exemplu de specificaţie IDL poate fi:
module Reservation { struct Date { long day; long month; long year; }; struct Moment { long hour; long minute; }; struct Time { Date date; Moment moment; }; struct Interval { Time start; Time end; }; typedef sequence<Interval> Intervals; exception UnspecifiedTimeTable {}; interface ReservationService { Intervals getTimeTable() raises(UnspecifiedTimeTable); long getAvailableSeats(in Interval interval) raises(UnspecifiedTimeTable); boolean makeReservation(in long customerId, in Interval interval, in Interval numberOfSeats) raises(UnspecifiedTimeTable); boolean cancelReservation (in long customerId, in Interval interval) raises(UnspecifiedTimeTable); }; };
În specificaţia IDL Reservation.idl
, au fost definite ca structuri de date Date
, Moment
, Time
, Interval
, Intervals
, şi excepţia UnspecifiedTimeTable
, utilizate ulterior în interfaţa ReservationService
. Au fost definite mai multe metode ce primesc parametri de intrare (fapt specificat prin cuvântul cheie in
), descriind funcţionalitatea oferită de aplicaţie. Parametrii de ieşire (indicând date care sunt transmise de la obiectul distribuit către client) sunt specificaţi prin cuvântul cheie out
, iar parametrii de intrare ieşire (indicând date transmise de la client către obiectul distribuit şi înapoi la client) sunt specificaţi prin cuvântul cheie inout
.
Produsele CORBA pun la dispoziţie un compilator care converteşte interfaţa IDL în reprezentarea corespunzătoare limbajului de programare. Pentru distribuţia standard Java, acesta se numeşte idlj
și se găseşte în directorul bin
al distribuţiei standard.
Prin comanda
idlj Reservation.idl
vor fi generate următoarele fişiere:
Fişier | Semnificaţie |
---|---|
ReservationService.java | Interfaţa IDL reprezentată ca intefaţă Java |
ReservationServiceHelper.java | Implementează operaţiile de tipare pentru interfaţă (insert , extract , read , write , narrow , unchecked_narrow ) |
ReservationServiceHolder.java | E folosit pentru operaţii cu parametri de tip out şi inout . |
ReservationServiceOperations.java | Conţine descrierile operaţiilor implementate de interfaţă (ReservationService este derivată din ReservationServiceOperations ) |
_ReservationServiceStub.java | Implementează un obiect local reprezentând obiectul CORBA “la distanţă” ce transmite cererile spre obiectul distribuit |
Pentru a genera atât fişierele pentru client şi pentru server, utilitarul idlj este apelat cu parametrul -fall
. Pentru a genera doar fişierele pentru server sau pentru client sunt folosiţi parametrii -fserver
, respectiv -fclient
.
Aşadar, etapele dezvoltării unei aplicaţii distribuite folosind CORBA sunt:
idlj
); se obţine versiunea interfeţei corespunzătoare limbajului de programare respectiv, şi totodată clasele ciot (eng. stub) respectiv schelet (eng. skeleton) care conţin infrastructura de conectare la ORB;
Prin serviciul de nume (referinţele către) obiectele distribuite sunt publicate de server, devenind astfel disponibile clienţilor, care le pot folosi pentru a apela metodele specificate în interfaţă. Se va utiliza orbd
, un proces care rulează în fundal (eng. daemon) şi conţine serviciile: de iniţializare (Bootstrap Service), de nume tranzitoriu (Transient Name Service) dar şi de nume permanent (Persistent Name Service) şi un proces de gestiune pentru server (Server Manager).
tnameserv
(apelat fără parametri), ca alternativă la orbd
. De regulă, tnameserv
se lansează pe portul 900.
Într-un sistem Unix, serviciul de nume se porneşte astfel:
aipi2014@ubuntu:$ orbd -ORBInitialPort 1100&
Într-un sistem Windows, serviciul de nume se porneşte astfel:
C:\Users\Aipi2014> start orbd –ORBInitialPort 1100
Parametrul ORBInitialPort
este obligatoriu.
CORBA implementează un sistem de excepţii care este foarte similar celui din limbajul de programare Java.
Există două tipuri de excepţii în CORBA: sistem şi utilizator.
Excepţiile de tip sistem sunt generate atunci când au loc evenimente ce ţin de aplicaţie la modul general (a fost apelată o metodă care nu este implementată pe server, există o problemă de comunicare, sistemul ORB nu a fost iniţializat corespunzător). System Exceptions în Java sunt o subclasă a RuntimeException
astfel încât ele nu trebuie incluse într-un bloc try {…} catch
. Totuşi, tratarea excepţiilor în acest fel poate beneficia de avantajul obţinerii unui cod de eroare, care diferă de la producător la producător.
Excepţiile de tip utilizator sunt generate în cazul unor erori în cadrul unei metode propriu-zise. User Exceptions în Java sunt o subclasă a Exception
, aşadar trebuie incluse (obligatoriu) într-un bloc try {…} catch
.
Implementarea obiectului distribuit CORBA este transparentă pentru client, care cunoaşte doar specificaţiile din interfaţa IDL. Încapsularea completă a obiectelor distribuite CORBA oferă mai multă libertate în ceea ce priveşte implementarea lor, aceasta putând fi realizată în limbaje de programare diferite chiar şi faţă de limbajul de programare în care este scris clientul. La nivel de server, implementarea obiectului distribuit se face pe baza clasei schelet generată la compilarea interfeţei IDL. Se oferă astfel mecanismul de acces la nivelul obiectului distribuit, ce conţine despachetarea datelor primite, apelarea metodei ce implementează operaţia solicitată, împachetarea rezultatelor transmise.
Pentru implementarea obiectului distribuit CORBA, programatorul trebuie să dezvolte o clasă derivată din casa schelet, specificând comportamentul pentru metodele descrise de interfaţa IDL.
CORBA specifică două mecanisme de dezvoltare a serverului pentru implementarea unei interfeţe IDL:
*POA.java
care extinde org.omg.PortableServer.Servant
, folosită drept clasă de bază pentru toate implementările servantului (clasa care implementează metodele specificate în interfaţa IDL pe server);*Operations.java
).La nivelul serverului, trebuie realizate următoarele operaţii:
import org.omg.CORBA.*; import org.omg.CosNaming.*; import org.omg.PortableServer.*; import Reservation.*; public class Server { public static void main (String[] args) { try { ORB orb = ORB.init(args,null); POA POARoot = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); POARoot.the_POAManager().activate(); ReservationServiceImplementation ReservationServiceImpl = new ReservationServiceImplementation(); org.omg.CORBA.Object ReservationServiceImplRef = POARoot.servant_to_reference(ReservationServiceImpl); ReservationService ReservationServiceRef = ReservationServiceHelper.narrow(ReservationServiceImplRef); org.omg.CORBA.Object nameServiceRef = orb.resolve_initial_references("NameService"); NamingContextExt nameContextRef = NamingContextExtHelper.narrow(nameServiceRef); String serviceName = "ReservationService"; NameComponent nameComponent = new NameComponent(serviceName,""); NameComponent path[] = { nameComponent }; nameContextRef.rebind(path,ReservationServiceRef); orb.run(); } catch (Exception exception) { System.out.println ("An exception has occurred: "+exception.getMessage()); } } }
Clasa ReservationServiceImplementation
reprezintă servantul, care extinde clasa ReservationServicePOA
, astfel încât moşteneşte funcţionalitatea CORBA generată de compilatorul IDL. Aceasta va conţine toate implementările descrise prin interfaţă, conţinând serviciile puse la dispoziţie.
Un server CORBA are nevoie de un obiect ORB local, ca de altfel şi fiecare client CORBA. Toate obiectele servant vor fi înregistrate prin acesta, astfel încât serviciul ORB să poată localiza serverul atunci când sunt invocate funcţionalităţi pe care le pune la dispoziţie. Prin metoda init()
, ce primeşte argumente din linia de comandă, se pot specifica anumite proprietăţi, între care cele mai importante sunt portul şi adresa pe care rulează serverul.
Serverul va fi lansat în execuţie astfel:
aipi2014@ubuntu:$ java Server -ORBInitialPort 1100 -ORBInitialHost localhost&
C:\Users\Aipi2014> start java Server -ORBInitialPort 1100 -ORBInitialHost localhost
Apoi, prin intermediul serviciului ORB se obţine obiectul care conţine referinţa către obiectul POA rădăcină prin metoda resolve_initial_references()
. După obţinerea referinţei către obiectul POA rădăcină se activează serviciul POAManager
. Prin metoda activate()
se schimbă starea serviciului de gestiune POA în activ astfel încât obiectele asociate acestuia vor prelucra cererile venite de la client. Fiecare obiect POA
are asociat un obiect POAManager
(care poate gestiona, la rândul lui, unul sau mai multe obiecte POA
). Prin POAManager
se încapsulează starea în care se găseşte prelucrarea fiecărui obiect POA asociat.
Serverul este procesul care instanţiază unul sau mai multe obiecte servant. Un servant moşteneşte interfaţa generată de compilatorul IDL, implementând propriu-zis prelucrările specificate prin operaţiile respective. Servantul ReservationServiceImplementation
este instanţiat prin obiectul ReservationServiceImpl
.
Se obţine o referinţă către obiectul distribuit, iniţial ca obiect CORBA (prin metoda servant_to_reference()
, apelată din contextul obiectului rădăcină POA, instanţei servantului), cast-ul la tipul corespunzător făcându-se prin metoda (statică) narrow()
din clasa (generată de compilatorul IDL) ReservationServiceHelper
.
Operaţiile puse la dispoziţie de (instanţa) servant(ului) sunt făcute vizibile către client prin serviciul de nume Common Object Service (COS).
Se obţine referinţa către acest serviciu de nume astfel încât să se poată înregistra prin ea referinţele către obiectele care implementează diferite interfeţe. Referinţele către obiectele care implementează diferite interfeţe sunt folosite de clienţi pentru invocarea metodelor specificate în interfaţă.
Referinţa către serviciul de nume se face tot prin metoda resolve_initial_references()
, transformarea către tipul corespunzător contextului de nume realizându-se prin metoda narrow()
, la fel ca în cazul obiectelor POA. Parametrul “NameService” este definit pentru toate serviciile ORB, indicând faptul că serviciul de nume va fi persistent, dacă se foloseşte serviciul de nume orbd
, respectiv tranzitoriu, în cazul utilizării tnameserv
.
Se realizează o componentă de nume indicându-se denumirea prin care serviciile puse la dispoziţie de obiectul respectiv pot fi accesate. Se face apoi legătura dintre componenta de nume şi referinţa către obiectul distribuit, întoarsă către client prin apeluri tip NamingContext.resolve_str(serviceName)
, prin care se poate obţine acces către funcţionalitatea dorită.
Apelul orb.run()
blochează serverul în aşteptarea invocărilor realizate din contextul clientului. Deoarece apelul este făcut din metoda main()
, este folosit firul de execuţie corespunzător acesteia, astfel încât, la momentul încheierii prelucrărilor corespunzătoare unei invocări, serverul va rămâne în continuare blocat în aşteptarea unor alte apeluri. Datorită acestui comportament, trebuie specificată o condiţie de terminare, implicând apelul metodei shutdown()
asociată obiectului corespunzător serviciului ORB.
Operaţiile realizate la nivelul clientului sunt asemănătoare cu cele realizate de către server:
java Client -ORBInitialPort 1100 -ORBInitialHost localhost
Orice client are nevoie de un obiect local ORB pentru realizarea împachetării datelor transmise şi prelucrărilor IIOP.
resolve_initial_references()
din contextul obiectului ORB având parametrul “NameService”, cu aceeaşi semnificaţie ca în cazul serverului, transformarea la tipul dorit realizându-se prin metoda narrow;resolve_str()
a obiectului care conţine o referinţă contexul de nume, având ca parametru denumirea sub care a fost specificat, în acelaşi mod precum s-a realizat localizarea serviciului de nume;narrow()
;import org.omg.CORBA.*; import org.omg.CosNaming.*; import Reservation.*; public class Client { public static void main (String[] args) { try { ORB orb = ORB.init(args,null); org.omg.CORBA.Object nameServiceRef = orb.resolve_initial_references("NameService"); NamingContextExt nameContextRef = NamingContextExtHelper.narrow(nameServiceRef); String serviceName = "ReservationService"; ReservationService ReservationServiceRef = ReservationServiceHelper.narrow(nameContextRef.resolve_str(serviceName)); // TO DO: apeleaza metode obiect rezervare } catch (Exception exception) { System.out.println ("An exception has occurred: "+exception.getMessage()); } } }
IIOP este un protocol de transport (peste Internet) între obiecte tip ORB având drept scop realizarea interoperabilităţii între limbaje de programare şi aplicaţii comercializate de diverşi producători. Acest protocol este utilizat pentru sisteme distribuite dezvoltate fie în Java RMI, fie în IDL.
Modelul de programare IDL este axat pe interfaţa care descrie metodele care pot fi apelate din procesul “la distanţă”, specificând tipurile de argumente acceptate de procedura invocată cât şi tipurile informaţiilor întoarse de aceasta. CORBA este un sistem independent de limbajul de programare în care valorile argumentelor sau rezultatelor întoarse sunt limitate la ceea ce poate fi reprezentat în limbajele de programare în care se realizeaza implementarea. Tipurile parametrilor de intrare şi de ieşiure trebuie să fie cele specificate în interfaţă. Totodată, orientarea pe obiecte este limitată la obiecte transmise prin referinţă (obiectul nu poate fi transmis între maşini prin cod).
Modelul de programare IDL (JavaTM IDL) conţine Java CORBA ORB şi compilatorul idlj
– care realizează corespondenţa între limbajele IDL şi Java. Astfel, este implementată funcţionalitatea CORBA în platforma Java, oferind interoperabilitate şi conectivitate standardizată permiţând aplicaţiilor distribuite să invoce – în mod transparent – operaţii puse la dispoziţie prin reţea folosind IDL şi IIOP. Este folosit un obiect ORB pentru prelucrări distribuite folosind comunicaţie bazată pe IIOP. Folosirea acestui model implică definirea intefeţelor “la distanţă” folosind limbajul IDL (dezvoltat de OMG), compilarea lor folosind idlj
care va genera versiunea Java a interfeţei ca şi clasele ciot şi schelet care permit aplicaţiilor să comunice prin ORB. Java IDL este o componentă a distribuţiei standard Java.
Limbajul IDL de specificare a intefeţelor este pur declarativ, proiectat pentru specificarea operaţiilor corespunzătoare unei aplicaţii distribuite independent de limbajul de programare. El cuprinde şi corespondenţele către limbaje de programare ca Java, C, C++, Lisp, Python, Smalltalk, COBOL şi Ada, astfel că fiecare instrucţiune este translatată corespunzător. Astfel, un client dezvoltat în Java se poate folosi de implementările (specificate ca interfaţă IDL) realizate în C++ pentru un anumit serviciu, interoperabilitatea dintre cele două limbaje de programare fiind obţinută prin intermediul ORB.
În RMI, interfaţa şi implementarea ei sunt dezvoltate folosind acelaşi limbaj de programare, astfel încât nu există problema corespondenţei dintre acestea. Obiecte la nivel de limbaj de programare (codul însuşi) pot fi transmise de la un proces la altul.
Modelul de programare RMI se referă la prelucrări distribuite prin API-ul cu acelaşi nume. Se poate lucra doar în limbajul de programare Java, folosind Java Remote Method Protocol (JRMP) sau cu limbaje de programare compatibile CORBA, folosind protocolul IIOP. Acest model de programare este parte din distribuţia standard Java şi conţine serviciul ORB şi compilatorul rmic
pentru generarea claselor ciot şi schelet precum şi a legăturilor dintre obiecte la distanţă folosind protocoalele JRMP sau IIOP. Folosind acelaşi limbaj de programare, dezvoltarea este mai rapidă, iar flexibilitatea este obţinută prin posibilitatea transmiterii de obiecte serializabile.
Modelul de programare IDL sau RMI cu componenta IIOP vor fi folosite aşadar doar pentru interfaţarea cu anumite aplicaţii (eng. legacy systems), preferându-se folosirea modelului de programare RMI din motive ce ţin de portabilitate, securitate şi colectarea memoriei disponibile.
aipi2014-lab05-remoteinterfaces.zip
1. [0 puncte] Să se pornească serviciul de nume orbd prin apelarea scripturilor startNameService
[.bat
|.sh
].
În cazul când calea către directorul bin al SDK-ului Java nu este precizată în variabila de mediu PATH
, acest script nu va fi executat cu succes.
În cazul când calea către directorul bin al SDK-ului Java nu este precizată în variabila de mediu PATH
, acest script nu va fi executat cu succes.
Precizarea căii către directorul bin
al SDK-ului Java în variabila de mediu PATH
se realizează astfel:
export PATH=${PATH}:/usr/lib/jvm/default-java/bin
SET PATH=%PATH%;C:\Program Files\Java\jdk1.8.0_25\bin
orbd
rulează înainte de a porni serverul.aipi2014@ubuntu:~$ ps -a
2. [0 puncte] Să se compileze intefaţa Reservation.idl
folosind compilatorul idlj
pentru generarea claselor server, respectiv client, plasându-se sursele generate în directoare diferite.
idlj -fserver Reservation.idl
idlj -fclient Reservation.idl
Se observă faptul că la generarea claselor din server lipsesc fişierele ReservationServiceHelper.java
şi _ReservationServiceStub.java
. Acestea vor trebui preluate din clasele generate pentru client.
Să se includă fișierele generate în codul sursă corespunzător proiectelor pentru server, respectiv client.
Folosind mediul integrat de dezvoltare (Refactor → Rename), să se redenumească pachetul reservation
în ro.pub.cs.aipi.lab05.reservation
.
Să se creeze configurații de rulare pentru server, respectiv client (dacă nu se folosesc testele unitare), specificând parametrii liniei de comandă:
-ORBInitialHost
având valoarea localhost
;-ORBInitialPort
având valoarea 1100
.Astfel, valoarea parametrilor din linia de comandă va fi:
-ORBInitialHost localhost -ORBInitialPort 1100
3. [10 puncte] Să se încarce orarul de funcţionare al restaurantului în constructorul clasei ReservationServiceImplementation
cu datele conţinute de fişierul timetable.txt
.
Se va parsa conţinutul fişierului timetable.txt
care pe prima linie conţine capacitatea (numărul de locuri) încărcată în variabila numberOfSeats
iar pe următoarele linii programul pentru fiecare zi calendaristică exprimat sub forma ZZ LL AAAA O1 M1 O2 M2
, acesta fiind încărcat în obiectul timetable
.
Să se implementeze metoda getTimetable a clasei ReservationServiceImplementation
.
Această metodă întoarce conţinutul obiectului timetable
.
Interval
/ ReservationData
deja definite (existente în pachetul entities
) şi clasele Interval
/ ReservationInformation
generate din interfaţa IDL (existente în pachetul reservation
).
Pentru clasa Interval
metodele de conversie trebuie realizate in ambele sensuri.
public ro.pub.cs.aipi.lab05.reservation.Interval entitiesIntervalToReservationInterval(ro.pub.cs.aipi.lab05.entities.Interval interval) { ro.pub.cs.aipi.lab05.reservation.Interval result = new ro.pub.cs.aipi.lab05.reservation.Interval(); // TO DO return result; } public ro.pub.cs.aipi.lab05.entities.Interval reservationIntervalToEntitiesInterval(ro.pub.cs.aipi.lab05.reservation.Interval interval) { ro.pub.cs.aipi.lab05.entities.Interval result = new ro.pub.cs.aipi.lab05.entities.Interval(); // TO DO return result; }
Pentru clasa ReservationData
/ ReservationInterval
, conversia trebuie realizată numai în sensul ReservationData
→ ReservationInterval
.
public ro.pub.cs.aipi.lab05.reservation.ReservationInformation entitiesReservationDataToReservationReservationInformation(ro.pub.cs.aipi.lab05.entities.ReservationData reservationData) { ro.pub.cs.aipi.lab05.reservation.ReservationInformation result = new ro.pub.cs.aipi.lab05.reservation.ReservationInformation(); // TO DO return result; }
4. [40 puncte] Să se implementeze metoda getAvailableSeats()
din cadrul clasei ReservationServiceImplementation
.
5. [10 puncte] Să se implementeze metoda makeReservation()
din cadrul clasei ReservationServiceImplementation
.
6. [10 puncte] Să se implementeze metoda cancelReservation()
din cadrul clasei ReservationServiceImplementation
.
7. [10 puncte] Să se apeleze metodele makeReservation()
şi cancelReservation()
din cadrul clasei Client
. Informaţiile utilizate ca parametrii ai metodelor se citesc de la tastatură sau pot fi definite sub formă de constante în codul sursă.
8. [10 puncte] Verificaţi comportamentul la distanţă al aplicaţiei, apelând metodele implementate de colegii voştri.
9. [20 puncte] Să se definească în interfaţa IDL o metodă
Reservations getReservation(in long customerId)
care să întoarcă lista cu intervalele în care clientul respectiv are făcute rezervări, precum şi numărul de locuri rezervate în fiecare dintre cazuri.
Să se implementeze metoda în clasa ReservationServiceImplementations
.
În interfaţa IDL, o posibilă definiţie a structurii Reservations
ar putea fi:
struct ReservationInformation { long customerId; Interval interval; long numberOfSeats; }; typedef sequence<ReservationInformation> Reservations;
CORBA Web Site
OMG Formally Released Versions of CORBA®
The Java™ Tutorials - Trail: RMI
CORBA meets Java
Java SE Core Technologies - CORBA / RMI-IIOP
Java IDL Code Samples
Introduction to CORBA - Short Course