MokaByte 101 - 9mbre 2005
 
MokaByte 101 - 9mbre 2005 Prima pagina Cerca Home Page

 

 

 

Integration Patterns
II parte

Nello scorso articolo (vedere [MOKA_INT_PATT_1]) si è visto come utilizzare in modo organico alcuni pattern d'integrazione (vedere [EAI_PATTERNS] e [EAI_PATT_WS]) al fine di ottimizzare il design dell'applicazione e-commerce d'esempio riguardante la vendita di articoli sportivi on-line. Analizzata la parte relativa alla richiesta di acquisto vedremo, in questo articolo, come progettare la parte relativa alla gestione degli ordini di acquisto avvalendoci ancora di alcuni importanti pattern d'integrazione.

Gestione dell'ordine di acquisto

Una volta ricevuti i messaggi relativi agli ordini di acquisto bisogna processarli per verificare:

  • la disponibilità dei prodotti richiesti nell'ordine di acquisto
  • l'opportuna disponibilità economica dell'acquirente

Di fatto le attività di verifica della disponibilità dei prodotti e della disponibilità economica del richiedente, piuttosto che farle in sequenza, possono essere effettuate in contemporanea e quindi in modo più efficiente. Per "parallelizzare" le due operazioni sfruttiamo le caratteristiche del canale Publish Subscribe in modo tale da inviare le medesime informazioni a più destinatari. Il pattern Publish-Subscribe Channel prevede l'invio del medesimo messaggio a più destinatari.



Figura 1: Publish-Subscribe Channel


Nel nostro esempio questo si traduce nell'inviare il messaggio dell'ordine di acquisto sia alla componente applicativa che deve verificare l'effettiva possibilità di acquisto da parte del client, sia alla componente che deve invece verificare l'effettiva disponibilità degli elementi da comprare.
L'ordine può contenere più elementi (item) da acquistare. Ogni singolo item deve quindi essere controllato per verificarne l'effettiva disponibilità nel magazzino. Si può quindi procedere con un unico controllo dell'ordeine o a parallelizzare ulteriormente l'operazione dividendo (split) il messaggio contenente gli N item in N messaggi diversi per poi controllarli in contemporanea. Ovviamente la seconda soluzione è più conveniente da un punto di vista di performance ma richiede di dividere l'ordine in N sotto-ordini, cioè un ordine per ogni item. Inoltre bisogna essere sicuri che una volta diviso il messaggio (Pattern Splitter) si possa essere in grado poi di aggregarlo (Pattern Aggregator) secondo una opportuna logica di correlazione.
Supponendo che l'ordine abbia come identificativo un customer id (l'identificativo del client acquirente) bisogna provvedere ad inserire nel messaggio un nuovo identificativo order id (l'id dell'ordine di acquisto) al fine di potere correlare i singoli item all'ordine dell'acquirente. Questo ci permetterà di effettuare lo split del messaggio e la relativa successiva aggregazione.
Aggiungiamo quindi delle informazioni al messaggio originario provvedendo ad un arricchimento dello stesso al fine di potere permettere una gestione parallela del check di ogni item.
Il pattern Content Enricher prevede di arricchire le informazioni contenute in un messaggio con dati aggiuntivi al fine di inserire nel messaggio le informazioni mancanti per essere correttamente processato dal destinatario.


Figura 2: Content Enricher


A questo punto è possibile suddividere l'ordine in tanti sotto-ordini quanti sono gli elementi contenuti nell'ordine.
Il pattern Splitter divide un messaggio composito contenente diversi elementi in una serie di messaggi individuali, ognuno contenente I dati relativi al proprio elemento.


Figura 3:
Splitter


Suddiviso l'ordine in tanti sotto-ordini correlate tra loro mediante un order-id, bisogna provvedere ad inoltrare il messaggio all'opportuno controllore in base alla tipologia dell'item.
Per fare questo introduciamo il pattern Content-based Router. Il pattern Content-based Router permette di recapitare il messaggio al corretto destinatario attuando l'opportuna logica di routing analizzando il contenuto del messaggio.
L'algoritmo di routing può avvenire in base all'esistenza o meno di specifici dati o in base a determinati valori di taluni campi o addirittura in base al contenuto del payload del messaggio.


Figura 4:
Content-based Router


Nel nostro esempio, il CBR dovrà inoltrare, in base alla tipologia dell'elemento da acquistare (maglietta di Football Americano o di Basket), il messaggio all'opportuno controllore (NFL o NBA).


Figura 5: Il Content-based Router dell'esempio proposto


Il controllore dovrà verificarne l'effettiva disponibilità dell'articolo (item) richiesto in magazzino.
Una volta analizzati tutti gli item dell'ordine, bisogna riaggregare le informazioni per ricavare la situazione globale dell'ordine.
Per fare questo si usa una Aggregatore. Il pattern Aggregator combina i messaggi relativi a operazioni individuali in un unico messaggio composito. Di fatto il messaggio finale è un "distillato" di N messaggi individuali. L'aggregatore è un componente Stateful che "colleziona" i vari elementi fino a che la composizione del messaggio finale non è completa per poi inviarlo all'opportuno destinatario che si aspetta di ricevere un unico messaggio composto.


Figura 6: Aggregator


