Nell’era delle App dove tutto è smart e veloce, parlare di Message Driven Bean (MDB) e Java Message Service (JMS) sembra retrogrado e pesante. In realtà, se sviluppate applicazioni a livello enterprise, non è così strano dover ricorrere a bus di messaggistica per risolvere determinati scenari di business. In Java EE 5 inoltre, come , se avevamo l’esigenza di eseguire operazioni in modo asincrono rispetto alla chiamata del client, le code potevano essere una valida seppur complessa alternativa per ottenere lo scopo.
In passato abbiamo anche avuto modo di approfondire sia che di cosa sono le code JMS, gli MDB e come si lavora con essi con JBoss AS 6. Da tempo è uscito JBoss AS 7, ma non abbiamo mai affrontato l’argomento con la nuova versione del nostro Application Server preferito. E’ tempo di aggiornarsi un po’.
Prima di cominciare
Se gestite il vostro progetto con Maven e siete partiti dalla famiglia di archetipi
jboss-javaee6-webapp-*
per risolvere le dipendenze JMS in compilazione è necessario importare nel vostro modulo EJB le dipendenze JBoss per JMS:
org.jboss.spec.javax.jms jboss-jms-api_1.1_spec
Facendo parte del BOM incluso nel progetto POM principale, la versione è automaticamente gestita.
Configurazione del Server
JBoss 7 raccoglie tutta la configurazione in un unico file xml. La maggior parte delle volte avremo a che fare con il file standalone.xml, ma gli stessi discorsi che faremo valgono anche se usiamo JBoss in modalità domain, gestita dal file (indovinate un po’) domain.xml. La natura modulare dell’AS ha consentito agli sviluppatori di realizzare altri file di configurazione che includono funzionalità aggiuntive, caratterizzati dai suffissi -full.xml, -ha.xml e -full-ha.xml.
Senza scendere nei dettagli, nella full si abilita tutto lo stack della specifica Java EE 6, che non sempre è completamente necessaria, mentre nella HA (High Availability), si attivano quelle funzionalità che garantiscono l’alta affidabilità e la continuità del servizio offerto da JBoss (leggi cluster).
La via semplice
JMS e gli MDB rientrano nella categoria del profilo full. Come attivarlo quindi?
Se avviamo il server come servizio o comunque tramite gli script standalone.sh/standalone.bat, basta individuare nel file JAVA_HOME/bin/standalone.conf il parametro:
-Djboss.server.default.config=standalone.xml
e aggiungere il suffisso -full.xml nel nome del file per avviare il server.
In fase di sviluppo, da Eclipse invece, basta fare doppio click sul nome del server e cliccare il link “Open lauch configuration”: in questo caso il parametro da cercare e sostituire sarà
--server-config=standalone.xml
Rimbocchiamoci le maniche
Se siamo maniaci del controllo, o non vogliamo cambiare profilo, possiamo portarci “a casa” quello che ci server dal profilo full.
Per cominciare basta copiarsi:
- l’estensione
da riportare in cima al file - tutto il subsystem urn:jboss:domain:messaging:1.1
- l’attivazione degli MDB:
da riportare nel subsystem urn:jboss:domain:ejb3:1.2 - i socket bindings:
da aggiungere al socket-binding-group in fondo al file
Configurare la coda JMS
Indipendentemente dalla scelta presa in precedenza, la configurazione di default contenuta nel subsystem urn:jboss:domain:messaging:1.1 prevede:
- Un Connection Factory raggiungibile dalla stessa JVM con nome JNDI:
java:/ConnectionFactory - Un Connection Factory raggiungibile da remoto con nome JNDI:
java:jboss/exported/jms/RemoteConnectionFactory.
Da notare che in questo caso l’accesso è regolamentato dai security-settings definiti nello stesso subsystem - Una coda di nome testQueue che risponde ai nomi JNDI:
queue/test e java:jboss/exported/jms/queue/test - Un topic di nome testTopic che risponde ai nomi JNDI:
topic/test e java:jboss/exported/jms/topic/test
Per aggiungere o modificare le code basta intervenire in questo punto. Un semplice esempio funzionante sulla configurazione di default per inviare messaggi di testo è:
@Stateless @LocalBean public class JmsMessageProducer { @Resource(name="java:/ConnectionFactory") private ConnectionFactory connectionFactory; @Resource(name="java:/queue/test") private Queue queue; public void sendTextMessage(String text) throws JMSException { Connection connection = null; try { connection = connectionFactory.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(queue); producer.send(session.createTextMessage(text)); } finally { if (connection != null) { connection.close(); } } } }
da notare la riga evidenziata: il nome della coda in questo caso richiede il prefisso java://. Nell’MDB che riceve il messaggio invece non è necessaria:
@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/test") }) public class JmsMessageListener implements MessageListener { private Logger logger = LoggerFactory.getLogger(JmsMessageListener.class); /** * @see MessageListener#onMessage(Message) */ public void onMessage(Message message) { try { logger.info("Messaggio ricevuto: " + ((TextMessage) message).getText()); } catch (JMSException e) { logger.error("Errore durante l'interpretazione del messaggio " + message, e); } } }
Conclusioni
Per chi ha già usato JMS e gli MDB con JBoss AS6 non noterà nessuna differenza rispetto all’AS7 (e meno male, non è mica cambiata la specifica…). Anzi, anche l’implementazione è sempre HornetQ, introdotto con l’AS 6. Portare quindi il codice suo nuovo AS 7 è solo un questione di configurazione e richiede solo un po’ di dimestichezza con lo standalone.xml e nient’altro.