Sunteți pe pagina 1din 506

Proiectarea si Arhitectura

Sistemelor Software
Complexe
Conf.dr.ing. Ioana Şora
staff.cs.upt.ro/~ioana/arhit/
ioana.sora@cs.upt.ro
Ce este si ce nu este
arhitectura software?

?
• Exemplu: figura intentioneaza sa descrie arhitectura unui sistem
care simuleaza o problema de acustica subacvatica
• Se utilizeaza pentru descriere o ”notatie informala” foarte “populara”
de tip boxes-and-lines
Ce este si ce nu este
arhitectura software? (cont)
• Ce NU se poate afla din aceasta figura ?
– Care este natura elementelor ?
– Care sunt responsabilitatile fiecarui element ?
– Care este semnificatia conexiunilor ?
– Care este semnificatia alinierii ?
• Concluzie: diagrama nu reprezinta o arhitectura software (sau cel
putin nu e o reprezentare utila a unei arhitecturi software)

Asa nu !
Arhitectura software - definitie
• “The software architecture is the structure
or structures of the system, which
comprise software elements, the externally
visible properties of those elements and
the relationships among them”
(Bass et al)
Arhitectura software – definitia explicata (1)
“The software architecture is the structure or structures of the
system, which comprise software elements, the externally visible
properties of those elements and the relationships among them”
(Bass et al)

• Elemente software: (termenul element arhit. e de preferat celui de


componenta arhit.)
– Arhitectura este o abstractizare a sistemului
– Arhitectura omite anumite detalii: se exclud acele proprietati ale
elementelor care nu afecteaza modul cum elementele pot fi utilizate de
alte elemente sau interactiunile intre elemente
– Proprietati vizibile din exterior: servicii furnizate, caracteristici de
performanta, utilizarea resurselor partajate de mai multe elemente, etc.
Arhitectura software – definitia explicata (2)

“The software architecture is the structure or structures of the system,


which comprise software elements, the externally visible properties of
those elements and the relationships among them”
(Bass et al)

• Structuri multiple: Arhitectura poate fi compusa din


structuri (vederi structurale) multiple:
– Structura modulelor - structura statica a sistemului, rezulta in
faza de design
– Structura interactiunilor – structura dinamica din timpul executiei
sistemului
– Structurile allocation/deployment - Descrie modul de mapare a
elementelor software pe elemente non-software (hardware, de
personal)
Arhitectura software – definitia explicata (3)

“The software architecture is the structure or structures of the system,


which comprise software elements, the externally visible properties of
those elements and the relationships among them”
(Bass et al)

• Structuri multiple: Arhitectura poate fi compusa din


structuri (vederi structurale) multiple.
– Implicatii: Termenii “Elemente” si “Relatii intre elemente”
pot avea diferite semnificatii:
• Elemente pot fi: obiecte, clase, functii, procese, programe,
biblioteci, etc.
• Relatii/Interactiuni intre elemente: subdivizare, sincronizare, apel
de functie, etc.
Exemplu
Descrieti arhitectura unui sistem care face prelucrari de
text: liniile de text initial sunt transformate astfel: liniile
impare sunt rescrise folosind doar litere mari iar liniile
pare sunt rescrise folosind doar litere mici.
Exemplu – Desen arhitectura 1
Exemplu – Desen arhitectura 2
?
Concluzie Exemplu –
Arhitectura sistemului
• Nici unul din cele 2 desene nu reprezinta o
vedere structurala riguros descrisa
• Fiecare dintre cele 2 desene ar trebui
completate astfel incat sa reprezinte o vedere
structural riguros descrisa
• Arhitectura sistemului este formata din ambele
vederi structurale !

• Arhitectura = un set de vederi structurale


diferite
Standarde/recomandari pentru
descrieri arhitecturale
• 42010-2011 - ISO/IEC/IEEE Systems and
software engineering -- Architecture
description:
– “addresses the creation, analysis and sustainment of architectures of
systems through the use of architecture descriptions. A conceptual
model of architecture description is established. The required contents
of an architecture description are specified. Architecture viewpoints,
architecture frameworks and architecture description languages are
introduced for codifying conventions and common practices of
architecture description. The required content of architecture viewpoints,
architecture frameworks and architecture description languages is
specified.” (from ISO/IEC/IEEE 42010-2011 abstract)
Structurile arhitecturale multiple –
Tipuri de vederi structurale (Viewtypes)

• Module
(Design/Functional Structure)
• Component and Connector
(Runtime) • Cum se descrie fiecare
tip de vedere structurala ?
• Allocation
• La ce serveste fiecare tip
(Deployment, Physical
de vedere structurala ?
Structure, Team Structure)
• Cum selectez vederile
relevante ?
The Module Structure: Elements & Relations

• Elemente: module
– Unitate de implementare pentru software, care reprezinta o entitate
coerenta din punctul de vedere al functionalitatii
• Relatii:
– Is-part-of: A is part of B
– Depends on (Uses or Allowed to use)
– Is-a: A is a B
• Proprietatile elementelor:
– Nume: de obicei contine informatia primara din care se poate “banui”
rolul sau.
– Responsibilitatile: rolul modulului trebuie descris in mai multe detalii
decat simplul nume
The Module Structure: Concluzii

• La ce e bun tipul de vedere Module:


– Construction blueprint
– Analiza unor proprietati ale sistemului
• Impact analysis: prezice efectul modificarilor aduse sistemului; se
bazeaza in special pe relatiile de dependenta
• Traceability to functional requirements: cerintele functionale sunt
suportate de responsabilitatile modulelor
– Comunicare:
• Intelegerea functionalitatii sistemului
• Relatii intre partile sistemului
• La ce NU e bun tipul de vedere Module:
– Comportamentul sistemului in timpul executiei
– Runtime qualities: performance, reliability, etc. => pentru analiza
lor sunt necesare vederi din tipul Component-and-Connector
Component-and-Connector: Overview

• Reprezinta entitati care apar in timpul executiei


programului
• Nu reprezinta unitati de implementare
• Analogie modelare UML:
– Module Viewtype <-> Class Diagrams
– Component&Connector ViewType <-> Object (Collaboration)
Diagrams
• Elementele sunt numite componente si conectori
– Ambele categorii au semantici bine definite
– Conectorii NU pot fi redusi la o subcategorie de componente
Component-and-Connector:
Elements& Relations
• Elemente: Componente – Unitati de procesare sau de stocare de date
– Se manifesta in timpul executiei, sub forma de: procese, obiecte, clienti, servere,
baze de date, etc.
– Porturi: “interfata” componentei la executie; puncte de (potentiala) interactiune
cu mediul
– Tipul unei componente: defineste functionalitatea generala a acesteia, numarul si
tipul porturilor, proprietatile cerute; de exemplu, o componenta de tip “filter”
proceseaza fluxuri (stream) de intrare primite pe porturile de tip “input”, rezultand
fluxuri de iesire la porturile “output”.
• Conectori – mecanisme de interactiune intre componente
– Se manifesta sub forma de apeluri de procedura, mesaje, evenimente, pipes
– Interactiunile pot fi si protocoale de comunicatie complexe, necesitand suportul
infrastructurii precum middleware, sisteme de operare, etc.
– Roluri: “interfetele”; de exemplu, un conector pipe poate fi descris avand 2 roluri,
“writer” si “reader”.
– Tipul unui conector: defineste natura interactiunilor, numarul si tipul rolurilor,
proprietatile cerute
• Relatii – attachment: definesc topologia sistemului
– specifica ce porturi ale componentelor se leaga la anumite roluri ale conectorilor
Exemplu: structura C&C
Informatii aduse de vederea C&C
• Care sunt elementele care apar in timpul executiei sistemului si
interactiunile dintre ele ? Care este dinamica acestui aspect in
cursul executiei ?
• Care sunt principalele surse de date ?
• Exista parti replicate in sistem ?
• Care sunt fluxurile de date prin sistem ?
• Ce protocoale de comunicatie utilizeaza elementele sistemului ?
Module Viewtype – C&C Viewtype
•Acelasi modul poate fi executat in mai multe componente
•Aceeasi componenta poate executa cod din mai multe module

[Clements] – fig.3.5
Allocation Structure
• Deployment:
– Descrie modul de mapare a elementelor software pe elemente
hardware
– Elemente:
• Componente software, definite in C&C
• Elemente de mediu: procesoare, elemente de stocare, de retea, etc.
– Relatii:
• Allocated-to, arata pe ce elemente de mediu sunt localizate elementele
software
• Migrates-to, copy-migrates-to, execution-migrates-to
– Utilizare: analiza: performance, availability, security; estimare costuri.
• Work assignement:
– Elemente:
• Software: module
• Elemente de mediu: persoana, echipa, subcontractor, etc
– Relati: Allocated-to
– Utilizare: project management
De ce e importanta arhitectura
software?

• Pentru ca reprezinta:
– Mijloc de comunicare intre stakeholders
– Primele decizii de proiectare
– Abstractizare transferabila a unui sistem
Arhitectura ca mijloc de
comunicare intre stakeholders
• Fiecare stakeholder este interesat de anumite
caracteristici ale sistemului
• Rolul proiectantului arhitecturii: gasirea strategiilor de a
echilibra caracteristicile diferite si/sau contradictorii
• Rolul arhitecturii: un limbaj comun in care se exprima,
negociaza si rezolva aceste caracteristici
– Arhitectura e suficient de abstracta ca sa poata descrie la un
nivel general inteligibil un sistem complex
– Arhitectura poate fi analizata din punct de vedere al principalelor
caracteristici/proprietati ale sistemului
Architectura ca decizie de
proiectare
• Defineste unele constrangeri privind implementarea
• Influenteaza structura organizationala
• Promoveaza anumite calitati ale sistemului (modifiability,
performance, safety, security, etc)
• Permite predictia calitatilor/proprietatilor sistemului
• Permite estimarea costurilor si termenelor de realizare
Arhitectura ca model transferabil,
reutilizabil
• Reutilizarea arhitecturii - Software product lines
• Arhitectura poate fi realizata utilizand componente
dezvoltate independent de externi
Arhitectura software

• Reprezinta:
Ce terminologie ?
– Mijloc de comunicare
intre stakeholders
– Primele decizii de De la ce se pleaca?
proiectare
– Abstractizare
transferabila a unui
sistem Terminologie comuna, bune practici,
obiceiuri, standarde,
solutii de succes cunoscute ….
PATTERNS
Concepte

Reference Model
Reference
Architecture
Design Architectural Software
Pattern Pattern Architecture
Architectural
Style Framework
Architectural Style
• “An architectural style defines a family of software systems in
terms of their structural organization. An architectural style
expresses components and the relationships between
them, with the constraints of their application, and the
associated composition and design rules for their
construction.”
[POSA1]/pag.394
• Exemplu: stilul Pipes-and-filters
– Componente: toate au acelasi tip, Filter.
• componente procesatoare de date, au 1 sau mai multe porturi de intrare si 1
sau mai multe porturi de iesire
– Relatii dintre 2 componente: conectori Pipe
• conector binar unidirectional care transmite fluxul de date de la un port de
iesire al unui filtru spre un port de intrare al altui filtru
– Constrangeri si reguli:
• Un filtru nu trebuie sa cunoasca identitatea filtrelor de la care primeste sau la
care transmite date
Architectural Pattern
• “An architectural pattern expresses a fundamental
structural organization schema for software systems.
It provides a set of predefined subsystems, specifies
their responsibilities, and includes rules and guidelines
for organizing the relationships between them.”
[POSA1]/pag.12
• Exemple:
– Model-View-Controller
– Broker
Design pattern
• “A design pattern provides a scheme for
refining the subsystems of a software system,
or the relationships between them. It describes a
commonly-recurring structure of communicating
components that solves a general design
problem within a particular context. [Go4]”
[POSA1]/pag.13

• Tipare de scara mai mica decat cele arhitecturale


• Independente de un limbaj de programare
• Aplicarea unor tipare din aceasta categorie nu afecteaza
structura fundamentala a unui sistem
Reference Models
• “A reference model is a division of functionality together
with data flow between the pieces. It is a standard
decomposition of a known problem into parts that
cooperatively solve the problem.”
[Bass]/&2.3
• Rezulta din experienta indelungata intr-un anumit
domeniu de aplicatie
• Sunt caracteristice domeniilor mature
• Exemple:
– Compilatoare: analiza lexicala, analiza sintactica, analiza
semantica, optimizare de cod, generare de cod,
– Retele: Modelul de referinta OSI
Reference Architectures
• “A reference architecture is a reference model mapped
onto software elements (that cooperatively implement
the functionality defined in the reference model) and the
data flows between them.”
[Bass]/&2.3
• Reference model defineste o descompunere a functionalitatilor
• Reference architecture defineste modul de mapare a
functionalitatilor pe niste definitii de subsisteme/componente
• Maparea poate fi 1-1 dar nu neaparat necesar
• Exemplu: CORBA (Common Object Request Broker Architecture)
Frameworks
• “A framework is a partially complete software system
that is intended to be instantiated. It defines the
architecture for a family of systems and provides the
basic building blocks to create them.”
[POSA1]/pag.396

• Defineste locurile unde se pot face insertii/adaptari la instantiere: hot


spots / frozen spots
• Instantierea: prin compunerea si subclasarea claselor furnizate de
framework
• Diferenta framework ↔ reference architecture: un framework este
dat sub forma de cod, reference architecture nu
• Diferenta framework ↔ biblioteca: la dezvoltarea unei aplicatii noi:
– biblioteca: scrii main body si utilizezi elemente (functii, clase, etc) din biblioteca
– framework: de obicei framework furnizeaza un main body predefinit, mai trebuie
adaugate/concretizate unele elemente (functii, clase) pe care acesta le
utilizeaza. “inversion of control”
Concepte

Reference Model
Reference
Architecture
Design Architectural Software
Pattern Pattern Architecture
Architectural
Style Framework
Continutul cursului
• Conceptul de arhitectura software
– Ce este arhitectura software ?
• Stiluri arhitecturale fundamentale
– Pipes and filters
– Layers
– Blackboard
– Event-driven
• Arhitecturi tipice pe domenii/tipuri de aplicatii:
– Adaptive
• Reflective
– Distribuite
• Client-server, Broker
– Enterprise
• Data access patterns
– Interoperability
Probleme de proiectare - Principii -Tehnologii

Problema de proiectare

Principii de proiectare
Tehnologii,
(Stiluri arhitecturale,
Framework-uri,
pattern-uri,
API-uri concrete
tactici, strategii)
Object Request Broker Pattern RMI, CORBA, .NET Remoting
Metalayer Architecture Java reflection, .NET Reflection
Data Access Patterns XML (JAXP, JAXB), SQL (JDBC)
Resurse
Laborator
• Exista o corelatie stransa intre laborator si continutul si ritmul
materiei de la curs
• Materie cu Evaluare Distribuita:
– 2 Lucrari scrise (L1, L2)
• Activitatea pe parcurs: Laborator
– 4 subiecte, fiecare subiect de laborator cuprinde 2 sau 3 “lucrari de
laborator”
– Nota la activitatea pe parcurs: media notelor subiectelor
– Este posibil ca unele subiecte sa contina parti optionale mai complexe
care ofere posibilitatea obtinerii de puncte bonus pentru lucrarea scrisa

• Calcul Nota Finala:


NotaExamen = PunctajLucrarea1 + PunctajLucrarea2 + 1PunctOficiu +
BonusLaborator
NotaFinala = round ((NotaExamen + NotaActivitateaParcurs)/2)
Pentru mai multe detalii: Web
• http://staff.cs.upt.ro/~ioana/arhit/

– Pagina web contine:


• Cuprins curs
• Slide-uri curs
• Teme laborator
• Bibliografie curs si resurse aditionale
Stiluri si tipare arhitecturale
fundamentale
Partea 1
Stiluri arhitecturale fundamentale
• Continutul cursului si bibliografie:
• Layers
• [POSA1] – in 2.2
• Pipes and Filters
• [POSA1] – in 2.2
• Blackboard; cu variantele Repository, Active Database
PART 1 • [POSA1] – in 2.2
• Event-driven (Implicit Invocation); cu variantele Publisher-Subscriber, Event-
Bus
• [POSA1] – din 3.6
• S. Gupta, J. Hartkopf, S. Ramaswamy: Event Notifier, a Pattern for Event
Notification, in Java Report, 1998 (republished as chapter 11 in the book More
Java Gems, Cambridge University Press, 2000)
http://sites.google.com/site/jeffhartkopf/notifier

• Bibliografie generala optionala:


• David Garlan, Mary Shaw, An Introduction to Software Architecture, online
http://www.cs.cmu.edu/afs/cs/project/able/ftp/intro_softarch/intro_softarch.pdf
Stilul arhitectural Layers

Bibliografie:
[POSA1] – in cap. 2.2
Layers
Stilul Layers (pe niveluri): adecvat aplicatiilor care
pot fi descompuse in grupuri de subtaskuri,
fiecare grup reprezentand un anumit nivel de
abstractizare. Fiecare nivel utilizeaza servicii
furnizate de nivelul(urile) de sub el

• Exemplu tipic:
– Stive de protocoale de retea
– Fiecare nivel se ocupa de un anumit aspect al
comunicarii in retea si utilizeaza serviciile nivelului
inferior
Exemplu tipic pentru Layers

[POSA]-Fig/P.31
Layers: Context & Problema
• Context:
– Un sistem de mari dimensiuni care necesita descompunere in
subsisteme (nu poate fi implementat monolitic)
• Problema:
– Caracteristica dominanta a sistemului este un amestec de
operatii de nivel inalt si de nivel scazut de abstractizare,
operatiile de nivel inalt depind de operatiile de nivel mai jos
– Uneori apare si o structurare pe orizontala, independenta de
structurarea verticala pe niveluri: mai multe operatii sunt pe
acelasi nivel de abstractizare, dar intre ele independente
(exemplu – nivelurile OSI unde apar mai multe functii insirate cu
and)
– Date initiale: specificatiile functionale pentru operatiile de nivel
inalt, descrierea unei platformei tinta, dar cu mentiunea de
portabilitate si pentru alte platforme.
Layers - Analiza
• Interfetele intre layers trebuie proiectate astfel incat sa fie
stabile (modificarile facute intr-un layer sa nu afecteze
celelalte)
• Partile sistemului (layers) trebuie sa fie inlocuibile (se
poate inlocui implementarea unui layer)
• Partile de nivel mai scazut (layers de la baza stivei)
trebuie proiectate astfel incat sa poata fi eventual
reutilizate si in alte sisteme
• Granularitatea descompunerii in layers trebuie bine
determinata !
– Granularitate prea mare: (prea putine layers de mari dimensiuni)
– Granularitate prea mica: (prea multe layers de mici dimensiuni)
Layers: Solutie - structura
• Sistemul este structurat pe
subsisteme organizate ca o
stiva de nivele
• Nivelul cel mai jos este
Layer1
• Nivelul cel mai sus este
LayerN
• Tiparul se bazeaza pe
restrictionarea relatiei
uses, aceasta fiind
permisa doar intre
anumite subsisteme:
• LayerJ is allowed to use
LayerJ-1

[POSA]-Fig/P.34
Layers: structura caracteristica
• Fiecare layer
ascunde layer-ele
de sub el fata de
layer-ele de
deasupra

[POSA]-Fig/P.35
Structura nivelurilor

[POSA]-Fig/P.35
Layers: Scenarii de comportament
• Top-down communication
• Bottom-up communication
Layers: top-down communication
EVENIMENT, CAUZA

calls

Directie permisa pentru


relatii de tip uses
Layers: Scenarii de comportament
• Top-down communication:
– un client adreseaza o cerere nivelului superior
LayerN. Acesta are nevoie de serviciile nivelului de
sub el pentru a rezolva cererea clientului. Layer N-
1 la randul sau va utiliza Layer N-2, etc, pana
ajunge la Layer 1.
– Variante: daca nivelurile implementeaza si
informatii de “stare”, este posibil ca comunicatia
nu ajunga pana la nivelul de jos, ci sa fie rezolvata
complet de un nivel intermediar
– De obicei, Layer J transpune o cerere primita de la
Layer J+1 in mai multe operatii cerute la Layer J-1,
considerate la un “nivel de abstractizare mai redus”
Layers:Bottom-up communication

Directie permisa pentru


relatii de tip uses

calls via callback

EVENIMENT, CAUZA
Layers: Scenarii de comportament
• Bottom-up communication:
– Un lant de actiuni este declansat din nivelul inferior
Layer1 (de ex un device driver detecteaza o
modificare). Layer1 trimite o notificare catre
Layer2, acesta incepe transformarea datelor
asociate si trimite o notificare catre Layer 3, etc.
– Trebuie realizata prin callback ! Acest
mecanism realizeaza un flux ascendent de
date si control, dar fara a rezulta relatii
Uses de tip ascendent
Paranteza despre
Mecanismul Callback
• Solutia pentru situatiile descrise de relatiile:
– FB calls FA dar A uses B si B does not use A
FA A

• Mecanismul Callback: numele rutinelor din


modulul A (de ex FA) de apelat din cadrul
modulului B sunt transmise de sus in jos, in
FB B
forma de date. Specificatia unui nivel inferior
include doar obligatia ca intr-o anumita situatie
(FB) sa apeleze rutina care i-a fost comunicata
mai sus
• Acest mecanism realizeaza un flux ascendent
de date si control, dar fara a rezulta relatii Uses
de tip ascendent -> nu contravine restrictiilor
stilului Layered
Exemplu situatie callback
• O aplicatie gestioneaza date despre studenti si
realizeaza diferite prelucrari asupra acestora,
inclusiv sortarea alfabetica. DomainLogic
• O alta aplicatie lucreaza cu reprezentarea unor
puncte geometrice in plan, printre prelucrarile uses
asupra acestora este si sortarea in ordinea
distantei fata de origine GenericUtilities
• Posibil ca alte aplicatii din alte domenii sa
necesite sortarea unor date
• Pentru toate aplicatiile, se va alege o arhitectura
de tip layers, cu 2 nivele
• Layer-ul Generic Utilities este refolosit intre
diferitele aplicatii si trebuie sa contina o rutina
generica de sortare
Exemplu situatie callback

main StudentAdministration
compare

sort
GenericUtilities
Posibilitati implementare callback
Layers: Pasi de definire a unei
arhitecturi pe nivele
Definirea criteriului de abstractizare: ce “inrudeste” elementele apartinand
aceluiasi nivel ?
De ex: distanta fata de HW, complexitatea conceptuala
Determinarea numarului de niveluri: compromis intre:
Prea multe: regie prea mare, probleme de performanta
Prea putine: structura deficitara
Numirea nivelurilor si atribuirea de functii:
Specificarea serviciilor:
Good practice: nivelurile inferioare implementeaza un numar restrans de servicii,
nivelurile superioare implementeaza un numar mai mare de servicii
Reconsiderarea pasilor anteriori, pana la solutia finala
Specificarea interfetelor nivelurilor
Asigura posibilitatea de a schimba implementarea unui nivel
Stabilirea structurii nivelurilor
Un nivel complex este implementat prin mai multe componente
Asigurarea decuplarii intre niveluri
Un nivel nu trebuie sa cunoasca identitatea nivelului de deasupra sa
Layers: variante
• Relaxed Layered Systems:
– se relaxeaza restrictia is-allowed-to-use:
• Un nivel poate utiliza toate nivelurile de sub el
– un nivel poate fi doar partial opac:
• Anumite servicii sunt vizibile doar nivelului imediat urmator, dar alte
servicii pot fi utilizate de toate nivelurile de deasupra
– Afecteaza negativ maintenability
• Merita utilizat in doar in sisteme care nu se modifica des si a caror
performanta e importanta
• Layering through inheritance
– Nivelul inferior = clasa de baza; Nivelurile superioare sunt
realizate prin mostenire (implementation inheritance) de la
nivelurile inferioare
– Fragile base class problem: o modificare a reprezentarii
datelor in clasa de baza (nivelul inferior) necesita recompilarea
tuturor celorlalte
– Nu e o idee buna!
Layers: Proprietati ale stilului
• Avantaje:
– Reusability: fiecare layer poate fi reutilizat individual, daca
implementeaza o abstractizare coerenta a unor servicii si are o interfata
bine definita si documentata
– Portability: interfetele standardizate ale nivelurilor permit limitarea
efectelor modificarilor in cadrul unui singur nivel
– Testability: nivelurile pot fi testate independent
– Exchangeability: se poate inlocui implementarea unui anumit nivel
• Atentionari:
– Cascades of changing behaviour: modificarea comportamentului unui
nivel poate avea efecte negative asupra comportamentului sistemului:
– Lower efficiency: daca la fiecare nivel apar transormari ale datelor
transferate, performanta este mai slaba decat in cazul unei
implementari monolitice
– Unnecessary work: daca nivelurile inferioare realizeaza operatii care nu
sunt cerute de nivelurile superioare
Layers: Observatii in concluzie
• Stitul arhitectural layers se bazeaza pe
restrictionarea directiilor permise ale relatiilor de
dependenta statica de cod (de tip uses)
• Restrictionarea directiilor permise ale relatiilor
de tip uses (si mai ales evitarea dependentelor
ciclice !) este pe de alta parte si un principiu
general pentru un design bun!
• Exista tool-uri care permit analiza relatiilor de
dependenta
– Exemple:
– NDepend, dependencyfinder, Lattix, JDepend, etc
– ART
Stilul arhitectural Pipes and Filters

Bibliografie:
[POSA1] – in cap. 2.2
Pipes and Filters
Pipes and Filters: structura adecvata pentru sistemele care
proceseaza fluxuri de date. Fiecare pas de procesare
este realizat de un Filtru. Datele sunt transmise intre
doua filtre succesive prin conducte (Pipes). Este posibila
recombinarea Filtrelor in alte sisteme.

• Exemplul cel mai tipic: pipeline de comenzi unix:


