Introduzione

Nei precedenti articoli abbiamo parlato di SOA sia dal punto di vista architetturale [MOKASOAI] che delle metodologie di analisi e di design [MOKASOAII].

Un'azienda che decide di evolvere il proprio sistema informativo verso una architettura SOA deve fare diverse scelte e fronteggiare numerose sfide.

In [MOKASOAIII] e [MOKASOAIV] abbiamo visto come sia indispensabile capire il livello di maturità dell'organizzazione e definire in base a questa una roadmap che definisca i passi aziendali (organizzativi, tecnici, metodologici e culturali) per definire un processo evolutivo ed incrementale con l'obiettivo di una architettura SOA matura.

In [MOKASOAV] abbiamo parlato di Service Oriented Integration (SOI): i principi Service Oriented applicati alle problematiche d'integrazione.

In [MOKASOAVII] si sono introdotte le caratteristiche principali di un Enterprise service BUS (ESB). I servizi SOA devono essere in grado di comunicare tra di loro attraverso un canale di comunicazione: il SOA bus. Da un punto di vista architetturale il SOA bus è un layer che deve mettere a disposizione uno strato di comunicazione tra i servizi: in [MOKASOAVIII] si sono presentati alcuni ESB open-source.

In [MOKA_VIII] si sono introdotte alcune possibili strategie d'adozione di SOA ed in particolare si è parlato dell'importanza di un SOA Pilot.

In [MOKASOAIX] abbiamo presentato uno scenario d'esempio di analisi e design di un processo, utilizzando WSDL e BPEL.

In questo articolo, l'ultimo della serie dedicata a SOA, concludiamo la presentazione dell'esempio pratico con cui stiamo "ripassando" tutto quello che è stato presentato nei precedenti articoli.

Lo scenario d'esempio

Il caso d'uso d'esempio che avevamo preso in considerazione è quello della gestione di un ordine di acquisto che viene considerato valido se l'acquirente presenta una email e una carta di credito validi.

L'esempio proposto è stato sviluppato con ServiceMix 3.0 [SERVICEMIX].

ServiceMix è ad oggi l'ESB JBI-compliant open-source che, a nostro parere, è il più maturo tra quelli disponibili open-source.

Nel nostro esempio ci siamo attenuti alle specifiche JBI: dobbiamo quindi definire l'applicazione come Composite Application. Coerentemente con JBI, i servizi saranno esposti al BUS in WSDL da Service Engine (SE) e accedibili dall'esterno tramite Binding Component (BC) HTTP.

