MokaByte 63 - Maggio 2002 
Una Chat basata su SOAP
I parte
di
Massimiliano
Bigatti
Le tecnologie avanzano e nuovi trend o soluzioni consentono di approcciare vecchi problemi in modo nuovo. Le nuove tecnologie risolvono sempre qualche problema... e ne introducono altri. Vediamo un'esperienza di sviluppo utilizzando i Web Services, ed in particolare la tecnologia SOAP

Introduzione
Da questo mese iniziamo una serie di articoli che ci seguirà nello sviluppo di una chat basata su SOAP. Questo primo articolo avrà un approccio un po' ad alto livello: ritengo sia sempre utile iniziare un progetto pensando ai requisiti funzionali, alle costrizioni tecniche ed all'architettura. In questo modo penso si affronti il design e l'implementazione con le idee più chiare e con tutti i vincoli già definiti, consentendo di svolgere queste fasi con maggiori semplicità. Una volta identificati i vincoli, si comincerà ad accennare qualche elemento di design.

 

Chattare, che passione
Quali sono le funzionalità di un'applicazione di chat? La risposta non é unica: diverse applicazioni contengono funzionalità diverse anche se il denominatore comune, che rappresenta la funzione di base dell'applicazione, é quella di scambiare messaggi tra più utenti connessi al sistema. In pratica, un utente invia un messaggio alla chat e questo viene ricevuto da tutti gli altri utenti connessi. In questo modo si realizza una comunicazione in tempo reale tra più utenti.
Per identificare i requisiti utenti la cosa più importante é... avere un utente a disposizione! Nel nostro caso, l'utente di riferimento é "Mokauser". Chi si cela dietro questo pseudonimo? Non lo possiamo rivelare, ma é un personaggio molto importante della redazione di Mokabyte.
Tra l'altro, forse questa chat verrà messa on-line sul sito di Mokabyte, dunque ci sono alcuni requisiti funzionali e tecnici da tenere in considerazione.
Con Mokauser, si é deciso di ispirarsi alla Java Relay Chat che Mokabyte ha presentato nei numeri di febbraio, aprile e maggio 1998 a cura di Michele Sciabarrà (riferimenti [1], [2] e [3]). Inoltre sono stati raccolti altri elementi, sia funzionali che tecnici:

  • Autenticazione. Per prima cosa, essendo il sistema basato sul concetto di utente connesso, appare evidente la necessità di un sistema di autenticazione che consenta di identificare l'utente in modo univoco e "sicuro". In merito a questa problematica, si nota come una funzionalità di autenticazione sia già implementata nel sistema della Community di Mokabyte, dunque l'ideale sarebbe utilizzare le funzione già esistente, lasciando però libero il sistema di utilizzare altri sistemi di autenticazione. In merito a ciò si é convenuto con Mokauser che l'id dell'utente verrà passato all'Applet da parte di una pagina di autenticazione sviluppata da Mokabyte.
  • Tecnologie. Questo progetto, non é fine a se stesso, ma vuole mettere alla prova le tecnologie che stanno alla base dei Web Services, come SOAP e le relative implementazioni Java, come JAXM. Inoltre, l'accoppiata SOAP/HTTP dovrebbe fornire più scalabilità rispetto, ad esempio, all'originale implementazione di Java Relay Chat che utilizza Socket dirette e Thread per utente. La versione originale, se dal punto di vista didattico riveste una comprovata importanza, da quello più strettamente operativo può presentare limitazioni per via dell'utilizzo delle risorse del sistema (come i thread).
  • Architettura. L'applicazione potrà essere fruita via Internet, tramite un'Applet. In alternativa potrà essere utilizzata all'esterno del browser, come applicazione standalone. Il requisito minimo di sistema é una implementazione di Java2. In merito ai livelli, rimane valida la scelta fatta per Java Relay Chat: l'applicazione può essere infatti realizzata attraverso un'architettura client/server.


In figura 1 é possibile vedere l'impostazione dell'architettura del sistema.


