Da un punto di vista applicativo l‘utilizzo dei pattern nell‘ambito dell‘integrazione si traduce nello sviluppare opportune classi (DAO, Proxy, Wrapper, Adapter, Delegate, …) con lo scopo di disaccoppiare (decoupling) la logica di integrazione dalla logica di business e di Presentation.
Introduzione
Effettuare l‘integrazione in modo corretto significa portare sistemi eterogenei a comunicare tra loro incapsulando opportunamente la logica applicativa che serve per normare e gestire la comunicazione tra di esse.
Oltre a preoccuparsi di connettersi e normalizzare la comunicazione con le risorse EIS utilizzando le opportune tecnologie (come JDBC, JCA, JMS, Web Services, … ), da un punto di vista applicativo bisogna utilizzare i pattern opportuni.
Un Pattern rappresenta una soluzione provata (e documentata) ad un problema ricorrente. Un pattern descrive un problema, il suo contesto, la relativa soluzione e le conseguenze (vantaggi e trade off) che possono derivare dall‘adozione del pattern stesso.
In questo articolo ci occuperemo dei pattern d‘integrazione.
I pattern d‘integrazione
Da un punto di vista applicativo l‘utilizzo dei pattern nell‘ambito dell‘integrazione si traduce nello sviluppare opportune classi (DAO, Proxy, Wrapper, Adapter, Delegate, …) con lo scopo di disaccoppiare (decoupling) la logica di integrazione dalla logica di business e di Presentation.
Ad esempio l‘intento del pattern DAO (Data Access Object) è di disaccoppiare la logica di business dalla logica di accesso ai dati.
Questo si ottiene spostando la logica di accesso ai dati dai componenti di business ad una classe DAO, rendendo i componenti di business indipendenti dalla natura del dispositivo di persistenza e dalle relative problematiche di accesso al mezzo di persistenza.
Ad esempio, supponendo di dover accedere ad una tabella Account di un DBMS, è opportuno incapsulare l‘utilizzo di SQL e JDBC all‘interno di un‘opportuna classe DAO.
public class AccountDaoImpl {public Account readAccount(int pk) throws DaoException {try {. . . . . .Connection con = dataSource.getConnection();PreparedStatement pstmt = con.prepareStatement("SELECT ..... FROM ..... WHERE ...... ");pstmt.setString(1, ""+pk);ResultSet rslt = pstmt.executeQuery();if (rslt.next()) {String name = rslt.getString(1);. . . . . .return account;}. . . . .
L‘accesso alla tabella del DBMS mediante JDBC viene reso trasparente allo sviluppatore delle classi di business che si limita a chiamare il metodo readAccount() dell‘oggetto DAO.
Ad esempio, da un EJB sarà possibile ottenere i dati d‘interesse istanziando il DAO e invocando il metodo readAccount():
public class CommandEJB implements SessionBean {public Account getAccount(String accountId){AccountDaoJdbcImpl dao = new AccountImpl();return dao.readAccount(accountId);}
Utilizzando in modo congiunto anche il pattern factory è possibile disaccoppiare la logica di business dalla conoscenza della classe concreta del DAO.
AccountDao dao = (AccounDao)FactoryDao.getInstance().getAccountDAO();
Le architetture tradizionali EAI basano il loro comportamento su un sistema di messaging.
Con il termine Messaging si definisce un meccanismo che permette la comunicazione asincrona tra client (detti peer-element) mediante uno scambio di messaggi caratterizzato da uno scarso grado di accoppiamento.
Nel libro “Enterprise Integration Patterns : Designing, Building, and Deploying Messaging Solutions” di Gregor Hohpe e Bobby Woolf sono presentati più di sessanta pattern message-oriented utili per l‘integrazione.
Ovviamente la conoscenza approfondita dei pattern ed il giusto contesto in cui utilizzarli riguarda da vicino gli Application Architects e gli sviluppatori che realizzano integrazioni P2P utilizzando piattaforme Enterprise come Java 2 Enterprise Edition (J2EE) o Microsoft .NET.
Tuttavia la loro conoscenza è utile anche per gli Integration Architect che progettano soluzioni d‘integrazione utilizzando la suite d‘integrazione (es: IBM Websphere Business Integration, Sonic Enterprise Service Bus, Microsoft BizTalk Server, SeeBeyond, Vitria, …) al fine di capire i concetti che stanno alla base delle funzionalità (già “pronte all‘uso”) fornite dal Middleware d‘integrazione.
Le suite di integrazione basano il loro funzionamento su un sistema di Messaging, un Message Oriented Middleware (MOM) infrastrutturale che di fatto costituisce la dorsale (backbone) di messaging sulla quale l‘Integration Middleware basa il suo funzionamento.
Nei sistemi di Messaging i client non interagiscono direttamente tra di loro, nè il produttore nè il ricevitore devono essere a conoscenza l‘uno dell‘altro, l‘unica cosa che entrambi devono sapere è il formato del messaggio e la “casella di posta” (destination) da usare.
Sarà il messaging server che farà le veci del “postino”: riceverà i messaggi dai produttori e li recapiterà ai relativi destinatari (consumatori).
Tipicamente i MOM prevedono due diversi modelli di messaging con i quali è possibile scambiarsi i messaggi: Point to point e Publish and Subcribe.
Il modello di Messaging Point-To-Point (PTP) è caratterizzato dal fatto che piu‘ produttori e piu‘ consumatori possono condividere la stessa destinazione (Queue) e ogni messaggio ha un solo consumatore; questo permette di fatto una comunicazione uno a uno (ad es: prenotazioni, vendite di biglietti, online trading, …)
Il modello Publish/Subscribe(Pub/Sub) permette una comunicazione uno a molti, dal momento che ogni messaggio inserito nella destinazione (topic) può essere inoltrato a tutti i destinatari che si sono dichiarati (subscription) interessati (ad es: quotazioni, aggiornamento cataloghi, data replication, chat, …).
Integrando applicazioni eterogenee mediante un message bus condiviso si possono incontrare disparate situazioni e scenari in cui oltre allo scambio di messaggi si necessita di conversioni, trasformazioni, routine, split e aggregazione di messaggi, ecc …
I pattern riguardano i sistemi basati sul messaging si possono principalmente raccogliere in sei principali categorie:
- Channel Patterns: descrivono le caratteristiche salienti dei sistemi di messaging
- Message Construction Patterns: pattern relativi alla costruzione dei messaggi
- Routing Patterns: spiegano i meccanismi e gli algoritmi per inoltrare/smistare opportunamente i messaggi alle corrette destinazioni
- Transformation Patterns: descrivono i meccanismi di trasformazione (sintattica e/o semantica) del contenuto del messaggio
- Endpoint Patterns: descrivono le varie viste dei possibili client del sistema di messaging e il modo di produrre e/o consumare messaggi.
- System Management Patterns: descrivono i pattern per monitorare il percorso dei messaggi all‘interno del sistema di messaging.
I pattern abbracciano quindi le principali tematiche che si “incontrano” per integrare sistemi eterogenei tra di loro utilizzando un sistema di messaging come fulcro dell‘integrazione.
Vediamo di spiegare brevemente il funzionamento dei principali pattern attraverso un esempio.
Immaginiamo di avere il seguente tradizionale scenario di e-commerce.
Esempio di utilizzo dei pattern d‘integrazione
Supponiamo di avere delle applicazioni già sviluppate che rappresentino i diversi canali attraverso i quali è possibile effettuare ordini di acquisto di prodotti (ad esempio di articoli sportivi come le magliette sportive di Football Americano e di Basket)
Supponiamo che i clienti possono acquistare tali prodotti via Web, via Call Center o via cellulare.
L‘applicazione client (l‘acquirente) dovrà specificare nell‘ordine la lista dei prodotti che è interessato a comprare, i suoi dati anagrafici e le credenziali della Carta di Credito con cui effettuare l‘acquisto.
Il venditore dovrà verificare la disponibilità dei prodotti richiesti, la validità delle credenziali e la disponibilità economica della carta di credito.
Vediamo un possibile design dell‘architettura per quanto riguarda la gestione dell‘ordine di acquisto.
Acquisizione dell‘ordine di acquisto
Vediamo come progettare la gestione dell‘ordine di acquisto proveniente dalle diverse applicazioni client possibili.
Come già detto, un client può effettuare un ordine attraverso differenti canali. Ogni canale ha il suo formato di dati e la sua specifica tecnologia di comunicazione. Ad esempio il canale Web potrebbe essere un‘applicazione J2EE, il canale Call Center un‘applicazione packaged e la gestione degli ordini via WAP potrebbe essere un‘applicazione .NET.
Utilizzando un sistema di messagging come Integration Middleware, il primo problema che dobbiamo risolvere è la connessione di ogni differente client al canale di messaging.
Bisogna quindi introdurre un Channel Adapter che consenta di adattare un canale non message-based ad un canale message-based.
Il pattern Channel Adapter permette di connettere un‘applicazione non basata su messaggi ad un sistema di Messaging.
Ogni sistema client avrà il proprio formato di dati. Per questo bisogna provvedere a convertire i differenti formati dei dati in un unico formato comune mediante dei Message Translators.
Il pattern Message Translator prevede un filtro di messaging tra due sistemi che utilizzano formati diversi di dato con lo scopo di trasformare i messaggi da un formato di dati ad un altro.
Di fatto il Message Translator è la versione “a messaggi” del pattern Adapter descritto nel libro “Design Patterns. Elements of Reusable Object-Oriented Software” di Gamma, Helm, Johnson e Vlissides.
Il formato dei dati risultante dalla trasformazione del messaggio “privato” del client, prende il nome di Canonical Data Model. Il Canonical Data Model definisce un formato indipendente da una specifica applicazione e/o tecnologia e/o protocollo. In questo modo il sistema di messaging può trattare in un modo omogeneo e univoco i diversi messaggi provenienti da applicazioni eterogenee.
Il pattern Canonical Data Model prevede l‘utilizzo di un formato di dati comune e condiviso.
Tale formato, detto canonico, è indipendente da qualsiasi tecnologia.
Il pattern permette di minimizzare le dipendenze tra i vari sistemi eterogenei che usano formati di dati diversi prevedendo un livello di “indirezione” che disaccoppi i formati dati eterogenei da un formato dati canonico e indipendente da una specifica applicazione.
Da notare come in questo modo qualsiasi modifica del formato dei messaggi da parte di uno dei client abbia ripercussioni solo sullo specifico Channel Adapter e sul relativo Message Translator.
Ogni Channel Adapter è connesso al Message Translator mediante una connessione punto-punto (Point-to-Point) perché si vuole che i messaggi siano consumati una sola volta da uno specifico destinatario.
Il pattern Poin-to-Point Channel prevede l‘utilizzo di una destinazione di tipo coda (queue) che permette che i dati siano ricevuti solo da uno specifico destinatario.
Tutti i Message Translator inviano i messaggi (trasformati nel formato canonico di dati) alla medesima destinazione per essere processati.
Tale canale viene specificato come Datatype Channel perché veicola messaggi di tipo omogeneo (nel nostro esempio sono gli ordini di acquisto). Questo fa sì che colui che riceve i messaggi sia a conoscenza della tipologia del messaggio da processare.
Il pattern Datatype Channel identifica un canale che trasporta messaggi dello stesso formato dati. Questo pattern semplifica la logica del ricevitore visto che conosce la tipologia del messaggio da processare.
I messaggi contenenti la richiesta di acquisto sono di tipo “documentativo” (Document Message): l‘intento del messaggio infatti non è di impartire un comando, bensì di inviare una serie di dati all‘interno del documento.
Il pattern Document Message prevede di trasferire dati mediante messaggi contenenti documenti.
Siamo quindi arrivati ad avere la seguente situazione per quanto riguarda la parte dell‘invio degli ordini di acquisto:
Conclusioni
Progettando la prima parte dell‘esempio, l‘acquisizione dell‘ordine di acquisto da parte di possibili clienti eterogenei, sono stati introdotti già ben sei pattern che ci hanno permesso di strutturare in modo organico e funzionale l‘architettura sin qui delineata.
Nel prossimo articolo proseguiremo la progettazione dell‘esempio proposto concentrandoci sulla parte relativa alla gestione dell‘ordine.
Riferimenti bibliografici
[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”
[ERMEJB]
Ed Roman, Scott Ambler, Tyler Jewell “Mastering Enterprise JavaBeans”
[AUNJ2EE]
Sun Java Center J2EE Patterns
http://developer.java.sun.com/developer/restricted/patterns/J2EEPatternsAtAGlance.html
[SBPDPC]
Sun Blueprints – Design Patterns Catalog
http://java.sun.com/blueprints/patterns/j2ee_patterns/catalog.html
[GOF]
Gamma, Helm, Johnson, Vlissides “Design Patterns: Elements of Reusable Object-Oriented Software”
[MOKA_PATT_DAO]
Rossini “J2EE Patterns. Parte I: Il pattern Data Access Object “, Mokabyte 62, Aprile 2002