Lo scenario che verrà implementato è il seguente:

  • Un client (Java e C#) invoca il WSDL del BPEL accedendo al bus service mix mediante un JBI Binding Component SOAP
  • L'invocazione, arrivata al BC, viene inoltrata (routing) al SE BPEL che orchestra i seguenti servizi: il servizio di controllo della carta di credito (CheckCdC) e il servizio di controllo email (CheckMail)
  • Il servizio, sulla base dei risultati dei servizi invocati, restituisce la risposta al client

Installazione dei componenti

ServiceMix mette a disposizione una serie di componenti JBI già pronti all'uso, che devono essere installati per essere utilizzati. Questi componenti sono presenti nella directory "components" di ServiceMix, sotto forma di archivio (.zip). Per effettuare l'installazione, è sufficiente copiare l'archivio relativo al componente che si vuole installare nella directory "install".

Per fare funzionare il nostro esempio, installeremo i seguenti componenti:

  • servicemix-jsr181: SE per i WS
  • servicemix-bpe: SE per il processo BPEL
  • servicemix-http: BC per l'esposizione al di fuori del bus del processo BPEL

Le directory di installazione e deploy

Questi componenti serviranno per effettuare il deploy delle nostre Service Unit (SU), sia Binding Component (BC) che Service Engine (SE). L'insieme delle SU assemblate in un Service Assembly produce la composite application che vogliamo costruire. La composite application non è altro che un archivio contenente i .zip delle SU e il jbi.xml del SA. L'archivio della SA va copiato nella directory "deploy" perché ServiceMix poi proceda all'installazione.

Quindi, coerentemente con le specifiche JBI, costruiremo una composite application formata da tre SU:

  • SE JSR181 per la pubblicazione dei servizi CheckMail e CheckCdC sul BUS
  • SE BPE per l'orchestrazione dei servizi
  • BC HTTP per l'esposizione del servizio all'esterno

Il Service Assembly descriptor (il file jbi.xml della SA) dell'applicazione demo dell'articolo prevede quindi:

<service-assembly>
  <identification>
    <name>MokaDemoSA</name>
    <description>Moka Demo service assembly</description>
  </identification>
  <service-unit>
    <identification>
      <name>jsr181su</name>
      <description>jsr181 service unit</description>
    </identification>
    <target>
      <artifacts-zip>jsr181.zip</artifacts-zip>
      <component-name>servicemix-jsr181</component-name>
    </target>
  </service-unit>
  <service-unit>
    <identification>
      <name>bpesu</name>
      <description>bpe service unit</description>
    </identification>
    <target>
      <artifacts-zip>bpe.zip</artifacts-zip>
      <component-name>servicemix-bpe</component-name>
    </target>
  </service-unit>
  <service-unit>
    <identification>
      <name>httpsu</name>
      <description>Contains the binding of the bpe process on SOAP-HTTP</description>
    </identification>
    <target>
      <artifacts-zip>http.zip</artifacts-zip>
      <component-name>servicemix-http</component-name>
    </target>
  </service-unit>
</service-assembly>

Il contenuto delle Service Unit

JSR 181: Web Services Metadata

Le annotazioni sono una delle funzionalità più recenti del linguaggio Java versione 5 e permettono di aggiungere marcatori al codice Java che indicano al container di seguire un determinato comportamento. Le annotazioni non sono codice, ma marcano il codice in modo che il container alteri il proprio comportamento di conseguenza. Questo meccanismo è stato utilizzato, fra le altre cose, per semplificare la definizione di oggetti e componenti, evitando la complessità di complicate configurazioni tramite file XML. Per quanto riguarda i WS, sono state definite appositamente le specifiche JSR 181 [JSR181SPEC].

Di seguito si riporta un semplice esempio di annotazione per la definizione di un semplicissimo Web Service "Hello World".

@WebService
public class HelloWorldService {
  @WebMethod
  public String helloWorld() {
    return "Hello World!";
  }
}

Caricando questa classe in un container apposito, che ne riconosca il significato, si ottiene un servizio Web già pronto, senza la necessità di codificare parti di codice che supportino SOAP.

ServiceMix supporta lo standard JSR181 tramite il SE servicemix-jsr181. Noi comunque abbiamo utilizzato questo SE senza annotare la classe, dato che questo componente supporta la possibilità di specificare l'endpoint del servizio sulla configurazione della SU.

Figura 1 - Web Service CheckEmailService
Figura 1 - Web Service CheckEmailService

L'endpoint del processo per l'accesso "esterno" è definito nel file xbean.xml di configurazione della SU HTTP:

<?xml version="1.0"?>
<beans xmlns:http="http://servicemix.apache.org/http/1.0">
  <http:endpoint service="test:TestProcess"
                 endpoint="TestProcessJBIPort"
                 role="provider"
                 locationURI="http://localhost:8192/TestProcess/"
                 defaultMep="http://www.w3.org/2003/05/soap/mep/request-response"
                 soap="true"/>
</beans>

La Service Unit BPEL

La SU BPEL invece contiene i .wsdl del processo che stiamo definendo e il .bpel che esprime la logica del processo stesso.

La dichiarazione del servizio è:

<service name="TestProcess">
  <port name="TestProcessJBIPort" binding="tns:TestProcessJBIBinding">
    <jbi:address jbi:end-point="TestProcessJBIPort" jbi:service="tns:TestProcess"/>
  </port>
</service>

All'interno dello stesso file WSDL sono state inserite (ma non riportate nell'articolo) anche le descrizioni WSDL dei servizi utilizzati (CheckEmailService e CheckCdCService).

Il BPEL corrispondente al servizio dichiara le variabili utilizzate, riceve il messaggio da elaborare, legge i valori che vengono utilizzati per chiamare i servizi ed esegue la chiamata ai servizi (checkCdC e checkEmail). Infine decide se restituire true o false e restituisce la risposta.

Monitoring mediante JMX

ServiceMix espone i servizi interni ed i componenti attraverso JMX come da specifica JBI. L'MBeanServer del JBIContainer è raggiungibile mediante un JMXConnector che permette la connessione remota via protocollo RMI. Tramite JMX è quindi possibile ispezionare gli oggetti installati in ServiceMix.

String jndiPath = "jmxrmi";
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:/" + jndiPath);
JMXConnector connector = JMXConnectorFactory.connect(url);

I parametri di default per la versione 3 di ServiceMix sono:

  • namingPort: 1099
  • container name: jmxrmi
  • JMX Service URL: service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi

Con il JDK 1.5 si ha a disposizione il tool Console JMX che permette di monitorare applicazioni JMX-compliant.

Per mandarla in esecuzione per il monitoring ed il management di ServiceMix utilizzare il seguente comando:

%JAVA_HOME%/bin/jconsole service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi

Una volta collegati è possibile visualizzare ed interagire con gli MBean selezionando la voce org.apache.servicemix.

Client di test

Avendo a disposizione l'interfaccia di un servizio definita in WSDL, il modo più semplice per chiamare un WS è generare gli stub mediante opportuni tool di conversione da WSDL al linguaggio d'interesse.