Figura 1
- architettura SOAP Chat

Come si vede, l'implementazione del server é interfacciato dal client tramite una servlet SOAP. Prima di uscire sulla rete esterna, la comunicazione passa attraverso un firewall per poi arrivare all'Applet o all'applicazione.

 

Il protocollo
Per capire come implementare il protocollo di comunicazione su SOAP, é necessario capire come avviene la comunicazione tra client e server. Il protocollo SOAP non sarà una mera trasposizione del protocollo Socket implementato in Java Relay Chat ma una nuova implementazione che coprirà solo le funzionalità richieste all'applicazione. Per prima cosa affrontiamo l'operatività interna del client che si decide essere la stessa di JRC (Java Relay Chat). In figura 2 é possibile vedere il ciclo operativo del client. Rimandiamo a [2] per approfondimenti in merito.



Figura 2
- ciclo operativo del client

Sommariamente, il punto (1) consente di leggere dal server i messaggi che sono stati inviati dagli altri utenti all'utente in oggetto (memorizzati in un buffer apposito), mentre il punto (2) effettua l'invio del messaggio digitato dall'utente agli altri utenti connessi al sistema (inserendo il messaggio all'interno del buffer di ciascun utente).
Si nota che l'utilizzo di buffer di messaggi per ciascun utente é un approccio che richiede la duplicazione dei riferimenti ai messaggi per ciascun utente. Queste code di dati occupano memoria e tempo di processore ma si ritiene che per il numero di utenti che può avere una chat pubblica (dove tutti intervengono), l'implementazione sia sufficentemente efficiente.
Dalle operazioni del client si evince la necessità di implementare due Web Services distinti:

1. servizio di lettura dei messaggi dell'utente connesso.;
2. servizio di invio del messaggio digitato dall'utente al server.

Il primo servizio é di tipo request/response: il client invia una richiesta al server e questo risponde con i messaggi che il client deve visualizzare.
Il secondo servizio può essere di tipo fire&forget (detto anche Oneway - termine utilizzato da SUN nelle JAXM), in quanto funzionalmente non é necessaria alcuna risposta. Implementeremo comunque una risposta a questi messaggi, al solo scopo di comunicare la corretta esecuzione della funzione.
La fase di attesa é invece presente per evitare di saturare il server di richieste, ma anche così l'approccio non é efficientissimo e può presentare problemi si scalabilità. L'ideale sarebbe che il server invii delle notifiche al client ma ad oggi questa strada non risulta percorribile.
A monte ed a valle del ciclo operativo del client sono necessarie le operazioni di login e logout del sistema che indicano l'entrata nella chat di un utente o la sua disconnessione. Queste informazioni consentono di gestire i buffer dei messaggi. Entrambi sono messaggi di tipo fire&forget.

 

Lettura messaggi
Il servizio di lettura dei messaggi può essere così strutturato:

  • nell'intestazione deve essere presente l'utente ed eventualmente un token di sicurezza, per verificare che la richiesta sia effettivamente inviata dall'utente in oggetto. Inoltre potrebbe essere utile inviare l'indirizzo ip del client per eseguire un logging delle operazioni;
  • nel corpo del messaggio, é sufficiente indicare la "funzione remota" da invocare. Non sono necessari parametri particolari.

Un esempio di messaggio SOAP di richiesta é presente nel listato 1, mentre nel listato due é possibile vedere un esempio di risposta.

Listato 1
<?xml version="1.0"?>
<soap-env:Envelope
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:mbc="http://schemas.mokabyte.it/soapchat">

<soap-env:Header>
<mbc:User>utente</mbc:User>
<mbc:Token>utente</mbc:Token>
<mbc:IP>192.168.1.1</mbc:IP>
</soap-env:Header>

<soap-env:Body>
<mbc:GetMessages/>
</soap-env:Body>

</soap-env:Envelope>

Listato 2
<?xml version="1.0"?>
<soap-env:Envelope
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:mbc="http://schemas.mokabyte.it/soapchat">

