La possibilità di utilizzare delle code per lo scambio di messaggi, consente lo sviluppo di servizi secondo un nuovo paradigma, che non segue più la classica logica della richiesta/risposta. È quello che praticamente facciamo ogni giorno, solo che non ce ne rendiamo conto. Il servizio di email si basa su questo principio, gli sms, giusto per fare degli esempi che ci permettono di chiarire l'importanza che si nasconde dietro la logica dei servizi message-oriented.
Nella lezione precedente abbiamo discusso la teoria dei servizi di messaggistica e come la presenza di sistemi appositi (MOM) ne consenta l'utilizzo. La piattaforma J2EE mette a disposizione uno strumento che sarà molto utile nello sviluppo di servizi che si basano sullo scambio di messaggi: i message driven bean.
Un message driven bean è un componente di logica applicativa che viene "legato" ad una coda e viene attivato automaticamente dal container nel momento in cui sulla coda arriva un messaggio. Di fatto rappresenta il consumatore di messaggi.
Attraverso questi componenti è possibile pensare a sistemi evoluti di invio messaggi (in tutte le forme che vi vengono in mente, email, sms, ecc), dove, grazie alla presenza delle code è facile gestire il flusso di operazioni (il bilanciamento di carico è mantenuto dal container).
Guardando il componente nella pratica, con l'aiuto di un esempio, noteremo che rispetto agli altri bean, questi si presentano davvero molto semplici da implementare.
Per non complicare la comprensione dello sviluppo del componente, creeremo un bean che, notificato (dal container) della presenza di un messaggio, ne stampa a video il contenuto.
Come si può osservare dal codice di ConsoleWriter.java, l'unico metodo di logica presente è il metodo onMessage(Message m)
. Questo è il metodo che viene richiamato dal container al momento della ricezione del messaggio, dove come parametro viene passato il messaggio vero e proprio. Nel nostro caso, trattandosi di una semplice applicazione, ci occuperemo di stampare il contenuto sul flusso di output.
Nella realtà sarà qui dentro ad esserci l'elaborazione del messaggio e la successiva operazione, eventualmente facendo uso degli altri componenti dell'application server. Infatti, attraverso la variabile context (come negli altri ejb) manteniamo il riferimento all'ambiente di esecuzione (ed attraverso di esso possiamo interrogare gli altri servizi).
Gli altri due metodi presenti sono il metodo ejbCreate()
ed ejbRemove()
, metodi callback che vengono chiamati dal container per gestirne il ciclo di vita.
Come si può intuire anche i message driven bean sono componenti stateless, in quanto la loro esecuzione si limita al metodo onMessage()
. Questo li rende adatti al meccanismo del pooling (vedi gli stateless session bean), che permette un'eccellente gestione delle risorse da parte del container.
Il descrittore di deploy (ejb-jar.xml) definisce il nome del bean, la classe e la tipologia di coda da collegare (Queue o Topic).
In realtà, per effettuare il deploy su un application server ben definito abbiamo necessità di un ulteriore elemento, cioè del descrittore vendor-specific. In esso, infatti, viene definita la coda (con un nome JNDI) a cui il bean sarà associato. Di seguito il descrittore per AS JBoss:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.2//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd">
<jboss>
<enterprise-beans>
<message-driven>
<ejb-name>ConsoleWriter</ejb-name>
</message-driven>
</enterprise-beans>
<resource-managers></resource-managers>
</jboss>
Qui bisogna aprire una piccola parentesi: ogni application server gestisce questo tipo di operazioni in maniera proprietaria. Anche la stessa presenza di MOM può essere più o meno buona, in base all'esigenza dell'applicativo. Di certo, a parte l'ultimo descrittore, la logica di business rimane tale e quale a come descritto.