Documente Academic
Documente Profesional
Documente Cultură
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)
• 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
[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
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
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
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
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.
[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)
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
Event Service
op
op
Obj1 Obj2 Obj1 Obj2
Publisher
Publisher Subscriber
Subscriber
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
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
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
Publisher Subscriber
Notifier
Publish Event
Receive Event
Data Transfer
Pull: Procurer
Publisher Subscriber
Procurer
Publish Event
Receive Event
Data Transfer
Hybrid Push/Pull: Queue
Publisher Subscriber
Queue
Publish Event
Receive Event
Data Transfer
Hybrid Pull/Push: Intelligent Agent
Publisher Subscriber
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
Publisher
Publisher Subscriber
Subscriber
Exemplu problema:
Network Management System
Managed Objects Management System
}
public void inform(Event event) {
// Assumes that this subscriber has only subscribed to FaultEvent
FaultEvent faultEvent = (FaultEvent) event;
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 ?
Hub Console
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
EventChannel Console
Hub
P&F BB Events
Pot diversifica productia ? Doar la startup Da, la runtime Da, la runtime
Bibliography:
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:
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<?> 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");
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() ;
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);
}
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);
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");
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:
[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
[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
– 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
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
• Bibliography:
– Joseph Yoder, Ralph Johnson: The Adaptive Object-Model Architectural Style,
WICSA 2002,
http://www.adaptiveobjectmodel.com/WICSA3/ArchitectureOfAOMsWICSA3.pdf
Representing Business Rules
• 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)
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.
[POSA]-Fig/P.310
Structura Forwarder-Receiver
[POSA]-Fig/P.311
Scenariu Forwarder-Receiver
[POSA]-Fig/P.312
Exemplu implementare
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
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);
}
[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
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
InfoServer
Client1
Sunt InfoServer la addr X,
info Meteo si Rutier
Client2 Dispatcher
Exemplu Client-Server:
[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.
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
(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
uses implements
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
Fisier StockMarketImpl.java
RMI - Pas 3.V1: Generare Traditionala Proxy-uri
RMI Stub/Skeleton
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)
• 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 );
• 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");
• 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
>rmic StockMarketImpl
• 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
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
• Deployment Client:
• StockMarket.class, StockMarketClient.class
– Rulare aplicatie
RMI - Pas 6 – Varianta 3: Rulare aplicatie
IDL Skeleton
Dynamic IDL Stub (ServerSide
Interface Invocation (ClientSide ORB Object Implem
Proxy) Adapter Repository
Repository Interface Proxy) Interface
• 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
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
TransparentProxy
RealProxy
• 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
Fisier StockMarketServer.cs
.NET – Pas 4. Implementare Client
Fisier StockMarketClient.cs
.NET - Pas 5. Rulare aplicatie
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
Fisier StockMarket.java
ToyORB - Pas 2. Implementare Obiect
• Se implementeaza clasa
StockMarketImpl, ca o clasa public class StockMarketImpl implements
normala StockMarket {
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");
Fisier StockMarketClient.java
ToyORB - Pas 3. Versiunea 0:
Scriere manuala proxy-uri
StockMarketClientSideProxy.java
StockMarketSErverSideProxy.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
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
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
ComplexStockMarket objRef=(ComplexStockMarket)
ToyORB.getObjectReference(“NASDAQ”);
float price=objRef.get_price(“ABC SRL”);
String junk=objRef.whois_lowest_today();
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
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
StockMarketServerProxy
Replyer
NamingService Address
127.0.0.1, 1111
Replyer
NamingService
StockMarketServerProxy
Replyer
ToyORB.getObjectRef
Requester
NamingService Address
127.0.0.1, 1111
Replyer
NamingService
StockMarketServerProxy
StockMarketClientProxy
Replyer
Requester
NamingService Address
127.0.0.1, 1111
Replyer
NamingService
• 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)
IDL Skeleton
Dynamic IDL Stub (ServerSide
Interface Invocation (ClientSide ORB Object Implem
Proxy) Adapter Repository
Repository Interface Proxy) Interface
• 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
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
StockMarketClient
ToyORB ToyORB StockMarketImpl
library impl library impl
in LANG1 in LANG2
• 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
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
dots.xml
http://download.oracle.com/javase/tutorial/jaxp/intro/simple.html
Citire XML cu SAX
Exemplu: XMLDotReader - citeste date din fisierul dots.xml
}
Construirea parserului SAX
// create an instance of the ContentHandler
DefaultHandler handler= new XMLDotReader();
}
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 {
}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
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
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();
•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.*;
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 ObjectFactory() {
}
}
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();
Database: “Company”
Table: “Employees” Table: “Cars”
Exemplu
Table Employees
Table Cars
DBMS Engine
Database files
JDBC:
Java <-> Relational Databases
DBMS
Java Application
DBMS Engine
JDBC API
JDBC Driver
Database files
JDBC
(Java Database Connectivity) (?)
JDBC
Bibliografie:
Laborator: Java DB = Sun’s supported distribution of the open source Apache Derby
database
http://developers.sun.com/javadb/
• Exemple:
• Exemple:
• Exemplu:
• Exemple
• 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
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 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 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
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.
• 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))";
con.setAutoCommit(false);
updateSales = con.prepareStatement(updateString);
Solution:
Put the aggregated object's attributes into the same table as the aggregating object’s.
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
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
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
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
• Enables Transparency
import java.sql.*;
...
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
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
Characteristics:
DomainObjects are dependent on the persistence mechanism
Use only if the DomainModel is simple enough and persistence mechanism
does not change