<soap-env:Header/>

<soap-env:Body>
<mbc:GetMessagesResponse>
<mbc:Message id="001">testo 1</mbc:Message>
<mbc:Message id="002">testo 2</mbc:Message>
<mbc:Message id="003">testo 3</mbc:Message>
</mbc:GetMessagesResponse>
</soap-env:Body>

</soap-env:Envelope>

Non si é ritenuto necessario utilizzare l'encoding SOAP in quanto questi servizi sono interni all'applicazione e dunque meno soggetti a problematiche di integrazione da parte di terze parti.

 

Invio di messaggi
L'altra funzione principale dell'applicazione é quella che consente di inviare messaggi agli altri utenti. Il servizio di invio del messaggio può essere così strutturato:

* nell'intestazione dovrebbero essere presenti le solite informazioni di sicurezza;
* nel corpo del messaggio, é necessario specificare il messaggio da inviare.

Un esempio di messaggio SOAP é presente nel listato 3.

Listato 3
<?xml version="1.0"?>
<soap-env:Envelope
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:mbc="http://schemas.mokabyte.it/soapchat">

<soap-env:Header>
<mbc:User>utente</mbc:User>
<mbc:Token>utente</mbc:Token>
<mbc:IP>192.168.1.1</mbc:IP>
</soap-env:Header>

<soap-env:Body>
<mbc:SendMessage>Messaggio da inviare</mbc:SendMessage>
</soap-env:Body>

</soap-env:Envelope>

In tutti i messaggi SOAP descritti, si é fatto uso del namespace "mbc" che punta all'URL http://schemas.mokabyte.it/soapchat. Una nota: non é indispensabile che l'URL esista, e cioé che a quell'indirizzo HTTP venga restituito qualche cosa. E' sufficiente fornire un nome univoco a livello mondiale e visto che schemas.mokabyte.it discende da un dominio web (mokabyte.it) che é di proprietà dell'intestatario del dominio (Mokabyte), é impossibile che qualche altro utilizzi come URI quella stringa (a meno che intenzionalmente non voglia utilizzare URI incompatibili).
Un'altro elemento da notare é che non sono specificate informazioni in relazione al "canale" di comunicazione (o ROOM - stanze in Java Relay Chat), infatti in questa versione non é prevista la gestione di più canali che potrà però essere aggiunta in futuro modificando i messaggi SOAP.

 

Login e logout
Come accennato, é necessario indicare al sistema la presenza di un nuovo utente, in modo da registrare i messaggi a lui inviati. Inoltre, per evitare di utilizzare risorse inutilmente, é bene indicarne anche la disconnessione, in modo da evitare di registrare i messaggi anche dopo l'uscita dal sistema.
Un esempio di messaggio di login é presente nel listato 4.

Listato 4
<?xml version="1.0"?>
<soap-env:Envelope
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:mbc="http://schemas.mokabyte.it/soapchat">

<soap-env:Header>
<mbc:User>utente</mbc:User>
<mbc:Token>utente</mbc:Token>
<mbc:IP>192.168.1.1</mbc:IP>
</soap-env:Header>

<soap-env:Body>
<mbc:Login/>
</soap-env:Body>

</soap-env:Envelope>

Il messaggio di logout sarà similare.

 

SOAP con JAXM
Le implementazioni Java di SOAP sono molteplici ed anche se si restringe il campo a quelle gratuite (più quelle anche libere) si riconoscono quattro implementazioni principali:

  • JAXM
  • Apache SOAP
  • Apache AXISù
  • IBM