ls | grep old | more
Alt exemplu: domeniu aplicatie:
Signal processing&Virtual Instrumentation
Context & Problema
• Context: Procesarea fluxurilor de date
• Problema: o aplicatie care poate fi descompusa in
mod natural in mai multe etape de procesare;
– Este nevoie de flexibilitate in viitor, obtinuta prin
reordonarea componentelor (etapelor de procesare)
– Este posibila constructia unei familii de sisteme
asemanatoare prin utilizarea a diferite subseturi de
componente
– Componentele ne-adiacente nu utilizeaza informatii
comune
– Este luata in considerare posibilitatea ca etapele sa fie
rulate in regim multitasking
– Solutia nu este aplicabila aplicatiilor interactive, conduse
de evenimente
Solutie - structura
• Sistemul se descompune natural in etape de procesare
secventiala
• Fiecare etapa este implementata de o componenta de
tip Filtru
• Caracteristicile unui Filtru:
– Citeste date din fluxul de intrare
– Realizeaza un anumit tip de procesare pe datele de intrare
– Produce date pe fluxul de iesire
• Etapele de procesare sunt legate prin fluxul de date din
sistem
• Pipes (conducte):
– transporta fluxul de date intre 2 filtre consecutive
– Implementarea unei conducte poate utiliza diferite tehnici: apel
de functie, apeluri sistem pipe, etc.
[POSA]-Fig/P.56
Solutie - comportament
• Tipuri de Filtre:
– Pasive: activitatea lor este declansata explicit
de filtrul precedent (push) sau de filtrul
urmator (pull)
– Active: corpul filtrului consta dintr-un ciclu
continuu in care citeste-proceseaza-scrie date
• Daca filtrele sunt de tip activ, Pipe trebuie sa
realizeze si sincronizarea intre filtre active, prin
bufferare
• Citirea si producerea datelor trebuie facuta
incremental, pentru a reduce latenta si a permite o
eventuala procesare concurenta
Passive Filters:
Push pipeline vs Pull pipeline

[POSA]-Fig/P.58
Active Filter: Push/pull pipeline

[POSA]-Fig/P.60
Pasi de definire a unei arhitecturi
pipes-and-filters
• Divizarea functionalitatii sistemului intr-un numar de
stagii intermediare de procesare
• Definirea formatului datelor care se transmit pe fiecare
pipe
– Format uniform => flexibilitate maxima, dar poate afecta negativ
eficienta
• Alegerea tipului de pipe pentru fiecare conexiune. Tipul
de pipe influenteaza tipurile de filtre – pasive sau active
• Proiectarea filtrelor
– Rule of thumb: One filter should do one thing well => asigura
reutilizarea individuala
• Realizarea sistemului prin asamblarea filtrelor
Proprietati ale stilului
Pipes-and-filters
• Avantaje:
– Flexibilitate prin recombinare:
– Reusability pentru componentele filtru
– Dezvoltare rapida
– Posibilitate de procesare concurenta
• Atentionari:
– Imposibil de mentinut o informatie de stare comuna
accesibila in mod eficient tuturor filtrelor
– Overhead datorita operatiilor de transformare a
formatului datelor
– Error handling
Discutie:
Pipes-and-Filters vs Layers

Layer A
Filter A Filter B Filter C
Layer B

Layer C
Discutie:
Pipes-and-Filters vs anumiti
design patterns
Tiparul arhitectural Blackboard

Bibliografie:
[POSA1] – in cap. 2.2
Blackboard
Blackboard: tipar adecvat problemelor in care mai multe
subsisteme specializate, independente, contribuie la gasirea
unei solutii, lucrand pe date comune (accesibile tuturor inmod
egal)

• Exemplu: Inteligenta artificiala – recunoasterea vorbirii


• Date de intrare:
– vorbirea inregistrata ca waveform
– Sistemul accepta nu numai cuvinte izolate, ci si fraze
– Sintaxa frazelor si vocabularul utilizat sunt restrictionate in concordanta
cu un anumit tip de aplicatie (ex interogare baza de date)
• Date de iesire:
– reprezentare interna (comanda corespunzatoare) pentru fraza
recunoscuta
– La gasirea solutiei contribuie subsisteme independente, specializate pe
domenii diferite: acustica-fonetica, lingvistica, statistica
Exemplu pentru arhitectura BB
• Sistem de recunoastere a vorbirii
• HEARSAY-II

KS BB

Word Creation

Syllable Creation

Segmentation

[POSA]-Fig/P.70
Solutie - Blackboard
• Structura: o colectie de elemente independente (Knowledge
Sources) care lucreaza in acelasi timp pe o structura de date
comuna (Blackboard), in vederea rezolvarii unei probleme
• Fiecare KS este specializat pe o anumita parte a problemei
comune
• KS sunt independente: nu exista interactiuni directe intre ele
• Ordinea de activare a KS nu este prestabilita, ci rezulta in mod
dinamic in functie de evolutia datelor din BB.
– Poate utiliza o componenta centrala de control care evalueaza starea
curenta a BB si activeaza KS
• Continutul BB: Solution space – consta din solutii partiale
(hypotesis), la diferite nivele de abstractizare
• Pe parcursul rezolvarii problemei, KS produc noi ipoteze, modifica
gradul de incredere in valabilitatea unei ipoteze, sau elimina ipoteze
care se dovedesc false
Solutie - Blackboard

[POSA]-Fig/P.77
Solutie - Blackboard
• BB:
– Permite KS sa citeasca si sa
scrie date
• KS
– Conditie: evalueaza starea
curenta a solutiilor partiale din BB
si determina daca in aceste
conditii are ceva de facut
– Actiune: efectueaza calculele
specifice, acestea pot duce la
modificarea starii BB
• Control
– Monitorizeaza BB
– Activeaza activitatile de evaluare
sau de actiune ale KS

[POSA]-Fig/P.79
Scenariu exemplu

[POSA]-Fig/P.80
Pasi de definire a unei arhitecturi
Blackboard
• Definirea problemei: stabilirea domeniilor de cunostiinte implicate,
definirea intrarilor si a proprietatilor lor (zgomote, variatiuni)
• Definirea spatiului solutiei: solutii partiale/complete, de nivel
inalt/de nivel intermediar
• Divizarea procesului de rezolvare in pasi: defineste regulile dupa
care solutiile se transforma in solutii de un nivel de abstractizare mai
inalt;
• Stabilirea knowledge sources si a a sarcinilor acestora
• Definirea vocabularului BB: gasirea unei reprezentari a datelor
astfel incat toate KS sa poata scrie si citi din BB
• Descrierea controlului: Controlul implementeaza o strategie
oportunista care determina ce KS pot face modificari la BB. Tinta
este construirea unei ipoteze acceptabile (credibilitatea > prag)
• Implementarea KS: separarea in partea de conditie si partea de
actiune; o KS nu trebuie sa cunoasca celelalte KS sau componenta
de Control
Varianta - Repository
• Generalizare a Blackboard
• Nu exista o componenta centrala de control si
KS nu au partea de execCondition
• Ordinea de executie a KS este determinata de
utilizator sau de un program principal
• Exemple:
– Baze de date clasice
– CASE Toolset
Varianta – Active Database
• Varianta hibrida, rezultata din combinatia
cu stilul event-driven
• Activarea KS se face prin evenimente:
• initial, fiecare KS isi inregistreaza interesul
pentru o anumita portiune a bazei de date.
• Cand se intampla modificari in acea portiune,
KS este notificat;
• dispare ciclul de control extern in care KS
testeaza execCondition() (se muta in active
database)!
Proprietati ale stilului
Blackboard
• Avantaje:
– Permite experimentarea cu diferiti algoritmi si euristici
– Changeability
– Reusability pentru KS
– Fault tolerance
• Atentionari:
– Testability: redusa
– Low efficiency
– Complexitate ridicata la realizare
Concluzii privind
Stilurile arhitecturale fundamentale (1)
• descriu scheme de structurare a unui sistem din puncte
de vedere diferite
– Structura statica (Module viewtype): Layers
– Structura dinamica de runtime (Component & connector
viewtype): Pipes-Filters, Blackboard, Event-driven
• Sunt solutii elementare de structuri foarte simple
• In sisteme reale, pot apare in stare “pura” sau
combinate/hibridizate
Concluzii privind
Stilurile arhitecturale fundamentale (2)
• Alegerea unui anumit stil arhitectural pentru o aplicatie poate
influenta caracteristicile/calitatile proiectului !
• For further reading: David Garlan, Mary Shaw, An Introduction to
Software Architecture, Technical Report Carnegie-Mellon University,
no CMU-CS-94-166,
http://www.cs.cmu.edu/afs/cs/project/able/ftp/intro_softarch/intro_sof
tarch.pdf
– Analizeaza probleme diferite din punctul de vedere al
avantajelor/dezavantajelor aduse solutiei de aplicarea unui anumit stil
arhitectural
• Laborator: problema “Fabrica de mobila”
Laborator 1 “Fabrica de mobila”
• Stilul arhitectural ales influenteaza proprietatile solutiei !

P&F BB Events
Pot diversifica productia ? Doar la startup Da, la runtime Da, la runtime

Pot angaja muncitori noi ?

Pot schimba procesul tehnologic ?

Aplicatia poate fi testata usor ?

Concurenta se realizeaza usor ?

Concurenta este eficienta ?

Aplicatia este eficienta ?


Concluzii privind
Stilurile arhitecturale fundamentale (4)
• Sunt stiluri/tipare cu un grad foarte ridicat de abstractizare,
reprezinta solutii de organizare structurala independente de o
anumita paradigma de programare sau de o anumita tehnologie
– Componentele acestor tipare arhitecturale pot avea granularitati diferite,
de la obiecte, componente, si pana la aplicatii care sunt integrate
– For further reading: Enterprise Integration Patterns
– Carte: Enterprise Integration Patterns, by Gregor Hohpe and Bobby
Woolf, A Martin Fowler Signature Book, Addison Wesley, 2004
– Site asociat cartii: http://www.eaipatterns.com/
• Shared Database (Repository):
http://www.eaipatterns.com/SharedDataBaseIntegration.html
• Pipes and Filters: http://www.eaipatterns.com/PipesAndFilters.html
• Messaging (Event-Driven) http://www.eaipatterns.com/Messaging.html
Stiluri si tipare arhitecturale
fundamentale
Continuare – Partea a 2-a
Stiluri arhitecturale fundamentale
• Continutul cursului si bibliografie:
• Layers
• [POSA1] – in 2.2
• Pipes and Filters
• [POSA1] – in 2.2
• Blackboard; cu variantele Repository, Active Database
• [POSA1] – in 2.2
• Event-driven (Implicit Invocation); cu variantele Publisher-Subscriber, Event-
PART 2 Bus
• [POSA1] – din 3.6
• S. Gupta, J. Hartkopf, S. Ramaswamy: Event Notifier, a Pattern for Event
Notification, in Java Report, 1998 (republished as chapter 11 in the book More
Java Gems, Cambridge University Press, 2000)
http://sites.google.com/site/jeffhartkopf/notifier

• Bibliografie generala optionala:


• David Garlan, Mary Shaw, An Introduction to Software Architecture, online
http://www.cs.cmu.edu/afs/cs/project/able/ftp/intro_softarch/intro_softarch.pdf
Stilul arhitectural Event-driven
(Publisher-Subscriber, Event Bus)
Bibliografie:
[POSA1] – din cap. 3.6
S. Gupta, J. Hartkopf, S. Ramaswamy: Event Notifier, a
Pattern for Event Notification, in Java Report, 1998
(republished as chapter 11 in the book More Java Gems,
Cambridge University Press, 2000)
http://sites.google.com/site/jeffhartkopf/notifier
Stilul arhitectural Event-driven
Event-driven(Implicit invocation): componente
reactioneaza la evenimente produse de alte componente
necunoscute lor. Stilul suporta un grad mare de
dinamism in ceea ce priveste aparitia de noi
componentele participante si introducerea unor noi tipuri
de evenimente.

Event Service
op

op
Obj1 Obj2 Obj1 Obj2

Explicit invocation Implicit invocation


Stilul arhitectural Event-driven
• Componentele unei aplicatii nu interactioneaza direct
unele cu altele, ci prin invocare implicita
• Interactiunea implicita este facilitata de o infrastructura
de Event Service
• Interactiunea prin invocare implicita poate avea loc in
variantele (dupa tiparele):
– Publisher/Subscriber simplu (direct)
– Event Channel (Event Bus)
Publisher-Subscriber direct
• Publisher-Subscriber direct:
– Mecanisme incorporate in unele limbaje de programare: Java
Event – Listener, C# Event – delegate
– Mecanismul Callback, tiparul Observer
– ReactiveX, reactive Java Observable
http://reactivex.io/intro.html
https://github.com/ReactiveX/RxJava

– In toate aceste cazuri, Subscriber trebuie sa il cunoasca


pe Publisher !
Event Channel - Structura

Publisher
Publisher Subscriber
Subscriber

Event Channel (Event Bus)

Publisher
Publisher Subscriber
Subscriber

Publish Event
Receive Event
Event Channel - Descriere
Elementul central = tipurile de Evenimente
Exista componente care produc evenimente, dar nu cunosc identitatea
componentelor care vor “consuma” aceste evenimente (Publisher).
Este posibil ca mai multi publisheri sa produca acelasi tipuri de evenimente.
Exista componente care sunt interesate sa primeasca anumite tipuri de
evenimente, dar nu cunosc/nu le intereseaza identitatea componentelor
care le-au produs (Subscriber)
Este posibil ca un Subscriber sa fie interesat de mai multe tipuri diferite de
evenimente
Este posibil ca o componenta sa fie in acelasi timp Publisher si Subscriber
pentru diferite evenimente
Componentele participante (Publisheri sau Subscriberi) pot fi adaugate/scoase
in mod dinamic din sistem
Noi tipuri de evenimente pot fi adaugate in mod dinamic
Componetele pot fi localizate in procese distincte (distribuite)
Structura unei aplicatii Event-Driven
Componente (Elemente): Publishers, Subscribers
Connectori (Relatii): publish event, subscribe to event type
Infrastructura: Event Channel (Event Bus). De obicei nu face parte
din aplicatie !

Publisher
Publisher Subscriber
Subscriber

Event Channel (Event Bus)

Publisher
Publisher Subscriber
Subscriber
Structura unei aplicatii Event-Driven
Infrastructura Event Channel (Event Bus):
EventChannel: subscribe(Subscriber, Event); publish(Event)
Subscriber: notify(Event)

Publisher
Publisher Subscriber
Subscriber

Event Channel (Event Bus)

Publisher
Publisher Subscriber
Subscriber
Event Channel – Modele de
comunicare
De obicei, cand un eveniment este receptionat de (unul sau mai multi)
Subscriber-i, se realizeaza un transfer de date intre Publisher-ul
care a generat evenimentul si Subscriber-ii respectivi
Se pot defini 4 categorii de modele de comunicare, in functie de modul
in care se realizeaza acest transfer de date:
Push: Publisher-ul este sursa activa care initiaza transferul de date,
Subscriber este destinatie pasiva. Event Channel = Notifier
Pull: Subscriber initiaza (cere) transferul de date de la sursa (Publisher)
pasiva. Event Channel = Procurer
Hibrid Push/Pull: Publisher-ii si Subscriber-ii sunt initiatori activi ai
transferurilor, care au loc intr-un/dintr-un buffer de la Event Channel =
Queue
Hibrid Pull/Push: Publisher-ii si Subscriber-ii sunt entitati pasive, initiativa
transferurilor de date ii apartine lui Event Channel = Intelligent Agent
Push: Notifier

Active behaviour Passive behaviour

Publisher Subscriber

Push data Push data

Notifier

Publish Event
Receive Event
Data Transfer
Pull: Procurer

Passive behaviour Active behaviour

Publisher Subscriber

Pull data Pull data

Procurer

Publish Event
Receive Event
Data Transfer
Hybrid Push/Pull: Queue

Active behaviour Active behaviour

Publisher Subscriber

Push data Pull data

Queue

Publish Event
Receive Event
Data Transfer
Hybrid Pull/Push: Intelligent Agent

passive behaviour passive behaviour

Publisher Subscriber

Pull data Push data

Intelligent Agent

Publish Event
Receive Event
Data Transfer
Discutie: comparatie modele
Push/Pull
Avantaje/Dezavantaje
Utilitate (exemple situatii)
Posibilitati implementare
Structura unei aplicatii Event-Driven
Componente (Elemente): Publishers, Subscribers
Connectori (Relatii): publish event, subscribe to event type
Infrastructura: Event Channel (Event Bus). De obicei nu face parte
din aplicatie ! Poate fi un messaging/ event middleware de tip Java
Message Service, CORBA message service, etc

Publisher
Publisher Subscriber
Subscriber

Event Channel (Event Bus)

Publisher
Publisher Subscriber
Subscriber
Exemplu problema:
Network Management System
Managed Objects Management System

Router Hub Console Paging

Managed Objects: elemente de retea monitorizate; sunt in numar mare, de diverse


tipuri, si pot fi pornite sau oprite in mod dinamic. Cand sunt pornite, activitatea lor e
monitorizata de elemente din Management System.
Evenimente monitorizate: erori neasteptate in functionare (de diverse grade de
gravitate), indicatori de performanta
Management System: cuprinde elemente de tip console, pagere, e-mail. Fiecare
element din management system poate fi configurat sa urmareasca anumite categorii de
evenimente
Exemplu problema - continuare
• Pentru rezolvarea problemei de Network
Management in stil Event-driven, se utilizeaza o
infrastructura de tip Event Service (EventBus)
care ofera un API cu urmatoarele facilitati:
– subscribe
– publish
– inform - in orice Subscriber
• Managed Objects: Publishers
• Management System: Subscribers
Exemplu problema - continuare
• Tipuri de Evenimente:
Exemplu problema - continuare
• Un Subscriber:
public class PagingSystem extends Subscriber {
public PagingSystem() {
FaultEvent event = new FaultEvent();
CriticalFaultFilter filter = new CriticalFaultFilter();

EventService.instance().subscribe(filter.getClass(), filter, this);

}
public void inform(Event event) {
// Assumes that this subscriber has only subscribed to FaultEvent
FaultEvent faultEvent = (FaultEvent) event;

// Respond to the event


System.out.println("Critical Fault Event occurred:" + faultEvent);
}
}
Exemplu problema - continuare
• Un Publisher:
public class Router {
public static void triggerPublication() {

Event event = new FaultEvent(FaultEvent.CRITICAL);

EventService.instance().publish(event);

}
}
Exemple de infrastructuri
Event Service
• Infrastructuri de tip Event Bus care asigura un API de tip
publish-subscribe-notify pe evenimente
• Event Bus intra-proces:
– Guava (Google Core Libraries for Java) Event Bus:
http://code.google.com/p/guava-libraries/wiki/EventBusExplained
– Akka Event Bus http://doc.akka.io/docs/akka/current/java/event-
bus.html
• Event Channel (Event Bus) incorporat in infrastructuri
(middleware) pentru aplicatii distribuite (mesaje intre
procese diferite):
– Java Message Service (JMS)
Cum se poate implementa o
infrastructura de tip Event Bus ?

• S. Gupta, J. Hartkopf, S. Ramaswamy: Event


Notifier, a Pattern for Event Notification, in
Java Report, 1998 (republished as chapter 11
in the book More Java Gems, Cambridge
University Press, 2000)
http://sites.google.com/site/jeffhartkopf/notifier
Exemplu de implementare a unui
Event-Bus simplu intra-proces

• Punct de pornire: exemplul Network Management System

Managed Objects Management System

Router Hub Console Paging


Exemplu Network Management:
Solutie simplista
Managed Objects Management System

Hub Console

Router Paging System

Probleme:
•Solutie nescalabila: Fiecare Managed object trebuie sa trimita
direct notificari fiecarui obiect din management system
•Orice schimbare/adaugare in Management System (exemplu:
adaugare e-mail Notification) afecteaza toate Managed Objects
Exemplu Network Management:
Solutie tip Mediator
Managed Objects Management System

Hub Console

Mediator
Router Paging System