Da notare come il messaggio che il Content-Based Router invia al sistema di controllo inventario non è un Document Message ma bensì un Command Message. Infatti in questo caso si incapsula nel messaggio la richiesta di attuare l'azione di controllo disponibilità dell'item.
Il pattern Command Message prevede di incapsulare in un messaggio la descrizione di un comando da impartire ad un'altra applicazione come ad esempio la richiesta di invocazione di una procedura / servizio remoto.


Figura 7: Command Message


Siamo arrivati ormai alla conclusione dell'esempio.
Abbiamo parallelizzato i controlli di ogni singolo elemento (item) dell'ordine ed il controllo della disponibilità economica dell'utente.


Figura 8: Controlli simultanei


Abbiamo quindi capito se il client ha le possibilità economiche per l'acquisto di tutti gli item dell'ordine e se gli item richiesti sono disponibili.
Dobbiamo quindi procedere ad aggregare un'ultima volta queste informazioni in un unico messaggio (ancora Pattern Aggregator) e valutare se è possibile inoltrarlo o meno (ancora Pattern Content-based Router).
La combinazione del pattern Splitter, Router e Aggregator viene anche chiamato Composed Message Processor Pattern.
Il pattern Composed Message Processor Pattern effettua lo split di un messaggio, il routing dei sotto messaggi ottenuti alle appropriate destinazioni e la relativa aggregazione finale in un unico messaggio. Ecco la situazione finale relativa al processo dell'ordine descritta fino ad ora.


Figura 9: Process Order


Da questo esempio si è visto come applicare ben dodici pattern. Questo a dimostrare di come sia importante conoscere i pattern sia da un punto di vista di applicabilità che da un punto di vista architetturale.
Come si vede la soluzione presenta una certa complessità. Utilizzando i sistemi di Messaging risulta particolarmente difficile ottenere una "big-picture" dell'architettura data la natura prettamente asincrona dei sistemi di messaging. E' quindi importante tracciare a runtime lo stato di ogni ordine all'interno del sistema per nn perdere di vista il flusso dei messaggi e lo stato complessivo del sistema.
Per ottenere questo è utile applicare il pattern Message Store al fine di permettere un tracciamento dei messaggi nelle varie destinazioni. Il pattern Message Store permette di tracciare lo stato del flusso dei messaggi all'interno del sistema di messaging.
In una situazione in cui si utilizza il canale di tipo Publish Subscribe questo si ottiene facilmente aggiungendo un subscriber interessato al messaggio senza "intralciare" il normale flusso di dati.



Figura 10: Message store in un canale Pub/Sub


Nel caso invece di canali P2P (code) bisogna aggiungere una nuova destinazione su cui duplicare il messaggio da inviare.
Per fare questo si può utilizzare il pattern Wire Tap.
Il pattern Wire Tap prevede l'introduzione di un elemento che viene interposto tra il sender del messaggio ed il receiver. Ricevuto il messaggio dal sender, lo inoltra (senza modificarne il contenuto) oltre che al receiver (primary channel) anche al componente di message store (secondary channel).
Questo permette il monitoring e l'ispezione dei messaggi anche per canali P2P.


Figura 11: Message store in un canale P2P


Altro pattern utile è sicuramente il Message History.
Il pattern Message History permette la storicizzazione dei messaggi transitati nel sistema di messaging. Questo permette di mantenere la lista dei componenti attraverso cui un messaggio è transitato. Ogni componente che processa il messaggio aggiunge un'entry alla lista di history.
Il Message History deve essere incluso nella parte header del messaggio perché contiene informazioni prettamente di controllo e non nel payload che deve contenere dati di tipo applicativo.


Figura 12: Message History


Vediamo ora di introdurre un ultimo pattern molto importante per quanto riguarda il test.
Il pattern Test Message permette di verificare lo "stato di salute" del sistema di messaging. Inserendo degli opportuni test-generator e dei test-verfier lungo il sistema è possibile verificare lo stato del corretto funzionamento del sistema e rilevare eventuali malfunzionamenti.


Figura 13: Test Message


Conclusioni
Dal semplice esempio proposto si è visto come, quando e dove applicare ben quindici pattern!
Questo a dimostrare di come sia importante conoscere i pattern sia da un punto di vista di "applicabilità" che da un punto di vista architetturale.


Bibliografia e riferimenti
[MOKA_INT_PATT_1] S.Rossini: Integration Patterns (II),Mokabyte N.100-Ottobre 2005
[EAI_PATTERNS] Gregor Hohpe, Bobby Woolf: Enterprise Integration Patterns : Designing, Building, and Deploying Messaging Solutions - Addison-Wesley, 2004
[EAI_PATT_WS] Gregor Hohpe Enterprise Integration Pattern web site: http://www.eaipatterns.com/index.html
[CJ2EE] Alur,Crupi,Malks: Core J2EE Patterns - Best Practices and Design Strategies
[FMEDP] Floyd Marinescu: EJB Design Patterns - Advanced Patterns, Processes and idioms
[SUNJ2EE] Sun Java Center J2EE Patterns:
http://developer.java.sun.com/developer/restricted/patterns/J2EEPatternsAtAGlance.html
[GOF] Gamma,Helm,Johnson,Vlissides: Design Patterns-Elements of Reusable Object-Oriented Software