Ho elencato per prima l'implementazione di SUN perché alla fin dei conti le interfacce definite saranno quelle standard della piattaforma Java anche se poi l'implementazione specifica potrà essere diversa (come nel caso di JAXP che per default propone Crimson di Apache ma può utilizzare anche altri parser XML come Xerces della stessa Apache).
Apache SOAP é stata inizialmente donata da IBM ad Apache Group ed é in fase di declino, sostituita da Axis. Quest'ultimo sembra un buon prodotto, sicuramente degno di approfondimento.
Per finire, anche IBM ha una propria implementazione di SOAP, contenuta nel toolkit per i Web Services che é disponibile anche in bundle con WebSphere. Anche la soluzione IBM sarebbe di interesse, anche se é facile prevedere che le interfacce si allineeranno in futuro agli standard definiti da (e con) SUN.
Per l'implementazione della nostra Chat si decide dunque di utilizzare JAXM, per imboccare una via il più standard possibile.
Una cosa da notare, però, é che, sebbene nelle specifiche siano definite diverse modalità di comunicazione punto-punto (fire&forget, request/response, sia sincrone che asincrone), l'implementazione di JAXM disponibile ad oggi prevede solo la fire&forget e la request/response. Questo può rivestire un limite per l'implementazione di una chat dove i messaggi potrebbero arrivare al client in modo asincrono e non su richiesta, approccio utilizzato nella Java Relay Chat e che dovremo replicare nella nostra. Inoltre, la funzionalità di fire&forget é disponibile solo per applicazioni J2EE che girano all'interno di un Web Container, dunque non utilizzabili nelle nostre Applicazioni ed Applet.

 

Riutilizzo del codice
Un ultimo elemento considerato in fase di analisi iniziale é la riutilizzabilità del codice di Java Relay Chat. Sebbene le due chat non condividano il livello di trasporto ed il protocollo applicativo, alcune classi presenti in JRC possono essere utilizzate anche per SOAP Chat, in particolare ChatBuffer e NickRegister.
La prima implementa il buffer di messaggi che devono ancora essere inviati ad un utente. L'implementazione é thread-safe e dunque consente l'accesso contemporaneo da parte di più thread. L'implementazione é molto pulita e ci consente di riutilizzare la classe nella sua integrità.
Per quanto riguarda NickRegister forse sarà necessario qualche intervento ma a grandi linee il codice potrà essere riutilizzato.
A proposito di JRC si noti un particolare: il software é rilasciato come GPL (GNU Public License). Questa licenza obbliga a ridistribuire ogni lavoro derivato come GPL, per questo motivo anche SOAP Chat viene rilasciata con questa licenza.

 

Conclusioni
In questo primo articolo abbiamo raccolto i requisiti funzionali del sistema, i limiti ed imposizioni tecniche richieste e tutti gli elementi che potranno essere utili per la fase di implementazione. Come nella serie originale di Michele Sciabarrà, non garantisco la conformità dei prossimi sviluppi con quanto detto finora: é possibile infatti che vengano riscontrati problemi in quanto rilevato o si rilevino incongruenze. Tutti i problemi che potrebbero sorgere saranno affrontati a tempo debito e potrebbero portare ad una revisione di quanto definito. D'altra parte il ciclo di sviluppo (almeno quello di mio riferimento) é ciclico: ogni fase può portare modifiche - meglio se minime - ai prodotti delle altre fasi.
Nella prossima puntata, vedremo l'implementazione del server, mentre in quella successiva ci occuperemo del client.

 

Bibliografia
[1] Michele Sciabarrà - "Java Relay Chat", Mokabyte, febbraio 1998
[2] Michele Sciabarrà - "Java Relay Chat, parte 2", Mokabyte, aprile 1998
[3] Michele Sciabarrà - "Java Relay Chat, parte 3", Mokabyte, maggio 1998
[4] Andrea Giovannini - "SOAP e Java: Integrazione di applicazioni Java con il nuovo protocollo SOAP", Mokabyte, gennaio 2001
[5] Massimiliano Bigatti - "Web Services (6) - Java API for XML Messaging (JAXM)", Mokabyte, Marzo 2002


Massimiliano Bigatti è SUN Certified Enterprise Architect for Java Platform, Enterprise Edition Technology. Si occupa di architetture applicative basate su Java ed Internet, technical writing e musica rock.

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it