Ad esempio con Axis, partendo dal contratto WSDL, è possibile generare le classi da usare lato client utilizzando il tool WSDL2Java (java org.apache.axis.wsdl.WSDL2Java). Il tool WSDL2Java è quindi utile poiché permette di semplificare notevolmente lo sviluppo di un client Java riducendo la quantità di codice da scrivere e senza fare riferimento diretto alle API Axis o JAX-RPC.

Il codice del client Java che ci permette di invocare il nostro WebService diventa così semplice ed intuitivo ed è il seguente:

public class ProcessDemoTest {
  public static void main(String[] args) {
    try {
      TestProcess process = new TestProcessLocator();
      ProcessRequest correctRequest = new ProcessRequest();
      correctRequest.setCdC("123456");
      correctRequest.setEmail("email@email.it");
      ProcessResponse response = process.getTestProcessJBIPort().processExecution(correctRequest);
      System.out.println("Risultato:" + response.getResult());
      // ...
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Client .NET

Con .NET è disponibile il programma analogo wsdl.exe che, dato il WSDL, genera la corrispondente classe Proxy C#.

Il codice client C# è di seguito riportato:

public class TestClient {
  public static void Main(string[] args) {
    new TestClient().test(args[0], args[1]);
  }

  public void test(string word1, String word2) {
    TestProcess service = new TestProcess();
    processRequest datoInput = new processRequest();
    datoInput.CdCId = word1;
    datoInput.email = word2;
    processResponse datoOutput = service.processExecution(datoInput);
    Console.WriteLine("Risultato:" + datoOutput.result);
  }
}

Esecuzione dell'esempio

Mandando in esecuzione il client il processo ritorna false se la email o la carta di credito non sono valide e true nel caso in cui entrambi i dati siano corretti.

Nella nostra implementazione (semplificata) del processo, il Web Service CheckEmailService restituisce true nel caso in cui nella email sia presente la @ mentre il Web Service CheckCdCService restituisce true nel caso in cui il numero della Carta di Credito sia in formato numerico.

Lanciando quindi il processo con carta di credito "123456" ed email "aaa@bbb.it" il processo restituisce true. Nel caso in cui si invochi il servizio con email senza @ o con numero della carta di credito non numerica il processo restituisce false.

Conclusioni

Con questo articolo finisce questa lunga serie di articoli dedicati a SOA. Il percorso che abbiamo affrontato è stato impegnativo e ha toccato alcuni degli aspetti per noi importanti, ma che (purtroppo) spesso non sono trattati con sufficiente chiarezza (anche per colpa di molti articoli "nebulosi" che si trovano in rete). Abbiamo cercato di affrontare l'argomento da molti punti di vista (architetturale, metodologico, organizzativo, tecnologico, pratico) in modo da offrire una visione il più possibile completa di questo tema complesso ma che oggi è sempre più strategico nel mondo IT.

Riferimenti

  • [MOKA_SOA_I] M. Piraccini – S. Rossini, "SOA: Introduzione", MokaByte 100, Ottobre 2005
  • [MOKA_SOA_II] M. Piraccini – S. Rossini, "SOA: Metodologia", MokaByte 101, Novembre 2005
  • [MOKA_SOA_III] M. Piraccini – S. Rossini, "SOA (III): Il Maturity Model", MokaByte 102, Dicembre 2005
  • [MOKA_SOA_IV] M. Piraccini – S. Rossini, "SOA (IV) Roadmap", MokaByte 103, Gennaio 2006
  • [MOKA_SOA_V] M. Piraccini – S. Rossini, "SOA (V) SOI", MokaByte 104, Febbraio 2006
  • [MOKA_SOA_VI] M. Piraccini – S. Rossini, "SOA (VI) ESB (I)", MokaByte 105, Marzo 2006
  • [MOKA_SOA_VII] M. Piraccini – S. Rossini, "SOA (VII) ESB (II)", MokaByte 106, Aprile 2006
  • [MOKA_SOA_VIII] M. Piraccini – S. Rossini, "SOA (VIII)", MokaByte 107, Maggio 2006
  • [MOKA_SOA_IX] M. Piraccini – S. Rossini, "SOA (IX) Esempio (I)", MokaByte 108, Giugno 2006
  • [SERVICEMIX] http://servicemix.org
  • [JSR208_SPEC] R. Ten-Hove – P. Walker, Java Business Integration (JBI) 1.0 Final Release May 24, 2005 http://www.jcp.org/en/jsr/detail?id=208
  • [JBI_HOME] http://java.sun.com/integration/
  • [JSR181SPEC] JSR 181: Web Services Metadata for the Java Platform http://www.jcp.org/en/jsr/detail?id=181
  • [WSBPEL] http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsbpel