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.
|