•Orice schimbare/adaugare in Management System (exemplu:


adaugare e-mail Notification) afecteaza doar Mediator
•Scalabilitate mai buna (numarul de dependente este n+m in loc
de n*m)
•Probleme:
•Nu suporta adaptarea dinamica si diferentiata a sistemului de
management (de ex fiecare managed object sa fie monitorizat
doar de un subset (eventual dinamic variabil) de obiecte din
Management System
Exemplu Network Management:
Solutie tip Observer
Subject Observer

Managed Objects Management System


Hub Console

Router Paging System

•Managed Objects nu trebuie sa cunoasca de dinainte multimea


de obiecte din management system pe care le notifica
•Probleme:
•Fiecare obiect din management system trebuie sa cunoasca
fiecare managed object pe care il monitorizeaza.
• Dezavantaje:
• Numarul de managed objects poate fi foarte mare
• Managed objects pot sa apara si sa dispara
Exemplu Network Management:
Solutie tip Event Channel
Publisher Subscriber
Managed Objects Management System

EventChannel Console
Hub

Router Paging System

Asigura o decuplare mult mai puternica intre Managed Objects si Management


System
Managed Objects nu cunosc identitatea obiectelor din Management System
Obiectele din Management System nu cunosc identitatea managed
Objects, ci doar tipurile evenimentelor generate de acestia
Event Channel
Asigura o decuplare mult mai puternica intre Publisher-i si
Subscriber-i
Publisher-ii nu cunosc identitatea Subscriber-ilor lor
Subscriberii nu cunosc identitatea Publisher-ilor, ci
doar tipurile evenimentelor generate de acestia
Intre Publisher si Subscriber se interpune un Event
Channel (asemanator Mediator)
Scenariu:
Concrete Subscriber se inregistreaza la Event Channel, specificand
tipul de evenimente de care este interesat
Concrete Publisher anunta la EventChannel producerea unui
eveniment
EventChannel determina ce Concrete Subscribers sunt interesati de
acest eveniment
Event Channel ii informeaza pe acestia de evenimentul produs
Exemplu Implementare
Event Notifier
[Gupta, Hartkopf, Ramaswamy]
EventService: intermediaza transmiterea de evenimente intre publisher
si subscriber
Publisher (Hub, Router): emite evenimente
Subscriber: interfata pentru toti consumatorii de evenimente
ConcreteSubscriber (Console, Pager): subscrie la EventService pentru
anumite tipuri de evenimente, trateaza evenimentele implementand
interfata Subscriber
Event: Baza ierarhiei de tipuri de evenimente
Filter: elimina evenimente care nu sunt de interes pentru un anumit
subscriber (de exemplu, un ConcreteSubscriber poate fi interesat de
un anumit tip de evenimente – de exemplu FaultEvent, cu exceptia
celor provenind de la un anumit Hub particular)
Discutie Implementare
Event Notifier
Subscriptia se bazeaza pe tipuri de evenimente si nu pe identitatea unui
publisher
Publisheri si Subscriberi sunt independenti. Cuplarea intre ei se reduce la
cunoasterea unui set de evenimente permise (semantica evenimentelor si
datele asociate)
Subscrierea la un anumit tip de eveniment cuprinde automat si toate subtipurile
sale
Filtrarea evenimentelor se poate face in plus fata de tipul evenimentului in
functie de alte atribute (de ex sursa evenimentului, datele asociate, etc)
Dezavantaj: type safety vs generalitate:
Class
isKindOf method in Event
Inform(event): cast la tipul (tipurile) asteptate de evenimente
Dezavantaj: Event Service e un point of bottleneck – performanta si fiabilitate
redusa. Solutie: mai multe EventServices, fiecare specializat intr-o anumita
categorie de evenimente
Facilitati optionale: Advertisment and Discovery of available Event Types
Variante ale stilului Event-Driven
• Active Database: combinatie cu
Blackboard
• Distributed Event Notification: combinatie
cu Broker
Concluzii privind
Stilurile arhitecturale fundamentale (1)
• descriu scheme de structurare a unui sistem din puncte
de vedere diferite
– Structura statica (Module viewtype): Layers
– Structura dinamica de runtime (Component & connector
viewtype): Pipes-Filters, Blackboard, Event-driven
• Sunt solutii elementare de structuri foarte simple
• In sisteme reale, pot apare in stare “pura” sau
combinate/hibridizate
Concluzii privind
Stilurile arhitecturale fundamentale (2)
•Alegerea unui anumit stil arhitectural pentru o aplicatie poate
influenta caracteristicile/calitatile proiectului !
• For further reading: David Garlan, Mary Shaw, An Introduction to
Software Architecture, Technical Report Carnegie-Mellon University, no
CMU-CS-94-166,
http://www.cs.cmu.edu/afs/cs/project/able/ftp/intro_softarch/intro_softar
ch.pdf
–Analizeaza probleme diferite din punctul de vedere al
avantajelor/dezavantajelor aduse solutiei de aplicarea unui anumit stil
arhitectural
•Laborator: problema “Fabrica de mobila”
Laborator 1 “Fabrica de mobila”
•Stilul arhitectural ales influenteaza proprietatile solutiei ! De exemplu:

P&F BB Events
Pot diversifica productia ? Doar la startup Da, la runtime Da, la runtime

Pot angaja muncitori noi ?

Pot schimba procesul tehnologic ?

Aplicatia poate fi testata usor ?

Concurenta se realizeaza usor ?

Concurenta este eficienta ?

Aplicatia este eficienta ?


Concluzii privind
Stilurile arhitecturale fundamentale (3)
• Sunt stiluri/tipare cu un grad foarte ridicat de abstractizare,
reprezinta solutii de organizare structurala independente de o
anumita paradigma de programare sau de o anumita tehnologie
– Componentele acestor tipare arhitecturale pot avea granularitati diferite,
de la obiecte, componente, si pana la aplicatii care sunt integrate
– For further reading: Enterprise Integration Patterns
– Carte: Enterprise Integration Patterns, by Gregor Hohpe and Bobby
Woolf, A Martin Fowler Signature Book, Addison Wesley, 2004
– Site asociat cartii: http://www.eaipatterns.com/
• Shared Database (Repository):
http://www.eaipatterns.com/SharedDataBaseIntegration.html
• Pipes and Filters: http://www.eaipatterns.com/PipesAndFilters.html
• Messaging (Event-Driven) http://www.eaipatterns.com/Messaging.html
Course contents
• Basic concepts
– What is software architecture ?
• Fundamental architectural styles
– Pipes and filters
– Layers
– Blackboard
– Event-driven
• Architectural patterns for :
– Adaptive systems
• The Reflection Pattern
– Distributed systems
• The Broker Pattern
– Data access patterns
• Pattern for Object-Relational Mappings
• Pattern for decoupling data access
A particular case of the Reflection Pattern:
Reflective programming languages

Bibliography:

Sun: The Java Tutorials – The Reflection API


http://download.oracle.com/javase/tutorial/reflect/index.html

IBM developerWorks: Java programming dynamics, Part 2: Introducing reflection


http://www.ibm.com/developerworks/library/j-dyn0603/

MSDN: Reflection
http://msdn.microsoft.com/en-us/library/f7ykdhsy.aspx
What is Reflection
• Reflection: the process by which a program can
observe and modify its own structure and behavior at
runtime.
• Based on RTTI (Run-Time Type Identification):
– RTTI: allows programs to discover at runtime and use at runtime
types that were not known at their compile time
– Non-RTTI / Traditional approaches:
• assume all types are known at compile time
• Polymorphism in OO languages: is a particular case of very limited
RTTI
Kinds of tasks specific to Reflection
• Inspection (introspection): analyzing objects and types
to gather information about their definition and behavior.
– Find the run-time type information of an object
– Find information about a type (supertypes, interfaces, members)
• Dynamic type discovery
• Manipulation: uses the information gained through
inspection to change the structure/behavior:
– create new instances of new types discovered at runtime
– dynamically invoke discovered methods
• Late binding: the types and methods used by a program are not
known at compile-time
– The most one could imagine to do in a reflective language:
restructure types and objects on the fly !
How is Reflection implemented
• Reflective capabilities need special support in language
and compiler !
– Java: java.lang.reflection
– .NET: System.Reflection
Reflection case study:
Reflection in Java
• java.lang.reflect
• Class java.lang.Class<T>
– For every type of object, the JVM instantiates an immutable
instance of java.lang.Class
– Instances of the class Class represent classes and interfaces in a
running Java application
– It is the entry point for all of the Reflection API
– Provides methods to examine the runtime properties of the object
including its members and type information.
– Provides the ability to create new objects of this type. It has no
public constructor, but Class objects are constructed automatically
by the JVM as classes are loaded
– T is the type of the class modeled by this class object. Use
Class<?> if the class is unknown.
The Reflection Logical Hierarchy in
Java

Object Class

compiled Field
class
file Method

Constructor

Member
Retrieving a Class object (1)
• If there is an object (an instance) of this class
available:

• Object.getClass(): If an instance of an object is available, then the


simplest way to get its Class is to invoke Object.getClass().

Rectangle r;

Class<?> c = r.getClass();

Class<?> c= "foo".getClass();
Retrieving a Class object (2)
• If the type is available but there is no instance:

• .class: If the type is available but there is no instance then it is


possible to obtain a Class by appending ".class" to the name of the
type. This is also the easiest way to obtain the Class for a primitive
type.
boolean b;
Class<?> c = b.getClass(); // compile-time error
Class<?> c = boolean.class; // correct
Retrieving a Class object (3)

• If the class is available as compiled code in a file on


the classpath:

• Class.forName(): If the fully-qualified name of a class is available,


and the file containing the compiled code is correctly put on the
runtime classpath, it is possible to get the corresponding Class using
the static method Class.forName()
Class<?> cString = Class.forName("java.lang.String;");
Retrieving a Class object (4)

• If the class is available as compiled code somewhere at a


URL:
• Each class object is constructed from bytecode by a java
classloader
• The default class loader loads from the local file system only,
directed by the classpath variable
• Other class loaders may load differently or from other locations.
URLClassLoader loads from a URL, that may point to a directory or
jar

URL[] urls = new URL[]{newURL("file:///home/pack.jar")};

URLClassLoader cl = new URLClassLoader(urls)

Class<?> c = cl.loadClass(“mypack.myclass”);
Inspecting a Class
• After we obtain a Class object myClass, we can:
• Get the class name
String s = myClass.getName() ;
• Get the class modifiers
int m = myClass.getModifiers() ;
bool isPublic = Modifier.isPublic(m) ;
bool isAbstract = Modifier.isAbstract(m) ;
bool isFinal = Modifier.isFinal(m) ;
• Test if it is an interface
bool isInterface = myClass.isInterface() ;
• Get the interfaces implemented by a class
Class [] itfs = myClass.getInterfaces() ;
• Get the superclass
Class<?> super = myClass.getSuperClass() ;
Discovering Class members
• fields, methods, and constructors
• java.lang.reflect.* :
– Member interface
– Field class
– Method class
– Constructor class
Class Methods for Locating Members
Inherited Private
List of
Member Class API members members
members?
? ?
getDeclaredField() no no yes
getField() no yes no
Field
getDeclaredFields() yes no yes
getFields() yes yes no
getDeclaredMethod() no no yes
getMethod() no yes no
Method
getDeclaredMethods() yes no yes
getMethods() yes yes no
getDeclaredConstructor() no N/A1 yes
getConstructor() no N/A1 no
Constructor
getDeclaredConstructors() yes N/A1 yes
getConstructors() yes N/A1 no
Working with Class members
• Members: fields, methods, and constructors
• For each member, the reflection API provides support to retrieve
declaration and type information, and operations unique to the member (for
example, setting the value of a field or invoking a method),
• java.lang.reflect.* :
– “Member” interface
– “Field” class: Fields have a type and a value. The java.lang.reflect.Field class
provides methods for accessing type information and setting and getting
values of a field on a given object.
– “Method” class: Methods have return values, parameters and may throw
exceptions. The java.lang.reflect.Method class provides methods for accessing
type information for return type and parameters and invoking the method on a
given object.
– “Constructor” class: The Reflection APIs for constructors are defined in
java.lang.reflect.Constructor and are similar to those for methods, with two major
exceptions: first, constructors have no return values; second, the invocation of a
constructor creates a new instance of an object for a given class.
Example: retrieving public fields
Class<?> c = Class.forName(“Dtest");

// get all public fields


Field[] publicFields = c.getFields();
for (int i = 0; i < publicFields.length; ++i) {
String fieldName = publicFields[i].getName();
Class <?> typeClass = publicFields[i].getType();
System.out.println("Field: " + fieldName + " of type " +
typeClass.getName());
}
Example
public class Btest public class Dtest extends Btest
{ {
public String aPublicString; public int aPublicInt;
private String aPrivateString; private int aPrivateInt;
public Btest(String aString) { public Dtest(int x)
// … {
} // …
}
public Btest(String s1, String s2) {
// … private void OpD1(String s) {
} // …
private void Op1(String s) { }
// …
} public String OpD2(int x){
protected String Op2(int x) { // …
// … }
}
public void Op3() {
// … }
}
}
Example: retrieving public fields
Class c = Class.forName(“Dtest");

// get all public fields


Field[] publicFields = c.getFields();
for (int i = 0; i < publicFields.length; ++i) {
String fieldName = publicFields[i].getName();
Class typeClass = publicFields[i].getType();
System.out.println("Field: " + fieldName + " of type " +
typeClass.getName());
}

Field: aPublicInt of type int


Field: aPublicString of type java.lang.String
Example: retrieving declared fields
Class c = Class.forName(“Dtest");

// get all declared fields


Field[] publicFields = c.getDeclaredFields();
for (int i = 0; i < publicFields.length; ++i) {
String fieldName = publicFields[i].getName();
Class typeClass = publicFields[i].getType();
System.out.println("Field: " + fieldName + " of type " +
typeClass.getName());
}

Field: aPublicInt of type int


Field: aPrivateInt of type int
Example: retrieving public constructors
// get all public constructors

Constructor[] ctors = c.getConstructors();


for (int i = 0; i < ctors.length; ++i) {
System.out.print("Constructor (");
Class[] params = ctors[i].getParameterTypes();
for (int k = 0; k < params.length; ++k)
{
String paramType = params[k].getName();
System.out.print(paramType + " ");
}
System.out.println(")");
}

Constructor (int )
Example: retrieving public methods
//get all public methods

Method[] ms = c.getMethods();
for (int i = 0; i < ms.length; ++i) {
String mname = ms[i].getName();
Class retType = ms[i].getReturnType();
System.out.print("Method : " + mname + " returns " + retType.getName() + "
parameters : Method
( "); : OpD2 returns java.lang.String parameters : ( int )
Class[] params = ms[i].getParameterTypes();
Method : Op3 returns void parameters : ( )
for (int k = 0; Method
k < params.length; ++k)
: wait returns void parameters : ( )
{ Method : wait returns void parameters : ( long int )
String paramType
Method : wait = params[k].getName();
returns void parameters : ( long )
System.out.print(paramType
Method : hashCode returns+ " "); int parameters : ( )
} Method : getClass returns java.lang.Class parameters : ( )
System.out.println(")
Method ");: equals returns boolean parameters : ( java.lang.Object )
} Method : toString returns java.lang.String parameters : ( )
Method : notify returns void parameters : ( )
Method : notifyAll returns void parameters : ( )
Example: retrieving declared methods
//get all declared methods

Method[] ms = c.getDeclaredMethods();
for (int i = 0; i < ms.length; ++i) {
String mname = ms[i].getName();
Class retType = ms[i].getReturnType();
System.out.print("Method : " + mname + " returns " + retType.getName() + "
parameters : ( ");
Class[] params = ms[i].getParameterTypes();
for (int k = 0; k < params.length; ++k)
{
String paramType = params[k].getName();
System.out.print(paramType + " ");
}
System.out.println(") ");
}
Method : OpD1 returns void parameters : ( java.lang.String )
Method : OpD2 returns java.lang.String parameters : ( int )
Using Reflection for
Program Manipulation
• Previous examples used Reflection for
Introspection only
• Reflection is a powerful tool to:
– Creating new objects of a type that was not known at
compile time
– Accessing members (accessing fields or invoking
methods) that are not known at compile time
Using Reflection for
Program Manipulation

Object Class

get/set

compiled invoke
Field
class
file
MyNewClass.class Method

Constructor
Creating new objects
• Using Default Constructors
– java.lang.reflect.Class.newInstance()

Class c = Class.forName(“java.awt.Rectangle”) ;
Rectangle r = (Rectangle) c.newInstance() ;

• Using Constructors with Arguments


– java.lang.reflect.Constructor. newInstance(Object... initargs)

Class c = Class.forName(“java.awt.Rectangle”) ;
Class[] intArgsClass = new Class[]{ int.class,
int.class } ;
Object[] intArgs = new Object[]{new Integer(12),new
Integer(24)} ;
Constructor ctor = c.getConstructor(intArgsClass) ;
Rectangle r = (Rectangle) ctor.newInstance(intArgs) ;
Example
String className = "java.lang.String";

Class<?> c;

try {
c = Class.forName(className);
Class<?>[] stringArgsClass = new Class[] { String.class };
Object[] stringArgs = new Object[] { new String("abc") };
Constructor<?> ctor = c.getConstructor(stringArgsClass);

Object something = ctor.newInstance(stringArgs);


System.out.println(something.getClass().getName());
System.out.println(something);
} catch (Exception e) {
e.printStackTrace();

}
Accessing fields
• Getting Field Values
Rectangle r = new Rectangle(12,24) ;
Class c = r.getClass() ;
Field f = c.getField(“height”) ;
Integer h = (Integer) f.get(r) ;
• Setting Field Values
Rectangle r = new Rectangle(12,24) ;
Class c = r.getClass() ;
Field f = c.getField(“width”) ;
f.set(r,new Integer(30)) ;
// equivalent with: r.width=30
Invoking methods
String s1 = “Hello ” ;
String s2 = “World” ;
Class c = String.class ;
Class[] paramtypes = new Class[] { String.class } ;
Object[] args = new Object[] { s2 } ;
Method concatMethod =
c.getMethod(“concat”,paramtypes) ;
String result = (String)
concatMethod.invoke(s1,args) ;
// equivalent with result=s1.concat(s2);
String className = "java.lang.String";
String methodName="length";

Class<?> c;

c = Class.forName(className);
Class<?>[] stringArgsClass = new Class[] { String.class };
Object[] stringArgs = new Object[] { new String("abc") };
Constructor<?> ctor = c.getConstructor(stringArgsClass);

Object something = ctor.newInstance(stringArgs);


System.out.println(something.getClass().getName());

Class<?>[] paramtypes = new Class[] {};


Object[] argsM = new Object[] {};
Method lengthMethod = c.getMethod(methodName, paramtypes);

System.out.println(lengthMethod.invoke(something, argsM));
Accessible Objects
• Can request that Field, Method, and Constructor objects be
“accessible.”
– Request granted if no security manager, or if the existing security
manager allows it
• Can invoke method or access field, even if inaccessible via privacy
rules !
• AccesibleObject Class: the Superclass of Field, Method, and
Constructor
• boolean isAccessible( )
– Gets the value of the accessible flag for this object
• static void setAccessible( AccessibleObject[] array, boolean flag )
– Sets the accessible flag for an array of objects with a single security
check
• void setAccessible( boolean flag )
– Sets the accessible flag for this object to the indicated boolean value
Uses of Reflection - Examples

Example 1:
Class Browsers
Uses of Reflection - Examples
• Serialization/deserialization in java: the
mechanisms of writing the state of an object into
a stream and later retrieving the object from the
stream
• Serialization could not be implemented without
reflection
Student s1 =new Student(211,“John");

FileOutputStream fout=new FileOutputStream("f.txt");


ObjectOutputStream out=new ObjectOutputStream(fout);

out.writeObject(s1);
Uses of Reflection
• Extensibility Features :
– An application may make use of external, user-defined classes by
creating instances of extensibility objects using their fully-qualified
names.
• Class libraries that need to understand a type’s definition
– Typical example = Serialization
• Class Browsers and Visual Development Environments
– A class browser needs to be able to enumerate the members of
classes. Visual development environments can benefit from making use
of type information available in reflection to aid the developer in writing
correct code.
• Debuggers and Test Tools
– Debuggers need to be able to examine private members on classes.
Test harnesses can make use of reflection to systematically call a
discoverable set APIs defined on a class, to insure a high level of code
coverage in a test suite.
Drawbacks of Reflection
• If it is possible to perform an operation without using reflection, then
it is preferable to avoid using it, because Reflection brings:
• Performance Overhead
– Because reflection involves types that are dynamically resolved, certain
Java virtual machine optimizations can not be performed. Consequently,
reflective operations have slower performance than their non-reflective
counterparts
• Security Restrictions
– Reflection requires a runtime permission which may not be present
when running under a security manager.
• Exposure of Internals
– Since reflection allows code to perform operations that would be illegal
in non-reflective code, such as accessing private fields and methods,
the use of reflection can result in unexpected side-effects, which may
render code dysfunctional and may destroy portability. Reflective code
breaks abstractions and therefore may change behavior with upgrades
of the platform.
Another Reflection case study:
Reflection in .NET
• System.Reflection
• What can you do with the System.Reflection API:
– Enumerate modules and types of an assembly;
– For each type, obtain its base type, implemented interfaces,
fields, methods, properties, events
– Create instances of types, dynamically invoke methods
The Reflection Logical Hierarchy in
.NET
Assembly
Module

Type

Object MemberInfo
MSIL code FieldInfo
(exe, dll)
PropertyInfo

EventInfo
MethodBase
MethodInfo

ConstructorInfo
Member
Example (C#) : Introspection
Assembly a = Assembly.LoadFile(args[0]);
// Find Modules
foreach (Module m in assem.GetModules()) {
WriteLine(1, "Module: {0}", m);
// Find Types
foreach (Type t in m.GetTypes()) {
WriteLine(2, "Type: {0}", t);
// Find Members
foreach (MemberInfo mi in t.GetMembers())
WriteLine(3, "{0}: {1}", mi.MemberType, mi);
}
}
Conclusions
• Reflective capabilities need special support at the levels
of language (APIs) and compiler
• Language (API) level:
– Java: java.lang.reflection
– .NET: System.Reflection
– Very similar hierarchy of classes supporting reflection
(Metaclasses)
• Compiler level:
– Speciffic type informations are saved together with the
generated code (needed for type discovery and introspection)
– The generated code must contain also code for automatically
creating instances of the Metaclasses every time a new type is
defined in the application code
Lab Assignments
Many Choices:

Versions A: using reflective features of


programming languages
1. Implementing MySerialization
2. Implementing MyReverseEngineeringTool
3. Implementing MyAlienInvaderGame

Version B: implementing a reflective architecture


– next week discussion
Course contents
• Basic concepts
– What is software architecture ?
• Fundamental architectural styles
– Pipes and filters
– Layers
– Blackboard
– Event-driven
• Architectural patterns for :
– Adaptive systems
• The Reflection Pattern
– Distributed systems
• The Broker Pattern
– Data access patterns
• Pattern for Object-Relational Mappings
• Pattern for decoupling data access
The Reflection Pattern
• Bibliography:
– The architectural Reflection pattern, in general:
• [POSA1], [POSAforDummies]
– Detailed Design methods for meta-objects:
• Dirk Riehle, Michel Tilman, Ralph Johnson: The Dynamic
Object Model, PLOP 2000,
http://hillside.net/plop/plop2k/proceedings/Riehle/Riehle.pdf
• Joseph Yoder, Ralph Johnson: The Adaptive Object-Model
Architectural Style, WICSA 2002,
http://www.adaptiveobjectmodel.com/WICSA3/ArchitectureOfAOMsWICSA3.pdf
Reflection
The Reflection architectural pattern provides a mechanism
for changing structure and behavior of software systems
dynamically.
In this pattern, an application is split into two parts. A meta
level provides information about selected system
properties and makes the software self-aware. A base
level includes the application logic. Its implementation
builds on the meta level. Changes to information kept in
the meta level affect subsequent base-level behavior.

[POSA1]
Reflection – The principle
• A precondition for doing changes is to be aware of the
current condition => a “mirror” is needed
• A self-aware software system is built on 2 levels:
• Meta level
• Base level

• There is a protocol that governs the interaction with the


MetaLevel:
• Meta Object Protocol
Reflection – The Structure

[POSA]-Fig/P.199
Reflection – The Elements

[POSA]-Fig/P.197
Reflection Example
• Example: Configuring application at
runtime by adding/updating components at
runtime
– Application is created or updated by reading
config files and executing the commands
found there
– Base level: static parts
– Meta level: variable parts
– MOP: config file editor/interpreter
Kinds of Reflection
• A taxonomy, according to:
– How much can be done via reflection:
• Introspection
• Intercession/Manipulation/Adaptation
– What it reflects:
• Structural reflection
• Behavioural reflection
• Reflective towers: meta-meta-meta-….
Reflection Taxonomy
Types of Reflection:
Find Examples
• Structural introspection: …

• Structural manipulation: …
–!
• Behavioural introspection: …

• Behavioural manipulation: …
Meta level
• Meta level:
– provides a self-representation of the software to give
it knowledge of its own structure and behavior
– It consists of metaobjects. Metaobjects encapsulate
and represent information about the software.
• Examples of metaobjects include: type structures, algorithms,
or even function call mechanisms.
Base level
• Base level:
– The base level defines the application logic.
– Its implementation uses the metaobjects to remain
independent of those aspects that are likely to
change.
• Base-level components may only communicate with each
other via a metaobject that implements a specific interaction
mechanism. Changing this metaobject changes the way in
which base-level components communicate, but without
modifying the base-level code.
Meta Object Protocol
• Meta Object Protocol (MOP):
– An interface for manipulating the metaobjects.
– It allows clients to request particular changes on the
metaobjects.
– The metaobject protocol itself is responsible for
checking the correctness of the change specification,
and for performing the change. Every manipulation of
metaobjects through the metaobject protocol affects
subsequent base-level behavior
Designing a reflective architecture
Case study
• Case study: Persistence Component in C++:
– We want to develop a persistence component that is
independent of specific type structures. However, to
store and read arbitrary C++ objects, we need
dynamic access to their internal structure.
Persistence component:
A bad solution
• Bad solution: implementing type-specific store and read
methods
• Disadvantages: expensive and error-prone. Whenever
we change the class structure of the application we
must modify these methods as well.

[POSA]-Fig/P.193
Persistence component:
Solution using Reflection
• We want to develop a persistence component
that is independent of specific type structures
• Solution with Reflection:
– Base level: user application (contains objects to be
serialized)
– Meta level: metaobjects that reflect base level objects
• Most difficult design task: finding out which
metaobjects are needed
– Where are they actually implemented ?
Steps for designing a reflective
architecture
1. Identify varying behavior
2. Identify structural aspects of the system, which, when
changed, should not affect the implementation of the
base level
3. Define the metaobjects. For every aspect identified in
the previous steps, define appropriate metaobjects.
4. Define the metaobject protocol. Support a defined and
controlled modification and extension of the meta level
• options for implementing the MOP:
– Integrate it with the metaobjects.
– Implement the metaobject protocol as a separate component.
5. Define Base Level
Designing the Persistence Component:
Steps 1-2:
1. Identify variable behavior:
– New types, objects that are instances of these types, must be
handled (serialized) without modifying the Persistence
Component
2. Identify aspects that do not change/ arte not allowed to
change:
– Existing types cannot change
Designing the Persistence Component:
Step 3:
3. Define the metaobjects:
– Persistence component itself is part of the Base Level:
reads/writes objects
– Metaobjects: give information about runtime types (
introspection only; in this example there are no changes of the
types allowed).
– Most difficult step: choosing the right types of metaobjects !
Finding out the metaobjects (1)
Start from the scenario for writing an object:
1. We must know its class => A metaobject of type Type-Info
(similar with Class); this metaobject must be retrieved
starting from an object
2. We must know the internal structure (the fields) of an object. =>
from a Type-Info metaobject we must retrieve Data-Info
(similar with Field) metaobjects.
3. For every field, if it is not a primitive type, recursiveley apply
steps 1-2
4. If a field is of a primitive type, write its value in the output
stream

The writing scenario requires following metaobject types:


Type-Info, Data-Info
Finding out the metaobjects (2)
Start from the scenario of reading an obiect:
• We need to instantiate an object of a type with a given name
=> a metaobject of type ObjectCreator (similar to
Class.newInstance)
• From the Type-Info of the created object we wil know its internal
structure (fields) (retrieve Data-Info metaobjects)
1. For every field, if it is not a primitive type, recursiveley apply
steps 1-2
2. If a field is of a primitive type, set it to the value read from the
input stream

The reading scenario requires following metaobject types:


ObjectCreator, Type-Info, Data-Info
Finding out the metaobjects (3)
• Main metaobject types:
– Type-Info
– Data-Info
– ObjectCreator

– Others:
• Base-Info
Example: Reading a object

Creates an object
– instance of a
type given by its
name

[POSA]-Fig/P.201
Designing the Persistence Component:
Step 4:
4. Defining the MetaObjectProtocol (MOP):
• Functions that modify the meta-layer:
– Create a new Type-Info metaobject newTypeId(typeName)
– Modify a Type-Info object, adding information
newTypeInfo(typeName, isBuiltIn, isPointer)
– Create a new Base-Info metaobject and modify a Type-Info by
addBase(typeName, baseName)
– Create metaobjects for the fields and modify aType-Info by: addData
(typeName, memberTypeName, memberName)
– Modify the ObjectCreator: addCreationCode(typeName)
• Functions that return info from the meta-layer:
– ObjectCreator.createObject(typeName) -> BaseLevelObject, TypeInfo
– TypeInfo.isBuiltIn
– TypeInfo.getData -> TypeInfo
Example: Updating metaobjects

[POSA]-Fig/P.203
Designing the Persistence Component:
Step 5:
5. Defining the Base Level:
– Persistence component is the Base Level
– Implements readObject and writeObject as discussed before
Reflection - Conclusions
• Advantages
– Modifying a system without changing code
– Supports structural or behavioral changes
• Liabilities
– Modifications at the meta level may cause damage. Even the
safest metaobject protocol does not prevent users from
specifying incorrect modifications.
– Increased number of components: more metaobjects than
base-level components.
– Lower efficiency. Reflective software systems are usually slow.
The base level consults the meta level. This reflective capability
requires extra processing: information retrieval, changing
metaobjects, consistency checking.
Other examples using the
Reflection pattern
• Mostly known from reflective programming languages
– CLOS (Common Lisp Object System)
• But the Reflection Pattern is used also in other different
domains !
– Dynamic architectures, adaptive architectures:
• Operating systems ex: Apertos
• Middleware: OpenORB, TAO
• Reflective Component frameworks: OpenCOM, Fractal
Reflection – Patterns for the
Detailed Design

• The description of the architectural pattern


specifies only the existence of a meta-layer and
a base-layer, no other details

• Patterns/methods/ideas for the detailed design:


– Dirk Riehle, Michel Tilman, Ralph Johnson: The
Dynamic Object Model, PLOP 2000,
http://hillside.net/plop/plop2k/proceedings/Riehle/Riehle.pdf
– Joseph Yoder, Ralph Johnson: The Adaptive Object-
Model Architectural Style, WICSA 2002,
http://www.adaptiveobjectmodel.com/WICSA3/ArchitectureOfAOMsWICSA3.pdf
Dynamic Object Model
• Goal: allow the types of objects to change at
runtime. This includes adding new types,
changing existing types, and changing the
relationships between types.
• Solution: Dynamic Object Model (Adaptive
Object Model, Runtime Domain Model)
– Composed from patterns Type Object and Property
List
– Bibliography:
• D.Riehle, M.Tilman, R.Johnson: Dynamic Object Model,
PLOP2000 http://hillside.net/plop/plop2k/proceedings/Riehle/Riehle.pdf
Motivating Example
• A banking system for handling customer accounts
• A class hierarchy of account classes is not feasible, because:
– more than 500 types of accounts
– Not all account types are known from the beginning
– Creating a new account type means changing source code (subtype)
The Dynamic Object Model
Dynamic Object Model Pattern =
Type Object Pattern +
Property List Pattern
Type Object
• Classical OO approach: a subclass for every new type
– Introducing a new type needs new code
• The metaclass ComponentType: instances of this class
replace subclasses
– Allows introducing new types at runtime
– Allows modifying the type of an object at runtime (example: an
account is transformed from CheckingAccount in VIPAccount)
• Here comes also the problem of converting attributes, but with
TypeObject the user has the control over the process
Type Object - Example

SavingsAccountType=new AccountType(“SavingsAccount”)
SavingsAccount1 = new Account(SavingsAccountType);
SavingsAccount2 = new Account(SavingsAccountType);
CurrentAccountType=new AccountType(“CurrentAccount”);
CurrentAccount1 = new Account(CurrentAccountType);
Property List
• Allows instances of the
same type to have
different kinds of
attributes
• Makes it possible to add
or remove attributes at
runtime
Property List - Example

Account1=new Account();
Account1.addProperty(“OverdrawLimit”,
Float.class, new Float(1000.0));
Account2 = new Account();
Account2.addProperty(“DepositTerm”,
Integer.class, new Integer(12));
Accounts problem solved: with
Type Object and Property List
Type Object: AccountType:
new types of accounts can
be dynamically created

PropertiesList: each
account has its own set of
properties

Type Object: PropertyType:


controls the allowed types
of properties for a certain
type of account
Accounts Example – The Solution
PropertyType OverdrawLimit = new PropertyType("overdrawLimit", Integer.class);
PropertyType DepositTerm = new PropertyType("depositTerm", Integer.class);
PropertyType OwnerName = new PropertyType("ownerName", String.class);

AccountType SavingsAccount = new AccountType("SavingsAccount");


SavingsAccount.addPropertyType(DepositTerm);
SavingsAccount.addPropertyType(OwnerName);

AccountType AnonymousSavingsAccount = new AccountType("AnonymousSavingsAccount");


AnonymousSavingsAccount.addPropertyType(DepositTerm);

AccountType CurrentAccount = new AccountType("CurrentAccount");


CurrentAccount.addPropertyType(OverdrawLimit);

Account aSavingsAccount1 = new Account(SavingsAccount);


Account aSavingsAccount2 = new Account(SavingsAccount);
Account aCurrentAccount = new Account(CurrentAccount);

aSavingsAccount1.setProperty("depositTerm", new Integer(12));


aSavingsAccount1.setProperty(“overdrawLimit”, new Integer(1000)); // will be not allowed
aSavingsAccount1.setProperty(“ownerName”, new Integer(100)); // will be not allowed
Accounts example – the solution
PropertyType OverdrawLimit = new PropertyType("overdrawLimit", Integer.class);
PropertyType DepositTerm = new PropertyType("depositTerm", Integer.class);
PropertyType OwnerName = new PropertyType("ownerName", String.class);

AccountType SavingsAccount = new AccountType("SavingsAccount");


SavingsAccount.addPropertyType(DepositTerm);
SavingsAccount.addPropertyType(OwnerName);

AccountType AnonymousSavingsAccount = new AccountType("AnonymousSavingsAccount");


AnonymousSavingsAccount.addPropertyType(DepositTerm);
Implementation of setProperty
(and of other operations) can
AccountType CurrentAccount = new AccountType("CurrentAccount");
can and must do verifications!
CurrentAccount.addPropertyType(OverdrawLimit);

Account aSavingsAccount1 = new Account(SavingsAccount);


Account aSavingsAccount2 = new Account(SavingsAccount);
Account aCurrentAccount = new Account(CurrentAccount);

aSavingsAccount1.setProperty("depositTerm", new Integer(12));


aSavingsAccount1.setProperty(“overdrawLimit”, new Integer(1000)); // proprietate nepermisa
aSavingsAccount1.setProperty(“ownerName”, new Integer(100)); // valoare incompatibila
Dynamic Object Model (Type Square)

Meta Level, Knowledge Level Base Level, Operational Level


Steps for defining a reflective
architecture [POSA]
• Example: The Dynamic Object Model problem
1. Identify variable aspects
Needs to modify types at runtime:
– Add a new type
– Modify an existing type (add new attributes)
2. Identify what is not allowed to not change
3. Define the metaobjects
• ComponentType (AccountType), PropertyType
4. Define the MetaObjectProtocol (MOP)
• Operations that modify the meta-layer:
– New AccountType
– New PropertyType
– AccountType.addPropertyType
• Operations that retrieve data from the meta-layer
– Account.getType
– Account.getPropertyTypes
Dynamic Object Model - Conclusions
• Advantages:
– Allows changes:
• Runtime typing
• Runtime object type creation
• Domain-speciffic typing
• Controlled dynamic type changing
• Runtime component type modification
– Reduces the number of classes
• Drawbacks
– Increased number of objects
– Increased design complexity
– Increased runtime complexity
• Limitations:
– Deals only with structural aspects ! -> behavioural aspects completed
by the Adaptive Object Model
The Adaptive Object-Model
Architectural Style
• Completes the Dynamic Object Model by adding:
– Business Rules
– Interpreters
• It builds a complete Domain Model: metadata represent application
types with attributes, relations and behavior
• The Domain Model can be described by a non-programmer, using a
domain specific description language
– The description can be stored, reused, modified, etc
– The description is interpreted at runtime
– The interpreter is needed at 2 different stages:
• Initialize/modify metaobjects that describe the domain
• Create objects of the base level and applies business rules

• Bibliography:
– Joseph Yoder, Ralph Johnson: The Adaptive Object-Model Architectural Style,
WICSA 2002,
http://www.adaptiveobjectmodel.com/WICSA3/ArchitectureOfAOMsWICSA3.pdf
Representing Business Rules

•Business Rules can be represented as Strategy/RuleObject/Composite of


RuleObjects attached to an EntityType (ComponentType)
•Describing Business Rules belongs to the Domain Model
A Domain Specific Language for
AOM
• NewEntityType <entityTypeName>
• NewPropertyType <propTypeName,
propTypeDescription>
• AddPropType <entityTypeName, propTypeName>
• RemovePropType <entityTypeName, propTypeName>
• AddRule <entityTypeName, ruleName,
ruleDescription>

• NewEntity<entityName,entityTypeName>
• AddNewProperty<entityName, propTypeName,
propValue>
• GetPropValue<entityName, propTypeName>
• applyRule<entityName, ruleName>
Example: Interpreting applications
from different domains

Commands
for describing
the
application
domain
Interpreter

Commands for
running a
particular
application
Example 1:
Managing bank accounts
• NewEntityType CheckingAccount
• NewPropertyType Owner, String
• AddPropType CheckingAccount, Owner
• NewEntityType SavingsAccount
• NewPropertyType InterestRate, Double
• AddPropType SavingsAccount, InterestRate
• NewEntity BobsCheckingAccount, CheckingAccount
• AddNewProperty BobsCheckingAccount, Owner, “Bob Bobbson”
• NewEntity JohnsCheckingAccount, CheckingAccount
• AddNewProperty JohnsCheckingAccount, Owner, “John Jones”
• RemovePropType CheckingAccount, Owner
Example2:
Shop inventory
• NewEntityType Cheese
• NewPropertyType Valability, Integer
• NewPropertyType ManufacturingCountry, String
• AddPropType Cheese, Valability
• AddPropType Cheese, ManufacturingCountry
• AddRule Cheese, Price, 10-
Valability+Lookup(ManufacturingCountry)
• NewEntity CheeseDorna, Cheese
• AddNewProperty CheeseDorna, Valability,6
• AddNewProperty CheeseDorna, ManufacturingCountry,
Romania
• NewEntity CheeseEmmental, Cheese
• AddNewProperty CheeseEmmental, Valability, 12
• AddNewProperty CheeseEmmental, ManufacturingCountry,
Germania
• applyRule CheeseDorna, Price
Adaptive Object Model -
Conclusions
• Advantages:
– Appropriate for systems that must support continuous changes
at their runtime
– Users(non-programmers) can modify at runtime the business
model
• Disadvantages:
– Complex, needs tool support (Interpretors, GUI, Domain Specific
Languages) in order to make it usable
– Performance (time)
Continutul cursului
• Conceptul de arhitectura software
– Ce este arhitectura software ?
• Stiluri arhitecturale fundamentale
– Pipes and filters
– Layers
– Blackboard
– Event-driven
• Arhitecturi tipice pe domenii/tipuri de aplicatii:
– Adaptive
• Reflection
– Distribuite
• Client-server, Broker
– Enterprise
• Data access
– Interoperability
Sisteme distribuite
• Continutul capitolului:
– Introducere:
• Modele pentru aplicatii distribuite
• Ultrascurta introducere in comunicarea intre procese in retea
– Tipare utilizate in realizarea infrastructurii pentru sisteme
distribuite:
• Forwarder-Receiver: [POSA1], din chap.3.6 (pag 307-322)
• Client-Dispatcher-Server: [POSA1], din chap. 3.6 (pag 323-336)
• Remote Proxy: [POSA1], din chap. 3.4 (pag 263-275)
• Broker:
– [POSA1] chap 2.3
– Exemple de tehnologii de middleware care implementeaza
tiparul Broker: Java RMI, CORBA, .NET Remoting
Distributed Object Computing ?
Proces2 (Calculator 2) Proces1 (Calculator 1)

Deoarece Client si InfoServer ruleaza in procese diferite,


nu exista spatiu de memorie comun/ variabile comune !
Trebuie utilizate mecanisme de comunicare intre procese
Ultra-scurta introducere in
comunicarea intre procese in retea

Datele sunt transmise pe Canale de comunicare


Un canal de comunicare este definit prin:
•2 communication endpoints
•protocol
Un communication endpoint (socket):
Adresa: are 2 componente: identificare host + port
Realizarearea modelului
Client-Server
SERVER
Deschide un canal de comunicare

CLIENT
Sta in asteptare pana la sosirea
unui cereri de la un client
Deschide un canal de comunicare
si se conecteaza la un canal
deschis de un server Accepta cererea

cerere
Scrie (date) Citeste (date)

raspuns
Citeste(date) Scrie (date)

notificare
Inchide canalul de comunicare
Dezavantaje:
• programatorul de aplicatii trebuie sa se ocupe de multe
aspecte de nivel scazut (trimiterea/receptionarea datelor in
format binar)
• logica aplicatiei nu este separata de partea de comunicatie
Suport pentru aplicatii distribuite
• Calitati dorite ale sistemelor distribuite:
– Separation of concerns: logica aplicatiei sa fie separata de aspectele
legate de realizarea comunicatiei la distanta => “cineva” trebuie sa
rezolve stabilirea canalului de comunicatie si eventualele transformari
ale formatului datelor
– Location independence: interactiunile client-server sa se desfasoare la
fel, independent de locatia serverului => “cineva” trebuie sa rezolve
localizarea serverului
– Location transparence: interactiunea unui client cu un server la distanta
sa aiba loc in mod similar cu un server local => “cineva” trebuie sa
rezolve aducerea unei referinte la un obiect aflat la distanta

• Middleware:
– Infrastructura care suporta realizarea aplicatiilor distribuite
– De obicei realizata de software “off-the-shelf”
– Exemple: Java RMI, .NET Remoting, CORBA
Tipare arhitecturale pentru sisteme
distribuite
• Tipare arhitecturale pentru sisteme distribuite:
– Broker
– Utilizeaza si integreaza tiparele:
• Forwarder-Receiver: separation of concerns: ascunde detaliile
mecanismelor specifice de comunicare intre procese (formatarea
datelor, transmiterea/receptionarea mesajelor conform protocolului
utilizat)
• Client-Dispatcher-Server: location independency: decupleaza
stabilirea conexiunii (cunoasterea adresei) de comunicarea
ulterioara
• Remote Proxy: location transparency: interactiunea cu un server la
distanta are loc prin intermediul reprezentantului sau local
Forwarder-Receiver
Tiparul Forwarder-Receiver realizeaza transparenta comunicatiilor
inter-procese pentru sisteme care interactioneaza dupa un model
peer-to-peer. Tiparul introduce elementele Forwarder si Receiver
pentru a decupla functionalitatea fiecarui peer de mecanismul de
comunicare utilizat.

How are you ?


Peer1 Peer2
I am alive !
Exemplu Forwarder-Receiver
Problema:
• Un Peer nu trebuie sa cunoasca mecanismul de comunicare intre
procese utilizat la baza
• Solutia trebuie sa permita schimbarea mecanismului de comunicare,
fara a afecta functionalitatea Peers
• Fiecare Peer cunoaste doar numele altui Peer cu care comunica
• Exista un protocol (formate de mesaje) agreat de ambele parti
class Peer1 { class Peer2 {
Receiver r; Receiver r;
Forwarder f; Forwarder f;
public void run() { public void run() {
f = new Forwarder("Peer1"); Message result = null;
Message msg = new Message r = new Receiver("Peer2");
("Peer1", "How are you"); result = r.receiveMsg();
f.sendMsg("Peer2", msg); System.out.println("Peer2 receptionat
mesaj "+result.data+" de la "+result.sender);
Message result = null;
r = new Receiver("Peer1"); f = new Forwarder("Peer2");
result = r.receiveMsg(); Message msg = new Message
System.out.println("Peer1 receptionat ("Peer2", "I am alive");
mesaj " + result.data + " de la " + f.sendMsg(result.sender, msg);
result.sender); }
} }
}
Structura Forwarder Receiver

[POSA]-Fig/P.310
Structura Forwarder-Receiver

[POSA]-Fig/P.311
Scenariu Forwarder-Receiver

[POSA]-Fig/P.312
Exemplu implementare

deliver ( marshal ( How are you ) unmarshal ) receive


F R
Peer1 Peer2
receive ( unmarshal ( I am alive ) marshal ) deliver
R F

Registry Registry

Config.db Config.db
“Peer1”: adresa … “Peer1”: adresa …
“Peer2”: adresa … “Peer2”: adresa …
Pasi implementare tipar
Forwarder-Receiver
• Specificarea maparii nume – adrese
• Specificarea protocolului de comunicatie intre peers si
intre Peers si Forwarders/Receivers: sendMsg,
receiveMsg
• Alegerea mecanismului de comunicatie
• Implementare Forwarder: deliver, marshal
• Implementare Receiver: receive, unmarshal
• Implementare Peers
• Implementare configuratie de start
Pas1: Specificarea maparii nume-adrese
class Entry { public class Registry
private String destinationId; {
private int portNr; private Hashtable hTable = new Hashtable();
public Entry(String theDest, int thePort) { private static Registry _instance=null;
destinationId = theDest;
portNr = thePort; private Registry(){}
}
public String dest() { public static Registry instance() {
return destinationId; if (_instance==null)
} _instance=new Registry();
public int port() { return _instance;
return portNr; }
}
} public void put(String theKey, Entry theEntry)
{
hTable.put(theKey, theEntry);
theDest, thePort: }
adresa IP+nr port public Entry get(String aKey) {
return (Entry)hTable.get(aKey);
}
} sub care este
theKey: numele
cunoscut serviciul ( de exemplu
Peer1, Peer2)
Pas2: Specificarea protocolului de
comunicatie pentru Peers
class Forwarder
{

class Message public void sendMsg(String theDest,
{ Message theMsg)
public String sender; {
public String data; deliver(theDest, marshal(theMsg));
public Message(String theSender, String }
rawData) }
{
sender = theSender;
data = rawData;
} class Receiver
} {

public Message receiveMsg()
{
return unmarshal(receive());
}
}
Pas3: Alegerea protocolului de comunicatie
class Receiver {
class Forwarder { private ServerSocket srvS;
private Socket s; private Socket s;
private OutputStream oStr; private InputStream iStr;

… …
private void deliver(String theDest, byte[] data) private byte[] receive() {
{ int val;
try { byte buffer[] = null;
Entry entry = Registry.instance().get(theDest); try {
if (entry == null) { Entry entry = Registry.instance().get(myName);
System.out.println(“Dest unknown"); srvS = new ServerSocket(entry.port(), 1000);
return; s = srvS.accept();
} iStr = s.getInputStream();
s = new Socket(entry.dest(), entry.port()); val=iStr.read();
oStr = s.getOutputStream(); buffer=new byte[val];
oStr.write(data); iStr.read(buffer);
oStr.flush(); iStr.close();
oStr.close(); s.close();
} catch (IOException e) { srvS.close();
System.out.println("IOE forwarder"); } } catch (IOException e) {
} System.out.println("IOE receiver"); }
} return buffer;
… }
} …
}
Pas4: Implementare Forwarder/Receiver
class Forwarder {

private byte[] marshal(Message theMsg) {
String m = " " + theMsg.sender + ":" + theMsg.data;
byte b[] = new byte[m.length()];
b = m.getBytes();
b[0] = (byte)m.length();
return b;
}

}

class Receiver {

private Message unmarshal(byte[] anArray) {
String msg = new String(anArray);
String sender = msg.substring(1, msg.indexOf(":"));
String m = msg.substring(msg.indexOf(":")+1, msg.length()-1);
return new Message(sender, m); }

}
Pas 5: Realizare configuratie de start
class Configuration { Adresele date ca exemplu
public Configuration(){ reprezinta cazul particular in care
Entry entry=new Entry("127.0.0.1", 1111); componentele comunicante sunt
Registry.instance().put("Peer2", entry); pe acelasi calculator – localhost –
entry=new Entry("127.0.0.1", 2222); identificat prin adresa IP de
Registry.instance().put("Peer1", entry); loopback 127.0.0.1
}
}

public class P1 {
public static void main(String args[]) {
new Configuration();
Peer1 p1=new Peer1();
p1.run();
}
}
In acest exemplu, informatiile de
configurare (adresele participantilor)
public class P2 { sunt duplicate, fiind pastrate atat la P1
public static void main(String args[]) { cat si la P2 !
new Configuration();
Peer2 p2=new Peer2();
p2.run();
}
}
Proprietati ale tiparului
Forwarder-Receiver
• Avantaje:
– Comunicare eficienta inter-procese
– Incapsulare a facilitatilor de comunicare inter-procese
• Atentionari:
– Nu suporta reconfigurarea flexibila a componentelor =>
combinatie cu dispatcher ca NamingService
Observatii privind tiparul
Forwarder-Receiver la Client-Server
• Interactiunea tipica Client-Server:
– Un server are o adresa bine-cunoscuta (publica)
– Un client trimite un mesaj pe adresa serverului, cerand un anumit
serviciu, si apoi asteapta mesajul de raspuns de la server
• Tiparul Forwarder-Receiver:
– Abstractizeaza un canal de comunicatie unidirectional intre Forwarder
si Receiver
• Client-Server realizat cu Forwarder-Receiver:
– Utilizeaza 2 canale de comunicatie distincte

cerere Adr
F R
Client Server
raspuns
R F
Adr
Tipare pentru comunicarea prin
mesaje pe canale de comunicatie
• In functie de protocol, un canal de comunicatie poate fi
bidirectional sau unidirectional
– Canal unidirectional: Send-Receive (Forward-Receive)
– Canal bidirectional: Request-Reply

• Daca protocolul utilizat permite canale de comunicatie


bidirectionale, pentru implementarea unui sistem client-
server (in care clientul este de tip blocking/sincron) este
de preferat comunicarea de tip request-reply !
Send-Receive
Client Server
Adr
Sender Receiver

Adr
Receiver Sender

ByteSender {
public ByteSender(String theName) ;
public void deliver(Address theDest, byte[] data);
}
ByteReceiver {
public ByteReceiver(String theName, Address theAddr) {
public byte[] receive()
}
Client
Request-Reply Server

Adr
Requestor Replyer

Requestor{
public Requestor(String theName) ;
public byte[] deliver_and_wait_feedback(Address theDest, byte[] data);
}

public interface ByteStreamTransformer{


public byte[] transform(byte[] in);
}
Replyer {
public Replyer(String theName, Address theAddr);
public void receive_transform_and_send_feedback(ByteStreamTransformer t);
}
Implementari
• Pentru exemple de implementari v. pagina web a
cursului: http:/staff.cs.upt.ro/~ioana/arhit/curs.html
– ByteSender-ByteReceiver
– Requestor-Replyer
• Detaliile de implementare pentru acestea NU fac obiectul
acestui curs (v. PRC)
• Exemple de aplicatii client-server construite cu acestea:
– Client-Server cu Send-Receive (SR)
– Client-Server cu Requestor-Replyer (RR)
• Implementarile date pot fi folosite ca puncte de plecare
la realizarea temelor
Implementare Forwarder-Receiver
peste Send-Receive
Client-Dispatcher-Server
Tiparul Client-Dispatcher-Server introduce o componenta
intermediara = Dispatcher intre componentele clienti si
servere. Rolul unui Dispatcher este de a realiza transparenta
locatiei serverelor prin intermediul unui Naming Service
Structura Client-Dispatcher-Server

[POSA]-Fig/P. 325
Structura Client-Dispatcher-Server

[POSA]-Fig/P. 326
Varianta: Client-Dispatcher-Service
• Clientii adreseaza Servicii si nu Servere
• Dispatcher-ul gaseste in repository-ul sau un server care furnizeaza
respectivul serviciu (Pot fi mai multe servere care furnizeaza acel
serviciu)
Interactiunea intre Client-
Dispatcher-Server

CSProtocol
Client Server

CDProtocol DSProtocol

Dispatcher

Toate interactiunile implica


mecanisme de comunicare intre procese !
Exemplu Peer-to-Peer:
Implementare cu Forwarder-Receiver

deliver ( marshal ( How are you ) unmarshal ) receive


F R
Peer1 Peer2
receive ( unmarshal ( I am alive ) marshal ) deliver
R F

Registry Registry

Config.db Config.db
“Peer1”: adresa … “Peer1”: adresa …
“Peer2”: adresa … “Peer2”: adresa …
Exemplu Peer-to-Peer:
Implem cu Forw-Rec + Dispatcher
“How are you ? “
F R
Peer1 Peer2
“I am alive “
R F

Registry

Config.db
“Peer1”: adresa …
“Peer2”: adresa …
Exemplu Peer-to-Peer:
Implem cu Req-Repl + Dispatcher
“How are you ? / I am alive “
Req Repl Peer2
Peer1
(Server)
Req

Repl

Registry

Config.db
“Peer1”: adresa …
“Peer2”: adresa …
Proprietati ale tiparului
Client-Dispatcher-Server
• Avantaje:
– Exchangeability of servers
– Location and migration transparency
– Re-configuration
– Fault-tolerance
• Atentionari:
– Lower efficiency: performanta este determinata de overhead-ul
introdus de dispatcher (1 singur Dispatcher la N Clienti si M
Servere)
• Localizarea serverelor
• Inregistrarea serverelor
• Stabilirea conexiunilor
– Nu incapsuleaza detaliile infrastructurii de comunicatie (vezi
pe diagrama de colaborari cate operatii diferite traverseaza
limitele proceselor !) => e nevoie de combinarea cu Forwarder-
Receiver
Exemplu Client-Server:
Implem cu Req-Repl + Dispatcher
• Exemplu: InfoServer: poate furniza la cerere informatii despre starea
vremii sau despre gradul de congestie pe sosele

Cum e vremea azi ?


Innorat si ploua

InfoServer
Client1
Sunt InfoServer la addr X,
info Meteo si Rutier

Client2 Dispatcher
Exemplu Client-Server:

Codul de implementare a lui Client1:


• Transmite mesaj la NamingService (Dispatcher) – intreaba care
e adresa unui server de info Meteo
• Primeste raspunsul de la Dispatcher – ii da adresa lui InfoServer
• Transmite mesaj la InfoServer (pe adresa aflata la pasul anterior)
– intreaba care e vremea azi
• Primeste raspunsul de la InfoServer cu prognoza pe azi

Ideal, Client1 ar trebui sa fie ceva de genul:


todayWeather=meteoServer.GetWeatherForecast(“today”);
Remote Proxy
Tiparul Proxy permite clientilor unei componente sa comunice cu un
“reprezentant” al acesteia, in loc de a comunica cu originalul.
Remote Proxy: permite clientilor unei componente la distanta sa un
acces transparent la aceasta, ascunzand clientilor aspectele ce tin
de adresarea si comunicarea la distanta
Structura generala Proxy

[POSA]-Fig/P.
Proxy – comportament

[POSA]-Fig/P.
Remote Proxy
Remote Proxy: pre and postprocessing
contain a Forwarder-Receiver

Proxy
locateServer, Helper
marshal, deliver serverloop
receive,
unmarsha

service
marshal,
deliver

receive, unmarshal
Broker
Tiparul Broker structureaza sisteme distribuite constand din
componente decuplate care interactioneaza prin invocarea
de servicii la distanta. Broker-ul realizeaza coordonarea
comunicarii si ascunderea detaliilor comunicarii fata de
componentele implicate.

Client1 Client2 Server1 Server2

Invoke Invoke Object X Object Y


foo on bar on
foo bar
Object X Object Y

Broker
Broker vs Forwarder-Receiver
• Ambele tipare realizeaza coordonarea comunicarii si ascunderea
detaliilor comunicarii fata de componentele implicate
• Forwarder-Receiver: comunicarea are loc prin mesaje al caror
format este stabilit si cunoscut de componentele Peer care
participa
• Broker: componentele interactioneaza prin invocare de servicii la
distanta (invocare de operatii exportate de o interfata), in mod
transparent fata de locatia componentelor.
– Realizarea tiparului Broker presupune integrarea unui tipar Remote
Proxy cu tiparul Forwarder-Receiver
Variante de Broker
• Indirect Broker:
– Broker-ul realizeaza o comunicatie indirecta intre client si server:
orice comunicatie intre client si server este transmisa prin
intermediul Broker-ului

• Direct Broker:
– Clientul poate comunica direct cu Server-ul, dupa ce conexiunea
a fost realizata prin intermediul Broker
Indirect Broker

2. pack_data 8. pack_data
3. forward_request 9. forward_response
F F
ClientProxy R ServerProxy
R R
10.return
11. unpack_data F
5. call service 6.unpack_data
1. call server 7. run service
Broker
Client Server
4.find server

NamingService
Broker

[POSA]-Fig/P.107
[POSA]-Fig/P. 103-105
Serverul se inregistreaza la Broker

[POSA]-Fig/P.108
Brokerul rezolva o cerere Client-Server

[POSA]-Fig/P.109
Variante de Broker
• Indirect Broker:
– realizeaza o comunicatie indirecta intre client si server: orice
comunicatie intre client si server este transmisa prin intermediul Broker-
ului
– Corespunde cu varianta prezentata in scenariul general din diagrama
de colaborari anterioara
– Ineficient din punct de vedere al comunicatiei, dar prezinta avantajul ca
se poate controla accesul la servere
• Direct Broker:
– Clientul poate comunica direct cu Server-ul, dupa ce conexiunea a fost
realizata prin intermediul Broker => creste eficienta comunicatiei
– Operatiile descrise in diagrama anterioara raman valabile ca principiu si
secventa dar sunt rearondate intre Proxy-uri si Broker: Proxy-urile vor
prelua operatiile forward_request si forward_response de la Broker. De
asemenea, Proxy-ul va interoga nameService-ul (locate_server)
Direct Broker

2. pack_data 5.unpack_data
4. forward_request
F R
ClientProxy ServerProxy
R F
8. forward_response
9. unpack_data
7. pack_data
1. call server 6. run service

R
Client Server
F

NamingService
Observatii: mecanisme de
comunicatie folosite
• Prezentarea patternurilor Broker a utilizat modelul
Forwarder-Receiver (bazat pe mecanismul de
comunicatie Send-Receive – presupune canale de
comunicatie unidirectionale)
• Daca:
– protocoalele utilizate permit canale de comunicatie bidirectionale
– Semantica apelurilor de la clienti la servere este cu apeluri
sincrone (cu blocarea clientului in asteptarea raspunsului)
=> e de preferat sa se foloseasca in implementare
mecanismul Request-Reply !
Exemplu Client-Server:
cu Direct Broker

• Codul de implementare a lui Client1:


– todayWeather=meteoServer.GetWeatherForecast(“today”);
– meteoServer este un obiect MeteoClientProxy
• In codul de implementare a lui MeteoClientProxy:
– La crearea proxy-ului:
• Transmite mesaj la NamingService (Dispatcher) – intreaba care e
adresa unui server de info Meteo
• Primeste raspunsul de la Dispatcher – ii da adresa lui InfoServer (de
fapt a MeteoServerProxy)
– In metoda GetWeatherForecast:
• Transmite mesaj la InfoServer (pe adresa aflata la creare) – intreaba
care e vremea azi: in mesaj trebuie inclus: numele operatiei, valorile
parametrilor
• Primeste mesajul de raspuns de la InfoServer
• Extrage (unmarshal) prognoza pe azi
• Returneaza raspunsul
Exemplu Client-Server:
cu Direct Broker (cont)

• In codul de implementare a lui MeteoServerProxy:


• Creaza Receiver (Replyer) si asteapta mesaje
• La sosirea unui mesaj, extrage (unmarshal) informatii care ii
spun despre ce operatie e vorba si care sunt valorile
parametrilor
• Invoca operatia corespunzatoare a InfoServer
• Preia rezultatul, il formateaza (marshal) si trimite mesajul de
raspuns inapoi
Generarea codului Proxy-urilor
• Se observa ca “ugly stuff” s-a mutat din codul client in codul Proxy-
urilor
• ClientProxy depinde de interfata serviciului (implementeaza aceeasi
interfata ca si serverul) => pentru fiecare tip de server vom avea alte
clase Proxy
• Avantaj: codul Proxy-urilor poate fi totusi generat automat !
– Programatorul de aplicatii va scrie (manual) cod doar pentru client si
server

(Descriere) Cod
Interfata Generator Proxy-uri
Server
Broker in practica: Middleware
• Middleware:
– Infrastructura care suporta realizarea aplicatiilor distribuite
– De obicei realizata de software “off-the-shelf”
– Exemple: Java RMI, .NET Remoting, CORBA
• Ce contine pachetul “off-the-shelf”:
1. Libraries+API pentru dezvoltarea aplicatiilor distribuite
2. Executabile server (de ex NamingService)
3. Tool-uri pentru dezvoltatorii de aplicatii (de ex Generator de
proxy-uri)
Broker in practica: Middleware
Tool Generare Proxy-uri

Biblioteca(API)+ Executabile

Application Developer
Broker in practica: Middleware
Tool Generare Proxy-uri

Biblioteca(API)+ Executabile

Application Developer
Implementari de referinta ale
arhitecturii Broker
Middleware care implementeaza tiparul Broker:
– RMI: Java Remote Method Invocation
– CORBA: Common Object Request Broker
Architecture. Arhitectura de referinta elaborata de
OMG (Object Management Group)
• Diverse implementari, comerciale sau open
– .NET Remoting
– Windows Communication Foundation (WCF) – in
parte si functionalitate de tip broker
– WSDL web services : proxy generators (WSDL-to-
language)
Arhitectura comuna
Invokes methods of
Remote Object via a
Server
local Proxy object
implements
Client Remote Remote
Interface Object

uses implements

ServerSide Proxy
ClientSide Proxy

Broker
Exemplu
• Aplicatie distribuita simpla: realizarea unui sistem
StockMarket, care poate fi interogat de la distanta
asupra valorii curente a actiunilor unor companii
specificate
• Middleware (Broker) utilizat - 3 variante:
– RMI
– .NET Remoting
– CORBA
• Se compara:
– Suportul oferit de cele 3 implementari de Broker pentru
dezvoltarea unei aplicatii distribuite simple
– Pasii necesari pentru realizarea aplicatiei
• Exemplul ajuta la intelegerea functionarii unui Broker in
general
Pasi de dezvoltare ai aplicatiei
1. Definire interfata obiect la distanta

INTERFACE
StockMarket 2. Implementare obiect
float get_price(Company) 4. Implementare Server
5. Implementare Client
StockMarketServer

StockMarketClient
StockMarketImpl

3. Generare Proxy 6. Rulare aplicatie


3. Generare Proxy

StockMarket Broker StockMarket


ClientSide PROXY ServerSide PROXY
RMI: Arhitectura
Server
implements
Client Remote Remote
Interface Object

uses implements

Stub Remote Reference Skeleton


(ClientSide Proxy) (ServerSide Proxy)
Layer

Transport
Layer
RMI - Pas1. Definire interfata
• Se defineste interfata
StockMarket package SimpleStocks;
• Aceasta exporta operatia import java.rmi.*;
get_price:
– Parametru: numele companiei public interface StockMarket
cotate la bursa extends java.rmi.Remote {
– Rezultat: valoarea actiunilor float get_price (String Company)
throws
RemoteException;
}
Specific RMI:
•Interfata trebuie sa
extinda java.rmi.Remote
•Metodele trebuie sa poata Fisier StockMarket.java
genera exceptii
RemoteException
RMI - Pas 2. Implementare Obiect

• Se implementeaza clasa import java.rmi.*;


StockMarketImpl import java.rmi.server.UnicastRemoteObject;
• Aceasta realizeaza operatia
public class StockMarketImpl
get_price extends UnicastRemoteObject
implements StockMarket {

public StockMarketImpl() throws


RemoteException {}
Specific RMI:
•Implementarea trebuie
sa extinda public float get_price(String company) {
UnicastRemoteObject float price=12345;
return price;
}
}

Fisier StockMarketImpl.java
RMI - Pas 3.V1: Generare Traditionala Proxy-uri

RMI Stub/Skeleton

Se genereaza automat din implementarea obiectului server cu


ajutorul tool-ului rmic

>rmic –v1.1 –keep StockMarketImpl

Argumente:
-v1.1 pentru ca incepand cu versiunea Java 1.2 implicit nu se mai
genereaza skeleton-ul, de aceea e optiunea –v1.1
-keep ca sa pastreze si codul sursa al claselor generate (doar ca sa il
putem vedea de curiozitate)

Rezulta clase pentru stub si skeleton, utilizand conventia de nume:


StockMarketImpl_Stub.class
StockMarketImpl_Skel.class
RMI - Pas 4. Implementare Server

• Se implementeaza un program
StockMarketServer, care import java.rmi.*;
creaza un obiect de tip
import SimpleStocks.*;
StockMarket, ce poate fi
accesat de la distanta public class StockMarketServer {
public static void main(String[] args) {
• Obiectul creat este inregistrat try {
StockMarketImpl stockMarketImpl = new
sub numele “NASDAQ” StockMarketImpl();

Naming.rebind("NASDAQ",
stockMarketImpl );

Specific RMI: } catch (Exception e) {}


}
• Naming: Obiectul }
Server este inregistrat
cu numele “Nasdaq”
Fisier StockMarketServer.java
RMI - Pas 5. Implementare Client

• Se implementeaza un program
StockMarketClient, care import java.rmi.*;
acceseaza un obiect de tip import SimpleStocks.*;
StockMarket aflat la distanta, si
public class StockMarketClient {
invoca operatia get_price
pentru un nume de companie public static void main(String[] args) {
• Prin intermediul Broker se try {
StockMarket market= (StockMarket)
localizeaza obiectul cu numele Naming.lookup("rmi://localhost/NASDAQ");
“NASDAQ”
float price=market.get_price("ABC SRL");

Specific RMI: System.out.println("Price is "+price);


• Naming.lookup: se obtine o
} catch (Exception e) {
referinta (un proxy de fapt) la
System.out.println("Exception !");}
obiectul server care a fost }
inregistrat ca “Nasdaq” }
•Nu trebuie sa gestionez
deloc adrese !
Fisier StockMarketClient.java
RMI – To Do Checklist:
• Cod sursa scris de programatorul aplicatiei Stockmarket:
StockMarket.java, StockMarketImpl.java,
StockMarketServer.java, StockMarketClient.java
• Compilare cod sursa : javac *.java
• Generare proxy-uri: rmic –v1.1 StockMarketImpl
– Se obtin StockMarketImpl_Stub.class si
StockMarketImpl_Skel.class

• Deployment Server:
• StockMarket.class, StockMarketImpl.class,
StockMarketImpl_Skel.class, StockMarketServer.class

• Deployment Client:
• StockMarket.class, StockMarketImpl_Stub.class,
StockMarketClient.class
RMI - Pas 6. Rulare aplicatie
RMI Registry =
non-persistent
Naming Service
> start rmiregistry

> start java StockMarketServer

> java StockMarketClient

Codul aplicatiei exemplu poate fi download-ad de pe pagina cursului,


de la sectiunea de exemple de cod pentru cursul c7: RMI_StockMarket
RMI - Pas 3.V2: Generare Proxy - Doar Client

Varianta 2: In pasul 3 se genereaza doar RMI Stub

Se genereaza automat din implementarea obiectului server

>rmic StockMarketImpl

Rezulta clase pentru stub, utilizand conventia de nume:


StockMarketImpl_Stub.class

Unde a disparut skeleton-ul ? (server-side proxy ?)


- in acest caz, server-side proxy-ul generat specific aplicatiei este
inlocuit cu unul general, care lucreaza exploatand faptul ca Java
permite invocarea de metode prin Reflection
RMI – To Do Checklist – V2:
• Cod sursa scris de programatorul aplicatiei Stockmarket:
StockMarket.java, StockMarketImpl.java,
StockMarketServer.java, StockMarketClient.java
• Compilare cod sursa : javac *.java
• Generare proxy-uri: rmic StockMarketImpl
– Se obtine StockMarketImpl_Stub.class

• Deployment Server:
• StockMarket.class, StockMarketImpl.class,
StockMarketServer.class

• Deployment Client:
• StockMarket.class, StockMarketImpl_Stub.class,
StockMarketClient.class

– Rulare aplicatie
RMI - Pas 3.V3: fara generare Proxy

Pasul 3 – Varianta 3: incepand cu versiunea Java 1.5, nu mai este


necesara pre-generarea stub-ului cu rmic !

property java.rmi.server.ignoreStubClasses:
– daca e falsa, se asteapta sa gaseasca un stub pregenerat (by
default e falsa)
– daca e true, nu mai e nevoie de existenta stub-urilor pre-
generate cu rmic

Unde a disparul si stub-ul ? (client-side proxy ?) de fapt el exista, dar


poate fi generat dinamic la runtime, in mod total transparent pentru
dezvoltatorul aplicatiei, prin mecanismul de dynamic proxy
RMI – To Do Checklist – V3:
• Cod sursa scris de programatorul aplicatiei Stockmarket:
StockMarket.java, StockMarketImpl.java,
StockMarketServer.java, StockMarketClient.java
• Compilare cod sursa : javac *.java
• Generare proxy-uri: Nu se mai face nimic ! (dar va trebui setat un
property la rulare!)
• Deployment Server:
• StockMarket.class, StockMarketImpl.class,
StockMarketServer.class

• Deployment Client:
• StockMarket.class, StockMarketClient.class

– Rulare aplicatie
RMI - Pas 6 – Varianta 3: Rulare aplicatie

> start rmiregistry

> start java StockMarketServer

> java -Djava.rmi.server.ignoreStubClasses=true


StockMarketClient
CORBA: Arhitectura
Server
Remote
Client Remote
Interface
Object
IDL

IDL Skeleton
Dynamic IDL Stub (ServerSide
Interface Invocation (ClientSide ORB Object Implem
Proxy) Adapter Repository
Repository Interface Proxy) Interface

ORB (Object Request Broker)


CORBA - Pas1. Definire interfata

• Se defineste interfata
StockMarket
• Aceasta exporta operatia
get_price: module SimpleStocks {
– Parametru: numele companiei
cotate la bursa interface StockMarket {
– Rezultat: valoarea actiunilor float get_price(in string Company);
};
};

Specific CORBA:
•Interfata se defineste intr-
un limbaj neutru, CORBA
IDL Fisier StockMarket.idl
CORBA - Pas 2. Generare Proxy-uri

CORBA IDL Stub/Skeleton

Se genereaza automat din definitia interfetei IDL

> idl2java StockMarket.idl

Rezulta clasele/fisierele:
Client Stub: _st_StockMarket.java
Server Stub: _StockMarketImplBase.java
CORBA - Pas 3. Implementare Obiect

• Se implementeaza clasa
StockMarketImpl import org.omg.CORBA.*;
import SimpleStocks.*;
• Aceasta realizeaza operatia
get_price public class StockMarketImpl extends
_StockMarketImplBase {
public float get_price(in string
company) {
float price=12345;
return price;
Specific CORBA: }
•Un obiect accesibil la public StockMarketImpl (String name) {
distanta trebuie sa extinda super(name);
server-side-proxy-ul }
generat automat din }
descrierea interfetei

Fisier StockMarketImpl.java
CORBA - Pas 4. Implementare Server

• Se implementeaza un program
StockMarketServer, care import org.omg.CORBA.*;
Import SimpleStocks.*;
creaza un obiect de tip
StockMarketImpl, ce poate fi public class StockMarketServer {
accesat de la distanta public static void main(String[] args) {
try {
• Obiectul creat este inregistrat ORB orb=ORB.init();
sub numele “NASDAQ” BOA boa=orb.BOA_init();
StockMarketImpl stockMarketImpl=
new StockMarketImpl(“NASDAQ”);
Specific CORBA: boa.obj_is_ready(stockMarketImpl);
•ORB boa. Impl_is_ready();
•BOA } catch (Exception e) {}
}
}

Fisier StockMarketServer.java
CORBA - Pas 5. Implementare Client

• Se implementeaza un program import org.omg.CORBA.*;


StockMarketClient, care import SimpleStocks.*;
acceseaza un obiect de tip
StockMarket aflat la distanta, si public class StockMarketClient {
invoca operatia get_price public static void main(String[] args) {
pentru un nume de companie try {
ORB orb=ORB.init();
• Prin intermediul Broker se StockMarket market=
localizeaza obiectul cu numele StockMarketHelper.bind(orb,
“NASDAQ”);
“NASDAQ”
market.get_price(“ABC SRL”);
} catch (Exception e) {}
Specific CORBA: }
•ORB }
•StockMarketHelper =
proxy generat
Fisier StockMarketClient.java
CORBA - Pas 6. Rulare aplicatie
Location service
(numele OSAgent e
specific unei anumite
implementari
CORBA)

> start osagent

> start java StockMarketServer

> start java StockMarketClient


.NET Remoting Architecture
Server

Client Remote Remote


Interface Object

TransparentProxy
RealProxy

Channel Remoting system


Remoting system
.NET – Pas 1. Definire Interfata Remote

• Se defineste interfata
StockMarket
public interface StockMarket {
• Aceasta exporta operatia float get_price(string company);
get_price: }
– Parametru: numele companiei
cotate la bursa
– Rezultat: valoarea actiunilor
Fisier StockMarket.cs

Specific .NET:
•Interfata nu contine nimic
special
•Nu este neaparat nevoie
sa fie definita o interfata
.NET – Pas 2. Definire Obiect Remote

• Se implementeaza clasa using System;


StockMarketImpl public class StockMarketImpl :
MarshalByRefObject, StockMarket{
• Aceasta realizeaza operatia public float get_price(string company){
get_price return 12345;
}
}

Specific .NET: Fisier StockMarketImpl.cs


•Obiectul accesibil la
distanta trebuie sa extinda
MarshalByRefObject
.NET – Pas 3. Implementare Server

• Se implementeaza un program using System;


using System.Runtime.Remoting;
StockMarketServer, care using System.Runtime.Remoting.Channels;
creaza un obiect de tip using System.Runtime.Remoting.Channels.Tcp;
StockMarket, ce poate fi public class StockMarketServer{
accesat de la distanta public static void Main(){
StockMarketImpl myStockMarket =
• Obiectul creat este inregistrat new StockMarketImpl();
sub numele “NASDAQ” TcpChannel m_TcpChan =
new TcpChannel(9999);
ChannelServices.
RegisterChannel(m_TcpChan);
Specific .NET: RemotingServices.Marshal(
•ChannelServices myStockMarket, "NASDAQ");
•RemotingServices System.Console.WriteLine(
"Listening for requests. Press ENTER to quit");
System.Console.ReadLine();
}
}

Fisier StockMarketServer.cs
.NET – Pas 4. Implementare Client

• Se implementeaza un program using System;


StockMarketClient, care using System.Runtime.Remoting;
acceseaza un obiect de tip using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
StockMarket aflat la distanta, si
invoca operatia get_price pentru
public class Client{
un nume de companie public static void Main(){
• Prin intermediul Broker se TcpChannel tcpChan = new TcpChannel();
localizeaza obiectul cu numele ChannelServices.RegisterChannel(tcpChan);
“NASDAQ”
StockMarket stockMarket = (StockMarket)
Specific .NET: Activator.GetObject(typeof(StockMarket),
•ChannelServices "tcp://localhost:9999/NASDAQ");
•Activator.GetObject
Console.WriteLine(stockMarket.get_price(
"abc SRL"));
}
}

Fisier StockMarketClient.cs
.NET - Pas 5. Rulare aplicatie

> Presupunand ca Windows si .NET Framework este instalat:


> start StockMarketServer
> start StockMarketClient
.NET - Pas 6. Creare Proxy ?

• Crearea de Proxy este total transparenta pentru developer-ul de


aplicatii
• Proxy se creaza automat de catre .NET Framework in timpul
executiei cand un client activeaza un obiect la distanta.
Broker in practica: Middleware
Tool Generare Proxy-uri

Biblioteca(API)+ Executabile

Application Developer
Exercitiu
• Implementarea unui broker foarte simplu, de “jucarie” -
Toy-ObjectRequestBroker
– Se furnizeaza implementari pentru suportul de comunicare in
retea la nivel de transport de octeti (ByteSender/Receiver sau
Requester/Replyer)
• Descarcati ByteCommunication.zip de pe pagina cursului si
incercati exemplele !
– Exemplul 1: ServerWithSR, ClientWithSR
– Exemplul 2: ServerWithRR, ClientWithRR
– Implementarea nu va folosi alte tehnologii de Middleware
– Detalii cerinte => Tema 3 laborator
http://staff.cs.upt.ro/~ioana/arhit/2016/t3.html
Cerinte ToyORB
• Scopul ToyORB este sa ofere support dezvoltatorilor de
aplicatii distribuite (precum o face, de exemplu, unul
dintre “competitorii” sai, Java RMI)
• ToyORB consta din:
– O biblioteca oferita dezvoltatorului de aplicatii, care va fi utilizata
pentru implementarea programelor client si server a aplicatiei
(omologul lui java.Remote)
– Un executabil tip server, Naming Service, care este necesar
pentru deploymentul si rularea aplicatiilor dezvoltate peste
ToyORB (omologul lui rmiregistry) . Pentru implementarea lui se
poate folosi suportul dat in ByteCommunication
– Optional, contine tool-uri sau implementeaza alte metode prin
care degreveaza dezvoltatorul de aplicatii de sarcina scrierii
manuale a proxy-urilor
Dezvoltarea unei aplicatii
folosind ToyORB
1. Definire interfata obiect la distanta

INTERFACE
StockMarket 2. Implementare obiect
float get_price(Company) 4. Implementare Server
5. Implementare Client
StockMarketServer

StockMarketClient
StockMarketImpl

3. Generare Proxy 3. Generare Proxy/


6. Rulare aplicatie
Scriere manuala in varianta simpl Scriere manuala in varianta simp

StockMarket Broker StockMarket


ClientSide PROXY ServerSide PROXY
Cerinte ToyORB (2)
• Peste ToyORB, se vor dezvolta diverse aplicatii, una
dintre ele poate fi de ex aplicatia StockMarket.
• Codul sursa al unei aplicatii StockMarket, dezvoltata
peste ToyORB, contine:
– Interfata obiectului la distanta StockMarket.java
– Implementarea obiectului la distanta StocMarketImpl.java
– Implementarea programului client, StockMarketClient,java
– Implementarea programului server, StockMarketServer.java
– Implementarea StockMarketClientSideProxy.java (* in varianta standard
a cerintelor, si aceasta clasa se scrie manual; in variantele extinse se
implementeaza masuri astfel incat sa nu se scrie manual)
– Implementarea StockMarketServerSideProxy.java (* in varianta
standard a cerintelor, si aceasta clasa se scrie manual; in variantele
extinse se implementeaza masuri astfel incat sa nu se scrie manual)
ToyORB - Pas1. Definire interfata
• Se defineste interfata
StockMarket, ca o interfata public interface StockMarket {
normala float get_price (String Company)
• Aceasta exporta operatia }
get_price:
– Parametru: numele companiei
cotate la bursa
– Rezultat: valoarea actiunilor

Fisier StockMarket.java
ToyORB - Pas 2. Implementare Obiect

• Se implementeaza clasa
StockMarketImpl, ca o clasa public class StockMarketImpl implements
normala StockMarket {

• Aceasta realizeaza operatia public StockMarketImpl() {}


get_price
public float get_price(String company) {
float price=12345;
return price;
}
}

Fisier StockMarketImpl.java
ToyORB - Pas 4. Implementare Server

• Se implementeaza un program
StockMarketServer, care import toyORB.*;
creaza un obiect de tip
public class StockMarketServer {
StockMarket, ce poate fi public static void main(String[] args) {
accesat de la distanta
StockMarketImpl stockMarketImpl = new
•Specific ToyORB:
Obiectul creat este inregistrat StockMarketImpl();
• ToyORB.register:
sub numele “NASDAQ” ToyORB.register("NASDAQ",
•Obiectul StockMarket este stockMarketImpl );
inregistrat la Naming Service cu }}
numele “Nasdaq”, }
•Se primeste de undeva nr portului }}
}}
la care va asculta serverul
•Se creaza instant lui serverside
proxy si se invoca metoda de start
a acestuia

Fisier StockMarketServer.java
ToyORB - Pas 5. Implementare Client

• Se implementeaza un program
StockMarketClient, care import toyORB.*;
acceseaza un obiect de tip
StockMarket aflat la distanta, si public class StockMarketClient {
invoca operatia get_price public static void main(String[] args) {
pentru un nume de companie
• Prin intermediul Broker se StockMarket market= (StockMarket)
Specific ToyORB: ToyORB.getObjectRef("NASDAQ");
localizeaza obiectul cu numele
• ToyORB.getObjectReference
“NASDAQ”
•Se interogheaza Naming
float price=market.get_price("ABC SRL");

service pentru adresa serverului System.out.println("Price is "+price);


•se returneaza o referinta (o
instanta a lui client side proxy de }
fapt) la obiectul server care a
fost inregistrat ca “Nasdaq”

Fisier StockMarketClient.java
ToyORB - Pas 3. Versiunea 0:
Scriere manuala proxy-uri

Cerinta standard: se vor implementa manual clasele:

StockMarketClientSideProxy.java
StockMarketSErverSideProxy.java

Se poate folosi suportul ByteCommunication (Requester-Replyer) in


implementarea acestor clase
ToyORB – To Do Checklist pentru
dezvoltarea aplicatiei StockMarket:
• Cod sursa scris de programatorul aplicatiei Stockmarket:
– StockMarket.java, StockMarketImpl.java, StockMarketServer.java,
StockMarketClient.java

– (**) StockMarketClientSideProxy.java,
StockMarketServerSideProxy.java

• Deployment Server:
• StockMarket.class, StockMarketImpl.class,
StockMarketServerSideProxy.class,
StockMarketServer.class

• Deployment Client:
• StockMarket.class, StockMarketClientSideProxy.class,
StockMarketClient.class
ToyORB - Pas 6. Rulare aplicatie

> start ToyORBNamingService

> start java StockMarketServer

> java StockMarketClient


ToyORB: Varianta Forwarder-Receiver
2 canale de comunicatie diferite, unul pentru transmis parametri,
unul pentru transmiterea rezultatului

deliver ( marshal ( “ABC SRL” ) unmarshal ) receive


StockMarket F R StockMarket
ClientProxy receive ( unmarshal ( 1234.5 ) marshal ) deliver ServerProxy
R F

ToyORB
Dezavantaj:
tiparul F-R presupune NamingService
participanti cu statut egal
=> ar trebui ca si clientii sa
se inregistreze (sau ORB
sa le asigneze un nr de
port in mod transparent) Config.db
“StockMarketClient”: IP, Port
“NASDAQ”: IP, Port
ToyORB: Varianta Requester-Replyer

StockMarket Marshaller Marshaller StockMarket


ClientProxy ServerProxy
deliver_and_wait_feedback
Requester Replyer
receive_transform_and_send_feedback

ToyORB
NamingService
deliver_and_wait_feedback:
deliver cererea urmata de receive_transform_and_
receptia rezultatului pe acelasi send_feedback: receive
canal de comunicatie (socket) cererea urmata de
Config.db transmiterea rezultatului
pe acelasi canal de
comunicatie
“NASDAQ”: IP, Port
ToyORB: Implementare Proxy-uri
call_service
send_request StockMarketServerSideProxy:
StockMarketClientSideProxy:
• Are un Replyer r
• Are un Requestor r • Il cunoaste pe StockMarketImpl s
• Are un Marshaller m • Are un Transformer t : primeste un sir de octeti si
• Pentru a rezolva operatia get_price: returneaza sirul de octeti transformat
• Pentru a realiza operatia get_price de ori de cate
pack_data – Cu ajutorul lui m – marshal, ori este solicitat:
transforma parametri de intrare(numele
companiei) intr-un sir de octeti While (true)
r.receive_transform_and_send_feedback(t(s));
forward_ – Cu ajutorul lui r -
deliver_and_wait_feedback, – Receptioneaza sirul de octeti reprezentand
request parametrii, t(s) il transforma in sir de octeti de
transmite catre ServerSideProxy sirul forward_ tip rezultat, care vor fi transmisi inapoi la
de octeti parametru si receptioneaza un response client
sir de octeti reprezentand rezultatul
– Cu ajutorul lui m - unmarshal, ServerTransformer:
unpack_data
transforma sirul de octeti obtinut in
valoarea rezultatului (pretul)
• Are un Marshaller m
• Pentru a rezolva transformarea:
– cu ajutorul lui m – unmarshal, reconstruieste
unpack_data parametri de intrare (numele companiei)
– Apeleaza operatia de la StockMarketImpl s si
Cu text rosu italics sunt obtine rezultatul
run_service
identificate operatiile – Cu ajutorul lui m - marshal, transforma
prin numele cu care apar in pack_data
rezultatul (pretul) in sir de octeti
Pattern-ul Broker
ToyORB: suport pt servere mai complexe

• Este de dorit ca sa se poata accesa la distanta si obiecte care


implementeaza interfete mai complexe (cu mai multe operatii).
• De exemplu:
public interface ComplexStockMarket {
float get_price (String Company);
String whois_highest_today();
String whois_lowest_today();
}

In acest caz, un client va putea accesa serviciile la distanta in felul urmator:

ComplexStockMarket objRef=(ComplexStockMarket)
ToyORB.getObjectReference(“NASDAQ”);
float price=objRef.get_price(“ABC SRL”);
String junk=objRef.whois_lowest_today();

Pentru aceasta, ClientSideProxy trebuie sa includa in sirul de octeti produs la


operatia marshal si informatia referitoare la ce operatie s-a cerut.
ServerSideProxy va deduce in operatia unmarshal despre ce operatie este vorba
ToyORB: Atentie la dependente !

• ToyORB trebuie sa poata fi folosit pentru orice tip de aplicatii


(StockMarket, ComplexStockMarket, InfoServer, MathServer, etc –
si orice alt tip, necunoscut la momentul crearii ToyORB)
• ToyORB nu poate sa depinda deloc de cod specific aplicatiilor !
– Marshaller: trebuie sa poata transforma in bytes orice combinatie de
parametrii
– ToyORB.getObjectReference(String ServerName) trebuie sa poata sa
creeze si returneze un obiect proxy client corespunzator tipului aplicatiei
(StockMarketClientSideProxy, MathServerClientSideProxy,
InfoServerClientSideProxy, etc), dar fara sa depinda de aceasta !
• Posibila solutie: utilizarea Reflection pentru crearea obiectului de
tipul corespunzator
Scenarii de localizare a serverelor

ToyORB.getObjectReference(“NASDAQ”);
StockMarketImpl
NASDAQ

StockMarketClient1

StockMarketImpl
StockMarketClient2 NIKKEI

ToyORB.getObjectReference(StockMarket);

InfoServerImpl
ToyORB.getObjectReference(“TimisInfo”)
TimisInfo

InfoClient1
Scenarii de localizare a serverelor
StockMarketImpl
NASDAQ
StockMarketClient1

StockMarketImpl
StockMarketClient2 NIKKEI

NamingService Address InfoServerImpl


InfoClient1 127.0.0.1, 1111 TimisInfo

NamingService

NASDAQ, StockMarket,127.0.0.1,1112
NIKKEI, StockMarket, 127.0.0.1,1113
TimisInfo, InfoServer, 127.001,1114
Scenarii de utilizare: Inregistrare Server
StockMarketImpl
NASDAQ

ToyORB.register
Requester

NamingService Address
127.0.0.1, 1111

Replyer
NamingService

NASDAQ, StockMarket, 127.0.0.1, 1112


Scenarii de utilizare: Serverul ready
StockMarketImpl
NASDAQ
StockMarketClient1

StockMarketServerProxy
Replyer

NamingService Address
127.0.0.1, 1111

Replyer
NamingService

NASDAQ, StockMarket, 127.0.0.1, 1112


Scenarii de utilizare: getObjectReference
StockMarketImpl
NASDAQ
StockMarketClient1

StockMarketServerProxy
Replyer
ToyORB.getObjectRef
Requester
NamingService Address
127.0.0.1, 1111

Replyer
NamingService

NASDAQ, StockMarket, 127.0.0.1, 1112


Scenarii de utilizare: s-a obtinut referinta
StockMarketImpl
NASDAQ
StockMarketClient1

StockMarketServerProxy
StockMarketClientProxy
Replyer
Requester

NamingService Address
127.0.0.1, 1111

Replyer
NamingService

NASDAQ, StockMarket, 127.0.0.1, 1112


ToyORB: Implementare NamingService

• NamingService mai complex (Trader):


– Localizarea unui obiect la distanta se face dupa numele sau
(“NASDAQ”)
– Localizarea unui obiect la distanta se face dupa descrierea
serviciului pe care il furnizeaza (StockMarket) -> se obtine o
referinta spre unul din obiectele inregistrate ca furnizand acest
serviciu
• Implementarea NamingService: sub forma de server
care are o adresa fixa cunoscuta de catre ToyORB
– ToyORB:getObjectReference Interactioneaza fiecare cu
– ToyORB:register NamingService
dupa tiparul Requester-Replyer
Scopul unui ORB
• Un Object Request Broker este o infrastructura pentru dezvoltarea
de aplicatii distribuite:
• Se refoloseste ca infrastructura in MULTE
aplicatii DIFERITE, NECUNOSCUTE
dezvoltatorului sau!
• Consecinte:
– Esential: ORB NU poate depinde in nici un fel de cod
specific acestor aplicatii
– Pentru cresterea “usability”: este de dorit ca Broker-ul
sa sprijine dezvoltatorul de aplicatii si in problema
scrierii proxy-urilor
• Tool-uri pentru generarea automata a proxy-urilor
ToyORB: Generarea automata a proxy-urilor

• Punct de start: scrieti manual proxy-urile pentru cel putin 2 aplicatii


diferite, pentru a identifica un Template comun
ToyORB: Implementare Proxy-uri StockMarket
call_service
send_request StockMarketServerSideProxy:
StockMarketClientSideProxy:
• Are un Replyer r
• Are un Requestor r • Il cunoaste pe StockMarketImpl s
• Are un Marshaller m • Are un Transformer t : primeste un sir de octeti si
• Pentru a rezolva operatia get_price: returneaza sirul de octeti transformat
• Pentru a realiza operatia get_price de ori de cate
pack_data – Cu ajutorul lui m – marshal, ori este solicitat:
transforma parametri de intrare(numele
companiei) intr-un sir de octeti While (true)
r.receive_transform_and_send_feedback(t(s));
forward_ – Cu ajutorul lui r -
deliver_and_wait_feedback, – Receptioneaza sirul de octeti reprezentand
request parametrii, t(s) il transforma in sir de octeti de
transmite catre ServerSideProxy sirul forward_ tip rezultat, care vor fi transmisi inapoi la
de octeti parametru si receptioneaza un response client
sir de octeti reprezentand rezultatul
– Cu ajutorul lui m - unmarshal, ServerTransformer:
unpack_data
transforma sirul de octeti obtinut in
valoarea rezultatului (pretul)
• Are un Marshaller m
• Pentru a rezolva transformarea:
– cu ajutorul lui m – unmarshal, reconstruieste
unpack_data parametri de intrare (numele companiei)
– Apeleaza operatia de la StockMarketImpl s si
Cu text rosu italics sunt obtine rezultatul
run_service
identificate operatiile – Cu ajutorul lui m - marshal, transforma
prin numele cu care apar in pack_data
rezultatul (pretul) in sir de octeti
Pattern-ul Broker
ToyORB: Template-uri pentru proxy:
Client Side Proxy

• Se presupune un server cu interfata ServiceX


• ServiceXClientSideProxy:
– Class ServiceXClientSideProxy implements ServiceX
– Fiecare operatie definita in interfata ServiceX este implementata in felul
urmator:
• Creaza mesajul (marshal): numele operatiei, (numarul si tipurile
parametrilor), valorile parametrilor
• Deliver_and_wait_feedback
• Extrage din mesajul de raspuns valoarea rezultatului (conform tipului
returnat de operatie) si o returneaza
ToyORB: Generare Client Side Proxy

– ServiceXClientSideProxy este o clasa care


implementeaza interfata ServiceX, deci depinde de
aplicatie !
– Pentru a genera Client Side Proxy:
• Varianta1 (general aplicabila): tipul ServiceX este cunoscut de
dinainte, Codul pentru ServiceXClientSideProxy este generat in
faza de design cu ajutorul unui tool si este instalat pe calculatorul
clientului (Exemple: CORBA, RMI in java < 1.5)
– Tool-ul de generare ia ca input descrierea interfetei ServiceX si genereaza cod
sursa care apoi e compilat
• Varianta 2 (pentru tehnologii care suporta forme de run time code
generation - dynamic proxy): codul clasei ServiceXClientSideProxy
este generat automat la runtime (nu trebuie utilizate tool-uri de
generare in faza de design), (Exemple: RMI in java dupa1.5 si
.NET Remoting)
ToyORB: Template-uri pentru proxy:
Server Side Proxy
• Se presupune un server cu interfata ServiceX
• ServiceXServerSideProxy:
– Class ServiceXServerSideProxy:
• are o referinta la obiectul server ServerXImpl
• Contine “server-loop” (while (true)
receive_transform_sendfeedback)
– Class ServiceXServerTransformer implements
ServerTransformer
• Primeste referinta la obiectul server ServerXImpl
• Extrage din mesajul primit (unmarshal) numele operatiei si valorile
parametrilor
• Invoca operatia pe obiectul server
– Varianta 1: secventa de cod de tip “switch-case” (Java 1.1, CORBA)
– Varianta 2: prin Reflection -> nu mai depinde de tipul ServiceX ->
devine un ServerSideProxy generic (Java 1.2, .NET)
• Creaza mesajul de raspuns(marshal) cu rezultatul invocarii operatiei
ToyORB: Generare Server Side Proxy

• Clasa ServiceXServerTransformer este cea care


depinde de aplicatie in masura in care trebuie sa
cunoasca metodele din interfata remote

– Varianta1 (general aplicabila): se genereaza cod sursa pentru


aceasta clasa, care va contine o secventa de cod de tip
“switch-case” cu cate un caz ptr fiecare operatie posibila
– Varianta2 (aplicabila daca limbajul in care e implementat obiectul
server suporta reflection): exista o clasa unica, generala,
valabila ptr orice aplicatie, care inlocuieste swich-case-ul cu
invocarea operatiei corespunzatoare prin reflection
Alte facilitati oferite de Middleware
• Exemplul introductiv ilustreaza doar facilitatile elementare oferite de
un Broker:
– Inregistrarea unui serviciu la Broker
– Localizarea unui serviciu prin Broker
– Obtinerea unei referinte la un obiect la distanta (o instant a proxy)
• In functie de fiecare tehnologie, se mai poate oferi suport si pentru
unele din urmatoarele:
– Invocare dinamica
– Livrare dinamica
– Transferul obiectelor (inclusiv remote objects) ca parametri la serviciile
la distanta – prin valoare sau referinta
– Activarea unui obiect la distanta
– Concurenta in interiorul obiectelor server
– Securitate
– Garbage collection pentru obiectele la distanta
– Interoperabilitatea intre clienti si servere din limbaje diferite
– Bridge cu alte tehnologii de Middleware
Alte facilitati oferite de Middleware - detalii

• Invocare statica vs. Invocare dinamica


– Invocare statica: daca clientul cunoaste de la design-time care este interfata
serviciului la distanta utilizat:
• Se pot genera clasele de tip ClientSideProxy pentru serviciul respectiv
• Clientul interactioneaza cu acest proxy
• Apelurile sunt hard-codate in codul sursa
– Invocare dinamica: daca clientul nu cunoaste la design-time care este interfata
serviciului la distanta utilizat (acesta va fi descoperit la runtime)
• Apelurile nu pot fi hardcodate in codul sursa al clientului
• Solutie: un mecanism tip Reflection: orice server ofera o operatie de tip invoke, care
primeste ca parametrii operatia concreta si valorile parametrilor
• Livrare statica vs livrare dinamica
– Livrare statica: Programul server cunoaste de la design-time care sunt obiectele
server pe care le gazduieste
– Livrare dinamica: Obiecte server pot fi create dinamic la runtime
• ServerSideProxy poate fi unul generic, care suporta o operatie de tip invoke ca la
invocarea dinamica
Alte facilitati oferite de Middleware – detalii (cont)

• Concurenta
– Varianta simpla: Programul server (ServerSideProxy) contine un ciclu in care
accepta cereri si le trateaza secvential
– Server concurent: creaza cate un thread pentru tratarea cererilor
• Problema: Obiectul server poate fi utilizat de thread-uri diferite in acelasi timp – poate
necesita utilizarea unor mecanisme de sincronizare
Alte facilitati oferite de Middleware – detalii (cont)

• Activarea obiectelor server


– Varianta simpla: Programul server creaza obiectul server, acesta
exista atat timp cat ruleaza programul server
– Activarea obiectelor la cerere: obiectul server este creat doar daca
apare prima cerere pentru el
• Activator: un server care:
– Are evidenta unde se gasesc Implementarile (clasele) din care pot fi instantiate
obiecte server
– Are evidenta obiectelor server create
– Primeste cererea de la client, daca obiectul server nu exista inca - il creaza,
altfel invoca operatia solicitata pe obiectul server
• Activator Pattern: Michael Stal, Douglas Schmidt, PLOP 2005
http://www.stal.de/Downloads/Activator.pdf
– Exemple: Implementation repository in CORBA, rmid (Java RMI
Activation System Daemon )
Alte facilitati oferite de Middleware – detalii (cont)

• Garbage collection pentru obiectele server:


– Obiectele server pentru care nu mai exista nici o remote reference pot fi
dezactivate
– Variante:
• Stil cooperativ: clientii anunta cand nu mai au nevoie/elibereaza referinta la server
object, serverul pastreaza evidenta prin contoare
• Brokerul pastreaza evidenta canalelor de comunicatie care sunt active
• Persistent remote reference
– Un client poate sa detina o remote reference catre un server object, chiar daca
acesta a fost oprit intre timp (accidental sau time-out)
– Daca clientul incearca sa acceseze obiectul server pentru care detine o referinta,
broker-ul trebuie sa il reactiveze si sa il aduca in starea in care acesta a fost
inainte de dezactivare
• sunt necesare mecanisme de salvare a starii obiectelor server, de aplicat automat
inainte de dezactivare
Alte facilitati oferite de Middleware – detalii (cont)

• Interoperability intre clienti si servere, indiferent de limbajul in care sunt


implementate:
– Interface Description Languages:
• Exista un model comun (model orientat pe obiecte, stabileste un sistem de tipuri,
operatii, interfete, exceptii)
• interfata obiectelor server este descrisa folosind un limbaj de descriere neutru
• Exista reguli (si tool-uri) care mapeaza conceptele IDL pe particularitatile unor limbaje
de programare concrete

– Arhitectura de referinta CORBA


CORBA: Arhitectura
Server
Remote
Client Remote
Interface
Object
IDL

IDL Skeleton
Dynamic IDL Stub (ServerSide
Interface Invocation (ClientSide ORB Object Implem
Proxy) Adapter Repository
Repository Interface Proxy) Interface

ORB (Object Request Broker)


CORBA - Pas1. Definire interfata

• Se defineste interfata
StockMarket
• Aceasta exporta operatia
get_price: module SimpleStocks {
– Parametru: numele companiei
cotate la bursa interface StockMarket {
– Rezultat: valoarea actiunilor float get_price(in string Company);
};
};

Specific CORBA:
•Interfata se defineste intr-
un limbaj neutru, CORBA
IDL Fisier StockMarket.idl
CORBA - Pas 2. Generare Proxy-uri

CORBA IDL Stub/Skeleton

Se genereaza automat din definitia interfetei IDL

> idl2java StockMarket.idl

Rezulta clasele/fisierele:
Client Stub: _st_StockMarket.java
Server Stub: _StockMarketImplBase.java
CORBA - Pas 3. Implementare Obiect

• Se implementeaza clasa
StockMarketImpl import org.omg.CORBA.*;
import SimpleStocks.*;
• Aceasta realizeaza operatia
get_price public class StockMarketImpl extends
_StockMarketImplBase {
public float get_price(in string
Specific CORBA: company) {
•Un obiect accesibil la float price=12345;
distanta trebuie sa extinda return price;
server-side-proxy-ul }
generat automat din public StockMarketImpl (String name) {
descrierea interfetei super(name);
•Acest lucru faciliteaza }
rezolvarea cazurilor cand }
limbajul nu permite
reflection
Fisier StockMarketImpl.java
CORBA - Pas 4. Implementare Server

• Se implementeaza un program
StockMarketServer, care import org.omg.CORBA.*;
Import SimpleStocks.*;
creaza un obiect de tip
StockMarketImpl, ce poate fi public class StockMarketServer {
accesat de la distanta public static void main(String[] args) {
try {
• Obiectul creat este inregistrat ORB orb=ORB.init();
sub numele “NASDAQ” BOA boa=orb.BOA_init();
StockMarketImpl stockMarketImpl=
new StockMarketImpl(“NASDAQ”);
Specific CORBA: boa.obj_is_ready(stockMarketImpl);
•ORB boa. Impl_is_ready();
•BOA } catch (Exception e) {}
}
}

Fisier StockMarketServer.java
CORBA - Pas 5. Implementare Client

• Se implementeaza un program import org.omg.CORBA.*;


StockMarketClient, care import SimpleStocks.*;
acceseaza un obiect de tip
StockMarket aflat la distanta, si public class StockMarketClient {
invoca operatia get_price public static void main(String[] args) {
pentru un nume de companie try {
ORB orb=ORB.init();
• Prin intermediul Broker se StockMarket market=
localizeaza obiectul cu numele StockMarketHelper.bind(orb,
“NASDAQ”);
“NASDAQ”
Specific CORBA: market.get_price(“ABC SRL”);
•StockMarketHelper = proxy } catch (Exception e) {}
generat }
•Codul client instantiaza direct }
client-side proxy ! (pentru ca
doar asa se poate trata si cazul
cand limbajul de implementare Fisier StockMarketClient.java
nu suporta reflection)
CORBA - Pas 6. Rulare aplicatie
Location service
(numele OSAgent e
specific unei anumite
implementari
CORBA)

> start osagent

> start java StockMarketServer

> start java StockMarketClient


Scenariu Broker in care clientul si
serverul sunt in limbaje diferite
1. Definire interfata obiect la distanta – in IDL neutru

IDL INTERFACE 2. Implementare obiect


StockMarket 4. Implementare Server
float get_price(Company) Folosing LANGUAGE2
5. Implementare Client
Folosind LANGUAGE1 StockMarketServer

StockMarketClient
ToyORB ToyORB StockMarketImpl
library impl library impl
in LANG1 in LANG2

3. Generare Proxy ByteComm ByteComm 3. Generare Proxy


TOOL1 IDL-to-LANG1 in LANG1 in LANG2 TOOL2 IDL-to-LANG2

StockMarket NamingService StockMarket


ClientSide PROXY ServerSide PROXY
Bibliografie suplimentara facultativa

• [POSA2]: Pattern-Oriented Software


Architecture – Volume 2: Patterns for
Concurrent and Networked Objects, Wiley,
2000.
http://www.cs.wustl.edu/~schmidt/POSA/POSA2/
The Java Dynamic Proxy
Proxy pattern
Classical Proxy Implementation vs Dynamic Proxy

A Classical Proxy Implementation requires the Programmer to write


the code of the Proxy class for every Original Interface and compile it.
A dynamic proxy class is a class that implements a list of interfaces specified
at runtime when the class is created and immediately instantiated
Java dynamic proxy
• A dynamic proxy class is a class that implements a list of interfaces specified at
runtime such that a method invocation through one of the interfaces on an
instance of the class will be encoded and dispatched to another object through a
uniform interface.
• Thus, a dynamic proxy class can be used to create a type-safe proxy object for a
list of interfaces without requiring pre-generation of the proxy class, such as
with compile-time tools.
• Method invocations on an instance of a dynamic proxy class are dispatched to a
single method in the instance's invocation handler, and they are encoded with a
java.lang.reflect.Method object identifying the method that was invoked and an
array of type Object containing the arguments.
• This process allows implementations to "intercept" method calls and reroute
them or add functionality dynamically. The dynamic proxy can act as a Decorator
pattern, where the proxy wraps invocations with additional functionality
The InvocationHandler Interface

public interface InvocationHandler {


Object invoke(Object proxy, Method method, Object[] args) throws
}

The job of an invocation handler is to actually perform


the requested method invocation on behalf of a
dynamic proxy. He gets a Method object (from the
Reflection API) and the objects that are the arguments
for the method call. In the simplest case, he can just
call Mehod.invoke() or add pre or post processings.
Proxy object – an instance
of the dynamic proxy class
created automatically at runtime

The service of the original


Object is called by Reflection
Creating a dynamic proxy in Java

• To create a proxy for some interface Foo:


• InvocationHandler handler = new MyInvocationHandler(...);
• Class proxyClass = Proxy.getProxyClass(
Foo.class.getClassLoader(), new Class[] { Foo.class });
• Foo f = (Foo) proxyClass. getConstructor(new Class[] {
InvocationHandler.class }). newInstance(new Object[] { handler
});

• A dynamic proxy class (simply referred to as a proxy class below) is a class that implements a list
of interfaces specified at runtime when the class is created, with behavior as described below. A
proxy interface is such an interface that is implemented by a proxy class. A proxy instance is an
instance of a proxy class.
• The unqualified name of a proxy class is unspecified. The space of class names that begin with
the string "$Proxy" should be, however, reserved for proxy classes. A proxy class extends
java.lang.reflect.Proxy. A proxy class implements exactly the interfaces specified at its creation, in
the same order.
Creating a dynamic proxy in Java

• A shorter way to create a proxy instance for Foo:


• InvocationHandler handler = new MyInvocationHandler(...);
• Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new
Class[] { Foo.class }, handler);
Java dynamic proxy
• To read more about java dynamic proxy:
• https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html
• https://docs.oracle.com/javase/7/docs/technotes/guides/reflection/proxy.html
• IBM technical library: http://www.ibm.com/developerworks/java/library/j-jtp08305.html
• https://opencredo.com/dynamic-proxies-java-part-2/
Persistenta datelor
• Multe aplicatii doresc sa asigure
persistenta datelor
• Metode/Tehnologii: •Probleme:
–Decuplarea componentelor
– Fisiere care fac accesul la
– Serializare date(specifice unei anumite
tehnologii) de celelalte parti
– Baze de date ale aplicatiei
–Abstractizarea accesului la
date
–Transformarea datelor intre
OO domain model si un
model de persistenta non-OO
(BD relationale, fisiere diferite
structuri)
Continutul cursurilor
• Tehnologii
– XML :
• JAXP: Java API for XML Procesing (SAX, DOM)
• JAXB: Java Architecture for XML Binding
– JDBC: API in Java care permite unui program Java sa interactioneze (query, update) cu
baze de date relationale
• Pattern for mapping object oriented to relational concepts
– OO concepts: aggregation, inheritance, association
– Relational model: tables, foreign key references to other tables
• Data Acess Patterns:
– Modul in care se face accesul la date depinde de
• tipul sursei de date: baze de date, fisiere
• implementarea concreta a acestui tip de sursa de date
– Se doreste decuplarea componentelor care fac accesul la date (puternic dependente de
API-ul tehnologiei folosite) de restul componentelor de business
– Data Access Object Pattern
– Variante (Data mapper, Table data gateway, Active record)
Tehnologii XML pentru Java
• JAXP: Java API for XML Procesing (SAX,
DOM)
– Bibliografie:
– Tutorial Oracle:
http://download.oracle.com/javase/tutorial/jaxp/index.html

• JAXB: Java Architecture for XML Binding


– Bibliografie:
– http://download.oracle.com/javase/6/docs/technotes/guides/xml/jaxb/i
ndex.html
XML
• XML este un standard pentru descrierea structurii documentelor
• eXtensible Markup Language
– Format text pentru descrierea datelor => simplu de utilizat
– Standardizat => exista API-uri care pot fi utilizate pentru a simplifica
parsing-ul (sintaxa reprezentarii datelor)
– Applicatiile care utilizeaza XML trebuie sa stabileasca doar partea
semantica a reprezentarii datelor
XML Tags
• Tags
– Reprezinta Metainformatii incluse in text
• Similare ca forma cu cu HTML tags
• Diferenta intre HTML tags si XML tags: HTML tags contin
informatii de reprezentare a datelor (ex: <B>), in timp ce XML
tags contin informatii de structurare si semantica a datelor
– XML tags sunt case-sensitive
– Pot contine text sau alte tag-uri
– Fiecare trebuie sa aiba un tag de sfarsit:
– <tag> </tag>
– O pereche de tag-uri fara continut se poate scrie ca si <tag />
• Tag Attributes
– Defineste perechi name-value in interiorul unui tag
• <dot x=“72” y=“13” />
Caractere speciale
• Unele caractere sunt utilizate in tag-uri si descrieri si pentru
reprezentarea lor explicita se folosesc secvente:
• Exemple:
– < se codifica &lt;
– > se codifica &gt;
– & se codifica &amp;
– “ se codifica &quot;
– ‘ se codifica &apos;
Organizarea documentelor XML
• Un document XML incepe cu o declaratie:
<?xml version='1.0' encoding='utf-8'?>
• Forma arborescenta:
– Exista exact un element radacina
– Alte elemente sunt incuibate
– Prin element se intelege o secventa cuprinsa intre 2 tag-uri pereche
<person>
<firstname>Ion</firstname>
<lastname>Popescu</lastname>
<age>30</age>
<ssn>2711130345678</ssn>
</person>
Reprezentarea datelor

• Dorim sa reprezentam coordonatele unor puncte in plan

XML
Stiluri de reprezentare a datelor:
Tag-uri sau atribute ?
• Dorim sa reprezentam coordonatele unor puncte in plan
• Exista 2 metode de structurare si reprezentare:
– Utilizand atribute:
<dot x=“25" y=“33">
– Utilizand tag-uri incuibate:
<dot>
<x>25</x>
<y>33</y>
</dot>
• Ce metoda de reprezentare este de preferat?
– Atribute: daca datele sunt scurte:
• <dot x='65' y=‘23' />
– Tag-uri: daca datele sunt lungi:
• <description>Acest program este foarte util tuturor</description>
– Tag-uri: daca numarul de atribute ce caracterizeaza un element nu este
fix: <polygon> <point> .. </point> <point>..</point> <point>..</point>
</polygon>
Exemplu 1: document XML –
datele reprezentate in atribute
• Dots – un set de puncte in plan, caracterizate de coordonatele (x,y)
• Root node: “dots”
• Child nodes: “dot”, cu atributele x si y
dots.xml

<?xml version="1.0" encoding="UTF-8" ?>


<dots>
<dot x="32" y="100" />
<dot x="17" y="14" />
<dot x="18" y="58" > </dot>
</dots>
Exemplu 2: document XML –
datele reprezentate in tag-uri incuibate
• Points – un set de puncte in plan, caracterizate de coordonatele (x,y)
• Root node: “points”
• Child nodes: “point”, fiecare avand child nodes “x” si “y”
points.xml Un document
<?xml version="1.0" encoding="UTF-8" ?>
-<points>
XML trebuie sa
<point> fie:
<x>12</x> Well-formed si
<y>24</y>
</point>
Valid
<point>
<x>22</x>
<y>11</y>
</point>
</points>
Documente XML: Well-formed
"well-formed": un document corect din punctul de vedere al
regulilor sintactice generale XML
• are exact un element radacina
• fiecare element are un tag de sfarsit
• elementele sunt incuibate corect
• valorile atributelor sunt intre ghilimele
Documente XML: Valide
XML Schema
• “Valid”: un document care respecta anumite reguli impuse structurii
• Metode de specificare formala a structurii unui document (unei clase de
documente) XML:
– XML DTD (Data Type Definition):
– XML Schema (XSD): un limbaj ce impune constrangeri asupra structurii
documentelor XML
• Pentru o clasa de documente XML, se pot impune reguli privitoare la:
– Ce tag-uri sunt permise, in ce ordine pot sa apara, de cate ori, ce atribute pot
sa aiba, de ce tipuri, etc.
• Parserele XML cu validare verifica respectarea constrangerilor impuse de
o schema specificata
• XML Schema Tutorial: http://www.w3schools.com/schema/default.asp
Exemplu 1 XML Schema
• Pentru reprezentarea unui set de puncte in plan, se
stabilesc urmatoarele reguli:
– Elementul radacina este dots
<xs:element name="dots">
– Acesta poate contine un numar oarecare de elemente de tip dot
• Este un tip complex ptr ca contine alte elemente
<xs:complexType>
• Contine o secventa de alte elemente
<xs:sequence>
– Fiecare element dot are 2 atribute, x si y, cu valori intregi
<xs:attribute name="x" type="xs:integer" />
Exemplu 1 XML Schema
dots.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs=http://www.w3.org/2001/XMLSchema>
<xs:element name="dots">
<xs:complexType>
<xs:sequence>
<xs:element name="dot" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="x" type="xs:integer" use="required"/>
<xs:attribute name="y" type="xs:integer" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Exemplu: document XML cu schema

dots.xml

<?xml version="1.0" encoding="UTF-8" ?>


<dots xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="dots.xsd">>
<dot x="32" y="100" />
<dot x="17" y="14" />
<dot x="18" y="58" > </dot>
</dots>
Exemplu 2 XML Schema
• Pentru reprezentarea unui set de puncte in plan, se
stabilesc urmatoarele reguli:
– Elementul radacina este points
<xs:element name=“points">
– Acesta poate contine un numar oarecare de elemente de tip point
• Este un tip complex ptr ca contine alte elemente
<xs:complexType>
• Contine o secventa de alte elemente point
<xs:sequence>
– Fiecare element point este de tip complex, fiind o secventa de 2
elemente x si y
<xs:element name="x" type="xs:integer" />
– Elementele x si y sunt elemente simple (contine numai text, nu
contine alte elemente sau atribute)
Exemplu 2 XML Schema
points.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="points">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="point">
<xs:complexType>
<xs:sequence>
<xs:element name="x" type="xs:integer" />
<xs:element name="y" type="xs:integer" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Suport pentru editarea XML
• Fisierele XML pot fi editate cu orice editor de texte (Notepad,
etc)
• Este recomandabila utilizarea unui XML Editor care poate ajuta
la validarea unui document XML in conformitate cu o schema
data si poate impune respectarea structurii permise inca din
timpul editarii
– XMLSpy
– Mediile Integrate de Dezvoltare (IDE) curente contin diverse
facilitati pentru lucrul cu XML :
• NetBeans
• .NET Studio
• Eclipse
Suport pentru prelucrarea
XML in Java
• JAXP (Java API for XML Processing)
– Suporta procesarea datelor XML de catre aplicatii scrise in
Java
– Suport pentru XML parsing: 2 standarde diferite:
– SAX (Simple API for XML Parsing): in timpul operatiei de
parsing se genereaza evenimente care anunta elementele
identificate, este sarcina aplicatiei sa trateze acele evenimente
furnizand metodele de callback (pentru a-si construi o structura
de date)
– DOM (Document Object Model): operatia de parsing
construieste in memorie o reprezentare arborescenta a datelor
din XML
– Suport pentru transformarea documentelor XML:
– XSLT (Extensible Stylesheet Language Transformation).
SAX

http://download.oracle.com/javase/tutorial/jaxp/intro/simple.html
Citire XML cu SAX
Exemplu: XMLDotReader - citeste date din fisierul dots.xml

// standard imports for SAX


import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

// Implementing a ContentHandler to handle the SAX events


public class XMLDotReader extends DefaultHandler {

}
Construirea parserului SAX
// create an instance of the ContentHandler
DefaultHandler handler= new XMLDotReader();

SAXParserFactory factory = SAXParserFactory.newInstance();


try {
// use the default non-validating parser
SAXParser saxParser = factory.newSAXParser();

saxParser.parse(new File(“dots.xml”), handler);

} catch (Exception ex) {


ex.printStackTrace();
}
Tipuri de evenimente
public void startDocument() throws SAXException ;

public void endDocument() throws SAXException ;

// Called at start of each element


public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException ;

// Called at the end of each element


public void endElement(java.lang.String uri, java.lang.String localName,
java.lang.String qName) throws SAXException;

// Called for characters between nodes.


public void characters(char buf[], int offset, int len) throws SAXException;
Tratarea evenimentelor
public class XMLDotReader extends DefaultHandler {

public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
System.out.println("start element:" + qName);
if (qName.equals("dot")) {
x = Integer.parseInt(atts.getValue("x"));
y = Integer.parseInt(atts.getValue("y"));
System.out.println(x + ", " + y);
}
}

}
Cod Sursa Exemplu1
• Vezi pagina web a cursului: XMLDotsReader.java
Rezultatele rularii

startDocument
start element:dots
dots.xml start element:dot
dot: 32, 100
end element:dot
<?xml version="1.0" encoding="UTF-8" ?>
<dots> start element:dot
<dot x="32" y="100" /> dot: 17, 14
<dot x="17" y="14" /> end element:dot
<dot x="18" y="58" > </dot> start element:dot
</dots> dot: 18, 58
end element:dot
end element:dots
endDocument
Rezultatele rularii
• Daca se modifica dots.xml astfel incat sa nu mai fie well-formed
(lipseste inchiderea la al 2-lea tag dot)
startDocument
start element:dots
start element:dot
dot: 32, 100
end element:dot
start element:dot
dot: 17, 14
start element:dot
dot: 18, 58
end element:dot
org.xml.sax.SAXParseException: The end-tag for element type "dot" must end with
a '>' delimiter.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAX
ParseException(Unknown Source)
Rezultatele rularii
• Daca se modifica fisierul dots.xml astfel incat sa contina si alte
nume de tag-uri (se inlocuieste al doilea tag dot cu dotu),
nemaifiind conform cu schema

startDocument
start element:dots
start element:dot
dot: 32, 100
end element:dot
start element:dotu
end element:dotu
start element:dot
dot: 18, 58
end element:dot
end element:dots
endDocument
Parser cu validare
public class ValidatingXMLDotReader extends DefaultHandler {

// changes to create a validating parser

Static final String JAXP_SCHEMA_LANGUAGE=


"http://java.sun.com/xml/jaxp/properties/schemaLanguage";
static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";

SAXParserFactory factory = SAXParserFactory.newInstance();


try {
factory.setValidating(true);
factory.setNamespaceAware(true);
SAXParser saxParser = factory.newSAXParser();
saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
saxParser.parse(new File(“dots.xml”), handler);
} catch (Exception ex) {
ex.printStackTrace();
}
Parser cu validare – evenimentul
error
public void error(SAXParseException e)
throws SAXParseException
{
throw e;
}
Exceptii SAX – tratare in detaliu
try {

}catch (SAXParseException spe) {
// Error generated by the parser
System.out.println(“Parsing Error: line ”+spe.getLineNumber()+” ,
”+spe.getMessage());

} catch (SAXException sxe) {


// Error generated by application or parser initialization

} catch (ParserConfigurationException pce) {


// parser with specified options cann’t be built

}catch (IOException ioe) {

}catch (Throwable t) {

}
Cod Sursa Exemplu2
• Vezi pagina web a cursului:
ValidatingXMLDotsReader.java
Rezultatele rularii
• Se ruleaza ValidatingXMLDotReader pe varianta modifica
fisierul dots.xml care contine si alte nume de tag-uri (se
inlocuieste al doilea tag dot cu dotu), nemaifiind conform cu
schema
startDocument
start element:dots
start element:dot
32, 100
end element:dot

** Parsing error, line 5, uri file:/C:/Documents%20and%20Settings/user/Desktop/x


ml-marti/dots.xml
cvc-complex-type.2.4.a: Invalid content was found starting with element 'dotu
'. One of '{dot}' is expected.
org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found
starting with element 'dotu'. One of '{dot}' is expected.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAX
DOM

http://download.oracle.com/javase/tutorial/jaxp/intro/dom.html
Element Node
• Un element/nod corespunde unei sectiuni cuprinsa
intre <tag>… </tag>
• Un nod poate contine alte noduri child
• Un nod poate avea atribute cu valori
• Exista un nod radacina a documentului
Citirea unui XML Document in DOM

// Standard imports for XML


import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.w3c.dom.*;
....
Construirea parserului XML DOM
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

try {
DocumentBuilder db = dbf.newDocumentBuilder();
// Gets default non-validating parser
// Parse the XML to build the whole doc tree
Document doc = db.parse(new File(“dots.xml”));

} catch (SAXParseException spe) { // Error handling code the same as with SAX
} catch (SAXException sxe) {
} catch (ParserConfigurationException pce) {
} catch (IOException ioe) {
} catch (Throwable t) {
}
Traversarea DOM
// Get root node of document
Element root = doc.getDocumentElement();

// Get list of children of given tag name


NodeList list = root.getElementsByTagName(“dot");

// Number of children in list


int len = list.getLength();

// Get nth child


Element elem = (Element) list.item(n);

// Get an attribute out of a element


// (returns "" if there is no such attribute)
String s = elem.getAttribute(“x");
Modificarea DOM in memorie
// Create a new node (still needs to be added)
Element elem = document.createElement(“dot");

// Append a child node to an existing node


node.appendChild(elem);

// Set an attribute/value binding in a node.


elem.setAttribute(“x”, “12”);
XSLT (The Extensible Stylesheet Language
Transformations APIs )

•XSLT API lets you transform XML


into other forms

•A TransformerFactory object is
instantiated and used to create a
Transformer.
•The source object is the input to
the transformation process. A
source object can be created from
a SAX reader, from a DOM, or from
an input stream.
•The result object is the result of
the transformation process. That
object can be a SAX event handler,
a DOM, or an output stream.

http://download.oracle.com/javase/tutorial/jaxp/xslt/index.html
Scrierea DOM din memorie in XML

import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

// Document doc exists already in memory at this point …

try {
TransformerFactory tranFact = TransformerFactory.newInstance( );
Transformer tran = tranFact.newTransformer( );
DOMSource DSource = new DOMSource(doc);
StreamResult SResult = new StreamResult(new FileOutputStream(“copie.xml”));
tran.transform(DSource, SResult);
} catch (TransformerConfigurationException tce) {
} catch (TransformerException te) {
}
Cod Sursa Exemplu3
• Vezi pagina web a cursului: XMLDotsDOM.java
Concluzii:
XML: Avantaje si dezavantaje
• Format standard
– Similar fisierelor text – editabil manual, citibil direct
• Big and Slow:
• Reprezentarea datelor in format text ocupa foarte mult spatiu !
• Adecvat pentru reprezentarea datelor din fisiere de configurare,
sau ca format de transport al datelor
• NU este adecvat pentru reprezentarea continutului unei ”baze
de date” de mari dimensiuni
Concluzii:
SAX vs DOM
• SAX:
• “de facto standard” elaborat de comunitatea XML-DEV
http://www.saxproject.org/
• Parsarea se face “online” pe masura ce se citeste documentul XML
• Parsarea se face mai rapid, consuma mai putina memorie
• Aplicatia trebuie sa isi construiasca singura modelul de date
• Adecvat pentru procesari de tip state-independent, dificil de folosit
pentru procesari state-dependent
• DOM:
• Model standard definit de W3C (model independent de limbaj si
platforma) http://www.w3.org/DOM/
• Parsarea construieste intai intregul model al documentului XML in
memorie => mai incet, mai multa memorie
• Modelul din memorie este mai usor de transformat si salvat din
nou ca XML
Concluzii:
JAXP
• JAXP: Java API for XML processing:
• http://download.oracle.com/javase/tutorial/jaxp/index.html
• Transpune diferitele modele de referinta existente pentru
procesarea XML in API-uri Java
• Pentru fiecare model, ofera un API uniform de parsing care
constituie o interfata ce trebuie respectata de diferitii furnizori de
parsere concrete
• Nu impune anumite implementari concrete pentru parsere !
(ParserFactory-urile pot fi configurate cu system property-urile
javax.xml.parsers.SAXParserFactory si
javax.xml.parsers.DocumentBuilderFactory )
Concluzii:
XML: SAX sau DOM sau ...
• Alte modalitati pentru XML parsing in Java:
• StAX:
• Standard JSR 173: Streaming API for XML http://jcp.org/en/jsr/detail?id=173
• Implementat si el in JAXP
http://download.oracle.com/javase/tutorial/jaxp/stax/index.html
• Este un model event-driven, ca si SAX
• Produce output in mod incremental; mod de lucru adecvat si cand sursa
de date este dinamica (din retea)
• Spre deosebire de SAX (care este de tip push-parsing) StAX este un
model de tip pull-parsing
• Bidirectional: suporta atat citirea (parsarea) cat si scrierea(generarea)
documentelor XML
• JDOM: http://jdom.org/
• DOM4J: http://dom4j.sourceforge.net/
Concluzii:
XML parsing sau ...
• In contextul in care XML
Class Dots e folosit ca modalitate
Class Dots instance de a asigura persistenta
datelor:
• Starea obiectelor trebuie
salvata respectiv
reconstituita din date
XML => acest lucru se
poate face prin parsarea
respectiv generarea XML
Dots schema
XML • Problema: trebuie scris
mult cod cu un continut
XML file complying
with Dots Schema standard => procesul se
poate automatiza
XML data binding
•XML data binding: procesul de
Class Dots reprezentare a informatiilor
dintr-un document XML ca
Class Dots instance obiect in memorie

•Tool-uri/API-uri care
automatizeaza procesul de
XML data binding: creaza
automat mapari intre
elementele dintr-o schema XML
si campurile unei clase
Dots schema •Exemplu: JAXB
XML
XML file complying
with Dots Schema
JAXB
The Java Architecture for XML Binding (JAXB)
“provides a fast and convenient way to bind between XML schemas and
Java representations”
https://docs.oracle.com/javase/tutorial/jaxb/intro/arch.html

http://
Exemplu utilizare JAXB
• Pasi:
1. Creare/Obtinere schema XML
2. Rulare Binding Compiler (direct sau transparent prin intermediul
facilitatilor oferite de un IDE) => rezulta cod sursa generat automat
pentru clasele care vor contine datele
3. Scrierea codului
• Se poate:
– Transforma fisiere XML conforme cu schema data in instante ale claselor
corespunzatoare (unmarshal)
– Transforma instante ale claselor in fisiere XML (marshal)
• se utilizeaza:
– JAXB API
– Codul generat anterior
Exemplu utilizare JAXB
Pas1: Schema XML
dots.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs=http://www.w3.org/2001/XMLSchema>
<xs:element name="dots">
<xs:complexType>
<xs:sequence>
<xs:element name="dot" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="x" type="xs:integer" use="required"/>
<xs:attribute name="y" type="xs:integer" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Exemplu utilizare JAXB
Pas2: Clase generate automat
package generated; public static class Dot {
protected BigInteger x;
public class Dots { protected BigInteger y;
protected List<Dots.Dot> dot; public BigInteger getX() {
return x;
public List<Dots.Dot> getDot() { }
if (dot == null) { public void setX(BigInteger value) {
dot = new ArrayList<Dots.Dot>(); this.x = value;
} }
return this.dot; public BigInteger getY() {
} return y;
}

public void setY(BigInteger value) {


this.y = value;
}
}
}
Exemplu utilizare JAXB
Pas2: Clase generate automat - cont
package generated;

public class ObjectFactory {

public ObjectFactory() {
}

public Dots.Dot createDotsDot() {


return new Dots.Dot();
}

public Dots createDots() {


return new Dots();
}

}
Exemplu utilizare JAXB
Pas3: Codul care trebuie scris
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import generated.*;
Exemplu utilizare JAXB
Pas3: Codul care trebuie scris - cont
try {
JAXBContext jc = JAXBContext.newInstance("generated");
Unmarshaller u = jc.createUnmarshaller();

Dots dots = (Dots) u.unmarshal(new FileInputStream("dots.xml"));

List dotList = dots.getDot();

for (Iterator iter = dotList.iterator(); iter.hasNext() ; ) {


Dots.Dot item = (Dots.Dot) iter.next();
System.out.println("x=" + item.getX() + " y=" + item.getY() + "\n");
}

} catch (JAXBException je) {


je.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
Persistenta datelor
• Multe aplicatii doresc sa asigure persistenta
datelor
• Metode/Tehnologii: • Probleme:
– Decuplarea componentelor
– Fisiere care fac accesul la
– Serializare date(specifice unei anumite
tehnologii) de celelalte parti
– Baze de date ale aplicatiei
– Abstractizarea accesului la
date
– Transformarea datelor intre
OO domain model si un model
de persistenta non-OO (BD
relationale, fisiere diferite
structuri)
Baze de date
(review BD)
• Baza de date: reprezinta o modalitate de stocare a
datelor, astfel incat acestea sa poata fi regasite
• Baza de date relationala (Relational Database):
– Informatiile sunt organizate in una sau mai multe tabele (Table)
– O tabela are un nume si una sau mai multe coloane (Columns)
– Fiecare coloana are un nume si un tip de date
– Fiecare data elementara este stocata pe o linie (Row) din
taabela
– O tabela = o relatie = o colectie de obiecte de acelasi tip (liniile)
Exemplu

Database: “Company”
Table: “Employees” Table: “Cars”
Exemplu
Table Employees

Employee_Number First_name Last_Name Date_of_Birth Car_Number

10001 Axel Washington 28-Aug-43 5

10083 Arvid Sharma 24-Nov-54 null

10120 Jonas Ginsberg 01-Jan-69 null

10005 Florence Wojokowski 04-Jul-71 12

10099 Sean Washington 21-Sep-66 null

10035 Elizabeth Yamaguchi 24-Dec-59 null


Exemplu

Table Cars

Car Number Make Model Year

5 Honda Civic DX 1996

12 Toyota Corolla 1999


Reguli de integritate
• Intr-o tabela nu pot exista 2 linii identice (DBMS verifica aceasta)
• Valorile unei coloane nu pot fi tablouri/colectii de valori
• Valori nule: valoare speciala prin care se marcheaza o valoare lipsa
(nu e zero sau blanc !)
• Cheie primara (primary key): una sau mai multe coloane care
identifica (diferentiaza) liniile. Coloanele care fac parte din cheia
primara nu pot avea valori nule
• Cheie straina (foreign key):
– Exemplu: Car_Number: primary key in table Cars, foreign key in table
Employees
DataBase Management Systems
• Sisteme de gestiune a
DBMS
bazelor de date (Data
Base Management
System – DBMS) DB Query Language

DBMS Engine

Database files
JDBC:
Java <-> Relational Databases
DBMS

DB Query Language SQL

Java Application
DBMS Engine
JDBC API

JDBC Driver

Database files
JDBC
(Java Database Connectivity) (?)
JDBC
Bibliografie:

Sun tutorial on JDBC:


http://download.oracle.com/javase/tutorial/jdbc/index.html

Laborator: Java DB = Sun’s supported distribution of the open source Apache Derby
database
http://developers.sun.com/javadb/

Exemple cod (folosind JDBC cu Derby Embedded):


http://www.cs.utt.ro/~ioana/arhit/exemple_jdbc.html

Apache Derby tutorial: http://db.apache.org/derby/papers/DerbyTut/index.html


Ce este JDBC
• JDBC: o tehnologie care permite programelor Java programs
sa interactioneze cu baze de date relationale (folosind
limbajul de interogare standard SQL).
• Folosind JDBC, un program poate:
– Stabili conexiuni cu diferite sisteme de baze de date
– Executa comenzi (SQL) pentru a crea, actualiza, manipula
datele si a receptiona rezultate
– Inspecta si manuipula meta-datele bazei de date
• JDBC este doar un API care permite programului sa interactioneze
cu un sistem de gestiune a bazelor de date – acesta (un server de
baze de date) trebuie sa existe separat !
– Java DB (fost Apache Derby)
– MySQL
SQL: Prezentare generala
• SQL (Structured Query Language): un limbaj
standard de interogare a bazelor de date
• Categorii de comenzi SQL:
– Data manipulation – realizeaza adaugarea,
regasirea, modificarea sau stergerea datelor; aceste
comenzi utilizeaza baza de date.
• SELECT, UPDATE, DELETE, INSERT
– Data definition – realizeaza crearea, configurarea
sau stergerea tabelelor, bazelor de date, views, sau
indexes; aceste comenzi administreaza baza de date.
• CREATE, DROP
SQL: Comanda SELECT
• Comanda SELECT este folosita pentru interogari
(queries); selecteaza valorile de pe coloanele
specificate pentru toate liniile care corespund criteriului
specificat de clauza WHERE

• Exemple:

SELECT First_Name, Last_Name FROM Employees WHERE


Car_Number IS NOT NULL
SELECT * FROM Employees
SQL: Clauza WHERE
• Clauza WHERE poate pune conditii privitoare la valorile
anumitor coloane
• Clauza WHERE poate insoti comenzile SELECT,
UPDATE, DELETE

• Exemple:

SELECT First_Name, Last_Name FROM Employees WHERE


Last_Name LIKE 'Washington%'
SELECT First_Name, Last_Name FROM Employees WHERE
Last_Name LIKE ‘Ba_man‘
SELECT First_Name, Last_Name FROM Employees WHERE
Employee_Number < 10100 and Car_Number IS NULL
SQL: Join
• Se refera la posibilitatea de a regasi date din mai mult de
o tabela la o interogare

• Exemplu:

• Gaseste angajatii care au masini de servici si afiseaza


numele angajatului (din tabela employees), numarul
masinii, marca, modelul si anul fabricatiei (din tabela
cars)

• SELECT Employees.First_Name, Employees.Last_Name,


Cars.Make, Cars.Model, Cars.Year FROM Employees,
Cars WHERE Employees.Car_Number = Cars.Car_Number
SQL: Comanda INSERT
• Comanda INSERT se utilizeaza pentru a adauga noi
linii de date intr-un tabel

• Exemple

insert into SUPPLIERS values(49, 'Superior Coffee',


'1 Party Place', 'Mendocino', 'CA', '95460');

insert into COFFEES values('Colombian', 00101, 7.99,


0, 0);
SQL: Comanda UPDATE

• Comanda UPDATE se foloseste pentru a


modifica valori din tabele

• Exemple:

UPDATE suppliers
SET zip = ‘99999’
WHERE zip = ‘95460’
UPDATE coffees SET price = 9.99
WHERE price<=5.0
SQL:Comanda DELETE
• Comanda DELETE se foloseste pentru a sterge linii din
tabele

DELETE FROM coffees WHERE price > 100


SQL: Comanda CREATE
create table SUPPLIERS (
SUP_ID integer NOT NULL, SUP_NAME varchar(40)
NOT NULL, STREET varchar(40) NOT NULL, CITY
varchar(20) NOT NULL, STATE char(2) NOT NULL,
ZIP char(5), PRIMARY KEY (SUP_ID));

create table COFFEES (


COF_NAME varchar(32) NOT NULL, SUP_ID int NOT
NULL, PRICE numeric(10,2) NOT NULL, SALES
integer NOT NULL, TOTAL integer NOT NULL,
PRIMARY KEY (COF_NAME), FOREIGN KEY (SUP_ID)
REFERENCES SUPPLIERS (SUP_ID));
Arhitectura aplicatiilor JDBC
• API-ul JDBC suporta atat arhitecturi 2-tiers si 3-tiers

From: http://download.oracle.com/javase/tutorial/jdbc/overview/index.html
Arhitectura de baza JDBC
• JDBC Driver: asigura comunicatia cu un anumit server
de baze de date, cu particularitatile lui
• JDBC Driver poate fi realizat dupa mai multe tipuri

Java Application
Application
JDBC API Database
Java Core
Server
APIs JDBC Driver

JVM
Database
Tipuri de drivere JDBC (1)

Type 1: JDBC Database


Java JDBC MS
ODBC Bridge Server
App API ODBC
Bridge Driver
Database

Type 1 JDBC drivers: ODBC Bridge: Drivers that implement the


JDBC API as a mapping to another data access API, such as ODBC
(Open Database Connectivity). Drivers of this type are generally
dependent on a native library, which limits their portability. The JDBC-
ODBC Bridge is an example of a Type 1 driver.
Tipuri de drivere JDBC (2)

Type 2: Java JDBC JDBC


Native App API Driver
DB API Native API Native
Database
Library API

Type 2 JDBC drivers: Native DB API: Drivers that are written partly in the
Java programming language and partly in native code. These drivers
use a native client library specific to the data source to which they
connect. Again, because of the native code, their portability is limited.
Oracle's OCI (Oracle Call Interface) client-side driver is an example of a
Type 2 driver.
Tipuri de drivere JDBC (3)

Type 3: JDBC Database


Java JDBC Database
Pure Driver Translator
Server
App API
Java
Database

Type 3 JDBC drivers: Pure Java: Drivers that use a pure Java client and
communicate with a middleware server using a database-independent
protocol. The middleware server then communicates the client's
requests to the data source.
Tipuri de drivere JDBC (4)
Type 4:
JDBC Database
Pure Java JDBC Server
Driver
Java App API
Direct
Database

Type 4 JDBC drivers: Pure Java Direct: Drivers that are pure Java and
implement the network protocol for a specific data source. The client
connects directly to the data source.

Java DB (Derby) comes with two Type 4 drivers, an Embedded driver and a
Network Client Driver. MySQL Connector/J is a Type 4 driver.
Embedded Derby - Network Derby

The Derby engine does not run in a


separate process, and there are no An application can also access a Derby database using
separate database processes to start up the client/server mode. This is achieved via a framework
and shut down. (Derby Network Server) that embeds Derby and handles
The Derby database engine runs inside database requests from applications, including
the same Java Virtual Machine (JVM) as applications running in different JVMs on the same
the application. machine or on remote machines.
Structura generala a unui
program utilizand JDBC
• Secventa tipica de operatii pentru interactiunea cu o baza
de date via JDBC:
– Incarca driver-ul JDBC potrivit sistemului de baze de date utilizat
(prin classname)
– Deschide o conexiune (Connection) catre baza de date (folosind
URL)
– Creaza instructiuni (Statement) (folosind Connection-ul care a
fost deschis)
– Executa instructiunile
– Eventual proceseaza rezultatele, daca exista (printr-un ResultSet
returnat)
– Inchide Connection

http://download.oracle.com/javase/tutorial/jdbc/basics/index.html
Establishing a Connection
• First, you need to establish a connection with the data source you want to
use.
– A data source can be: a DBMS, a legacy file system, or some other source of
data with a corresponding JDBC driver.
• DriverManager:
– This fully implemented class connects an application to a data source, which is
specified by a database URL.
– When this class first attempts to establish a connection, it automatically loads
any JDBC 4.0 drivers found within the class path. Note that your application must
manually load any JDBC drivers prior to version 4.0.
– Connecting to your DBMS with the DriverManager class involves calling the
method DriverManager.getConnection.
– The method DriverManager.getConnection establishes a database connection.
This method requires a database URL, which varies depending on your DBMS
Specifying Connection URL’s
• A database connection URL is a string that your DBMS JDBC driver
uses to connect to a database.
• It can contain information such as:
– where to search for the database
– the name of the database to connect to
– configuration properties.
• The exact syntax of a database connection URL is specified by your
DBMS !
• See examples for Java DB and MySQL
Java DB Database Connection
URLs
Java DB Database Connection URLs format:
• jdbc:derby:[subsubprotocol:][databaseName][;attribute=value]*
• subsubprotocol specifies where Java DB should search for the
database, either in a directory, in memory, in a class path, or in a
JAR file. It is typically omitted.
• databaseName is the name of the database to connect to.
• attribute=value represents an optional, semicolon-separated list of
attributes. These attributes enable you to instruct Java DB to
perform various tasks, including the following:
– Create the database specified in the connection URL.
– Encrypt the database specified in the connection URL.
– Specify directories to store logging and trace information.
– Specify a user name and password to connect to the database.
• Examples:
– jdbc:derby:testdb;create=true
MySQL Database Connection
URLs
MySQL Connector/J Database URL syntax:
• jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1]
[=propertyValue1][&propertyName2][=propertyValue2]...
• host:port is the host name and port number of the computer hosting
your database. If not specified, the default values of host and port
are 127.0.0.1 and 3306, respectively.
• database is the name of the database to connect to. If not specified,
a connection is made with no default database.
• failover is the name of a standby database (MySQL Connector/J
supports failover).
• propertyName=propertyValue represents an optional, ampersand-
separated list of properties. These attributes enable you to instruct
MySQL Connector/J to perform various tasks.
• Example:
– jdbc:mysql://localhost:3306/
Establishing Connection Example
Connection conn = null;
Properties connectionProps = new Properties();
connectionProps.put("user", this.userName);
connectionProps.put("password", this.password);

if (this.dbms.equals("mysql")) {
conn = DriverManager. getConnection("jdbc:" + this.dbms +
"://" + this.serverName + ":" + this.portNumber + "/",
connectionProps);
}
else if (this.dbms.equals("derby")) {
conn = DriverManager. getConnection("jdbc:" + this.dbms + ":" +
this.dbName + ";create=true", connectionProps);
}

System.out.println("Connected to database");

From JDBCTutorialUtilities :
http://download.oracle.com/javase/tutorial/jdbc/basics/gettingstarted.html
The JDBC Connection Class
• There are many methods a program can call on
its valid Connection object.
– The createStatement() method will create a Statement
object that can be used to assemble and run SQL
commands. The preparedStatement() creates an object
that is associated with a predefined SQL command (the
Statement object can be used for arbitrary statements –
and can be reused for other SQL commands)
– The getMetaData() method will return metadata associated
with the database, including descriptions of all of the tables
in the DB.
– The prepareCall() method is used to call stored
procedures in the SQL database.
Creating Statements
• A Statement is an interface that represents a SQL statement.
• You execute Statement objects, and they generate ResultSet objects, which is a table
of data representing a database result set.
• You need a Connection object to create a Statement object.

• There are three different kinds of statements:


– Statement: Used to implement simple SQL statements with no parameters.
– PreparedStatement: (Extends Statement.) Used for precompiling SQL statements that might
contain input parameters.
– CallableStatement: (Extends PreparedStatement.) Used to execute stored procedures that
may contain both input and output parameters.

• Example:
Connection con;
Statement stmt;

stmt=con.getStatement();
Executing Statements/Queries
• To execute a query, call an execute method from Statement such as
the following:
– executeQuery: Returns one ResultSet object.
– executeUpdate: Returns an integer representing the number of rows
affected by the SQL statement. Use this method if you are using
INSERT, DELETE, or UPDATE SQL statements.
• ResultSet: A ResultSet is like a database table; it has zero or more
rows (zero if no data elements match the query criteria) and each
row has one or more columns

• Example:
String query = "select COF_NAME, SUP_ID, PRICE, SALES,
TOTAL from COFFEES"; ”;
ResultSet rs = stmt.executeQuery(query);
Processing ResultSets
• You access the data in a ResultSet object through a cursor. This
cursor is a pointer that points to one row of data in the ResultSet
object.
• Initially, the cursor is positioned before the first row. You call various
methods defined in the ResultSet object to move the cursor.
• For example, the method ResultSet.next moves the cursor forward
by one row
• There are multiple methods of extracting data from the current
row in a ResultSet.
– The getString() method returns the value of a particular column in the
current row as a String.
– The getInt() method returns the value of a particular column in the current
row as an int.
–The getBoolean() method returns the value of a particular column in the
current row as an boolean.
–The getDouble() method returns the value of a particular column in the
current row as an double.
–The getObject() method returns the value of a particular column in the
current row as an Object.
ResultSet Example
String query = "select COF_NAME, SUP_ID, PRICE, SALES,
TOTAL from COFFEES"; ”;

stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String coffeeName = rs.getString("COF_NAME");
int supplierID = rs.getInt("SUP_ID");
float price = rs.getFloat("PRICE");
int sales = rs.getInt("SALES");
int total = rs.getInt("TOTAL");
System.out.println(coffeeName + "\t" + supplierID +
"\t" + price + "\t" + sales + "\t" +
total);
Populating Tables Example
stmt = con.createStatement();
stmt.executeUpdate("insert into COFFEES” +
"values('Colombian', 00101, 7.99, 0, 0)");
stmt.executeUpdate("insert into COFFEES“ +
“values('French_Roast', 00049, 8.99, 0, 0)");
Creating Tables Example
String createString = "create table " + dbName + ".COFFEES " +
"(COF_NAME varchar(32) NOT NULL, " +
"SUP_ID int NOT NULL, " +
"PRICE float NOT NULL, " +
"SALES integer NOT NULL, " +
"TOTAL integer NOT NULL, " +
"PRIMARY KEY (COF_NAME), " +
"FOREIGN KEY (SUP_ID) REFERENCES " + dbName +
".SUPPLIERS (SUP_ID))";

Statement stmt = con.createStatement();


stmt.executeUpdate(createString);
JDBC Statements - Types
• There are three types of statement objects in
JDBC programming:
– Statement - This allows the execution of arbitrary
statements on the database.
– PreparedStatement - This kind of statement allows
the program to execute the same SQL command
repeatedly, while allowing substitutions for particular
words or values (input parameters).
– CallableStatement - This kind of statement allows the
program to execute SQL stored procedures, with
substitutions for arguments. A stored procedure is a
function that is part of, and stored inside, a SQL
database
Prepared Statement Example
PreparedStatement updateSales = null;

String updateString = "update " + dbName + ".COFFEES " +


"set SALES = ? where COF_NAME = ?";

con.setAutoCommit(false);

updateSales = con.prepareStatement(updateString);

for (Map.Entry<String, Integer> e : salesForWeek.entrySet())


{ updateSales.setInt(1, e.getValue().intValue());
updateSales.setString(2, e.getKey());
updateSales.executeUpdate();
con.commit(); }
JDBC Data Types
• As SQL defines its own datatypes, it is important to
understand the mapping between SQL and Java
datatypes…
SQL Java SQL Java
---------------------------------- ---------------------------------------------
BIT boolean NUMERIC BigDecimal
BIGINT long REAL float
BINARY byte[] SMALLINT short
CHAR String TIME Time
DATE Date TIMESTAMP Timestamp
DOUBLE double TINYINT byte
FLOAT float VARBINARY byte[]
INTEGER int VARCHAR char[]

BLOB Blob REF Ref


CLOB Clob STRUCT Struct
Summary
• JDBC is a core Java technology that supports access to
relational databases and database servers.
• JDBC uses the standard Structured Query Language
(SQL) for all database interaction.
• In order to use JDBC with a particular database, you
must install a driver for the database server you are using
• Almost all JDBC functionality is accomplished through
the use of SQL statements
Data Access Patterns
• Some of the problems with data access from OO
programs:
1. Data source and OO program use different data
modelling concepts
2. Decoupling domain logic from database technology
Problems in Data Access (1)
– Problem: Data sources and OO programs use different
data modeling concepts:
– OO programs: class, object, attribute; relations: association, aggregation,
inheritance
– XML: tags, elements, attributes
– SQL: tables, rows, columns; relations: foreign key references
– Solution: mapping OO concepts to concepts specific for each
data source type
– Mapping patterns
– XML <-> OO
– SQL <-> OO
– Automatic mapping tools:
– XML data binders: ex: JAXB; see a list of more examples:
http://www.xmldatabinding.org/
– Object-Relational Mappers: ex: Java Persistence API, Hibernate, LINQ to SQL;
see a list of more examples:
http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software
Bibliography
• Lecture notes based on:
• Wolfgang Keller, Mapping Objects to Tables
– http://www.objectarchitects.de/ObjectArchitects/papers/Published/ZippedP
apers/mappings04
Mapping Object Oriented to
Relational Concepts
• The object-relational impedance mismatch: conceptual
and technical difficulties that are often encountered when a
relational database management system is being used by a
program written in an object-oriented programming language
or style
• Object-oriented model:
– Aggregation
– Inheritance and polymorphism
– Associations between classes
• Relational model:
– Tables
– Foreign key references to another table
Mapping Object Oriented to
Relational Concepts
• General rules:
– Class <-> Table
– Object<->Row
– Attribute <->Column
– Works well only for simple classes with scalar attributes only
• Problems:
– Aggregations: one domain object contains other domain objects
– Associations: objects have references to other objects (m:n)
– Inheritance: How do you map an inheritance hierarchy of classes to
database tables?
Solutions for Mapping Aggregation (1):
Single Table Aggregation

Solution:
Put the aggregated object's attributes into the same table as the aggregating object’s.

Figure from : Wolfgang Keller, Mapping Objects to Tables


Single Table Aggregation Example & Consequences

Performance: +, only one table needs to be accessed for queries


Flexibility: -, if the aggregated object type is aggregated in more than one object
type, the design results in poor maintainability
Figure from : Wolfgang Keller, Mapping Objects to Tables
Solutions for Mapping Aggregation (2):
Foreign Key Aggregation

Solution:
Use a separate table for the aggregated type. Insert an Synthetic Object
Identity into the table and use this object identity in the table of the aggregating
object to make a foreign key link to the aggregated object.
Foreign Key Aggregation Example & Consequences

Performance: -, needs a join operation or at least two database accesses


Maintenance: +, Factoring out objects into tables of their own makes them
easier to maintain and hence makes the mapping more flexible.
Consistency of the database: !, Aggregated objects are not automatically
deleted on deletion of the aggregating objects.
Solution for Mapping Associations:
Association Table

Solution: Create a separate table containing the Object Identifiers (or Foreign Keys) of the
two object types participating in the association. Map the rest of the two object types to
tables using any other suitable mapping patterns presented in this paper.
Association Table Example

n:m association between Employees and Departments


An Employee may work with m Departments
A Department comprises n Employees
Solutions for Mapping Inheritance (1):
One Class – One Table

Solution:
Map the attributes of each class to a separate table. Insert a Synthetic OID into
each table to link derived classes rows with their parent table's corresponding
rows.
One Class – One Table Example & Consequences

Performance: -, reading a SalariedEmployee instance in our example costs 3


(=depth of inheritance tree) database read operations
Solutions for Mapping Inheritance (2):
One Inheritance Tree – One Table

Use the union of all attributes of all objects in the inheritance hierarchy as the
columns of a single database table. Use Null values to fill the unused fields in
each record.
One Inheritance Tree – One Table Example & Consequences

Performance: +, needs one database operation to read or write an object.


Space consumption: -, optimal space consumption.
Balancing database load across tables: -
Solutions for Mapping Inheritance (3):
One Inheritance Path – One Table

Solution: Map the attributes of each concrete class to a separate table. To a


classes’ table add the attributes of all classes the class inherits from.
One Inheritance Path – One Table Example & Consequences

Performance: +, needs one database operation to read or write an object.


Space consumption: +, optimal space consumption.
Maintenance cost: +/-: inserting a new subclass means updating all polymorphic
search queries. The structure of the tables remains untouched. Adding or
deleting attributes of a superclass results in changes to the tables of all derived
classes.
Data Access Patterns
• Some of the problems with data access from OO
programs:
1. Data source and OO program use different data
modelling concepts
2. Decoupling domain logic from database technology
Problems in Data Access (2)
• Access to data varies depending on the source of the data.
• type of storage (relational databases, object-oriented databases, flat files,
etc)
• particular vendor implementation for a type.
• When business components need to access a data source, they can
use the appropriate API to achieve connectivity and manipulate the
data source.
• Problem: coupling between the components and the data source
implementation: appears when including the connectivity and data
access code provided by different API’s within the business
components (domain objects)
• Such code dependencies in components make it difficult to migrate the
application from one type of data source to another
• Components need to be transparent to the actual persistent store or
data source implementation to provide easy migration to different
vendor products, different storage types, and different data source
types.
Bibliography
– Sun: Core J2EE Pattern Catalog
• http://www.oracle.com/technetwork/java/dataaccessobject
-138824.html

– For further reading, only if interested:


• Clifton Nock, Data Access Patterns: Database Interactions in
Object Oriented Applications, Addison Wesley, 2003
• Martin Fowler, Patterns of Enterprise Application Architecture
http://martinfowler.com/eaaCatalog/index.html
The Data Access Object
Pattern
• Intent: Abstract and Encapsulate all access to the data source

Sun Developer Network - Core J2EE Patterns


http://www.oracle.com/technetwork/java/dataaccessobject-138824.html
DAO – Participants and responsibilities

• BusinessObject: represents the data client. It is the object that


requires access to the data source to obtain and store data.
• DataAccessObject: the primary object of this pattern. It abstracts the
underlying data access implementation for the BusinessObject to
enable transparent access to the data source. The BusinessObject also
delegates data load and store operations to the DataAccessObject.
• DataSource: represents a data source implementation. A data source
could be a database such as an RDBMS, OODBMS, XML repository,
flat file system, etc.
• Transfer Object: used as a data carrier. The DataAccessObject may
use a Transfer Object to return data to the client. The
DataAccessObject may also receive the data from the client in a
Transfer Object to update the data in the data source.
Where to get DAO’s from ?

• Strategies to get DAO’s:


– Automatic DAO Code Generation Strategy
– Factory for Data Access Objects Strategy
Automatic DAO Code Generation Strategy

• Since each BusinessObject corresponds to a specific DAO, it is


possible to establish relationships between the BusinessObject, DAO,
and underlying implementations (such as the tables in an RDBMS).
• Once the relationships are established, it is possible to write a simple
application-specific code-generation utility that generates the code for
all DAOs required by the application.
• The metadata to generate the DAO:
– can come from a developer-defined descriptor file.
– or, alternatively, the code generator can automatically
introspect the database and provide the necessary DAOs to
access the database.
• If the requirements for DAOs are sufficiently complex, consider using
third-party tools that provide object-to-relational mapping for
RDBMS databases.
– Examples: Java Persistence API (JPA): Hibernate
Factory for Data Access Objects Strategy

• The DAO pattern can be made highly flexible by adopting the


Abstract Factory [GoF] and the Factory Method [GoF] patterns
• Use Factory Method: When the underlying storage is not
subject to change from one implementation to another, use the
Factory Method pattern to produce a number of DAOs needed
by the application.
• Use Abstract Factory: When the underlying storage is subject
to change from one implementation to another, this strategy may
be implemented using the Abstract Factory pattern. In this case,
this strategy provides an abstract DAO factory object (Abstract
Factory) that can construct various types of concrete DAO
factories, each factory supporting a different type of persistent
storage implementation. Once you obtain the concrete DAO
factory for a specific implementation, you use it to produce
DAOs supported and implemented in that implementation.
DAO with Factory Method
DAO with Abstract Factory
Consequences

• Enables Transparency

• Enables Easier Migration


.
• Reduces Code Complexity in Business Objects:

• Adds Extra Layer

• Needs Class Hierarchy Design


Example
Example- Using Factory Method
Example- Using Abstract Factory
Abstract class DAO Factory
// Abstract class DAO Factory
public abstract class DAOFactory {

// List of DAO types supported by the factory


public static final int CLOUDSCAPE = 1;
public static final int ORACLE = 2;
public static final int SYBASE = 3;
...
// There will be a method for each DAO that can be created.
//The concrete factories will have to implement these methods.
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO();
...
public static DAOFactory getDAOFactory( int whichFactory) {
switch (whichFactory) {
case CLOUDSCAPE:
return new CloudscapeDAOFactory();
case ORACLE :
return new OracleDAOFactory();
...
default :
return null;
}
}
}
Cloudscape concrete DAO Factory implementation
import java.sql.*;

public class CloudscapeDAOFactory extends DAOFactory {


public static final String DRIVER=
"COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL=
"jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";

// method to create Cloudscape connections


public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
}
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
Interface that all CustomerDAOs must support

// Interface that all CustomerDAOs must support


public interface CustomerDAO {
public int insertCustomer(...);
public boolean deleteCustomer(...);
public Customer findCustomer(...);
public boolean updateCustomer(...);
public RowSet selectCustomersRS(...);
public Collection selectCustomersTO(...);
...
}
CloudscapeCustomerDAO implementation

// CloudscapeCustomerDAO implementation of the CustomerDAO interface.


// This class can contain all Cloudscape specific code and SQL statements.

import java.sql.*;

public class CloudscapeCustomerDAO implements CustomerDAO {


public CloudscapeCustomerDAO() {
// initialization
}

// The following methods can use CloudscapeDAOFactory.createConnection()


// to get a connection as required

public int insertCustomer(...) {


// Implement insert customer here.
// Return newly created customer number or a -1 on error
}
public boolean deleteCustomer(...) {
// Implement delete customer here
// Return true on success, false on failure
}
public Customer findCustomer(...) {
// Implement find a customer here using supplied argument values as search criteria
// Return a Transfer Object if found, return null on error or if not found
}
Customer Transfer Object

public class Customer implements java.io.Serializable {


// member variables
int CustomerNumber;
String name;
String streetAddress;
String city;
...

// getter and setter methods...


...
}
Client Code
// Create a DAO
CustomerDAO custDAO = cloudscapeFactory.getCustomerDAO();

// create a new customer


int newCustNo = custDAO.insertCustomer(...);

// Find a customer object. Get the Transfer Object.


Customer cust = custDAO.findCustomer(...);

// modify the values in the Transfer Object.


cust.setAddress(...);
cust.setEmail(...);
// update the customer object using the DAO
custDAO.updateCustomer(cust);

// delete a customer object


custDAO.deleteCustomer(...);
// select all customers in the same city
Customer criteria=new Customer();
criteria.setCity("New York");
Collection customersList = custDAO.selectCustomersTO(criteria);
// returns customersList - collection of Customer
// Transfer Objects. iterate through this collection to
// get values.

...
Related Pattern:
Data Mapper [Martin Fowler]

The Data Mapper is a layer of software that separates the in-memory objects
from the database. Its responsibility is to transfer data between the two and
also to isolate them from each other.

http://martinfowler.com/eaaCatalog/dataMapper.html
DAO and other patterns
• DAO is a general and complex pattern

• Martin Fowler, Patterns of Enterprise Application


Architecture
http://martinfowler.com/eaaCatalog/index.html
– Table Data Gateway
– Row Data Gateway
– Active Record/Active DomainObject
Related Pattern:
Table Data Gateway [Martin Fowler]

A Table Data Gateway holds all the SQL for accessing a single table or view:
selects, inserts, updates, and deletes. Other code calls its methods for all
interaction with the database. A Table Data Gateway has one instance per
table.
Simpler Pattern:
Row Data Gateway

Row Data Gateway gives you objects that look exactly like the record in your
record structure but can be accessed with the regular mechanisms of your
programming language. All details of data source access are hidden behind this
interface. A Row Data Gateway has one instance per row returned by a query.
Simplest Pattern:
Active Record/Active DomainObject

An object that wraps a row in a database table, encapsulates the database


access, and adds domain logic on that data.

Characteristics:
DomainObjects are dependent on the persistence mechanism
Use only if the DomainModel is simple enough and persistence mechanism
does not change

S-ar putea să vă placă și