Dans la configuration Full de Jboss 7, un broker de messagerie est intégré. (HornetQ)
Pour l’activer, il suffit de lancer son Jboss avec la configuration full (-c=standalone-full.xml).
La configuration des queues et topics se fait dans le subsystem urn:jboss:domain:messaging.
> <subsystem xmlns= »urn:jboss:domain:messaging:1.1″>
> <hornetq-server>
> <persistence-enabled>true</persistence-enabled>
> <journal-file-size>102400</journal-file-size>
> <journal-min-files>2</journal-min-files>
>
> <connectors>
> <netty-connector name= »netty » socket-binding= »messaging »/>
> <netty-connector name= »netty-throughput » socket-binding= »messaging-throughput »>
> <param key= »batch-delay » value= »50″/>
> </netty-connector>
> <in-vm-connector name= »in-vm » server-id= »0″/>
> </connectors>
>
> <acceptors>
> <netty-acceptor name= »netty » socket-binding= »messaging »>
> <param key= »host » value= »${hornetq.remoting.netty.host:XXX.XXX.XXX.XXX} »/>
> <param key= »port » value= »${hornetq.remoting.netty.port:15445} »/>
> </netty-acceptor>
> <netty-acceptor name= »netty-throughput » socket-binding= »messaging-throughput »>
> <param key= »batch-delay » value= »50″/>
> <param key= »direct-deliver » value= »false »/>
> </netty-acceptor>
> <in-vm-acceptor name= »in-vm » server-id= »0″/>
> </acceptors>
>
> <security-settings>
> <security-setting match= »# »>
> <permission type= »send » roles= »guest »/>
> <permission type= »consume » roles= »guest »/>
> <permission type= »createNonDurableQueue » roles= »guest »/>
> <permission type= »deleteNonDurableQueue » roles= »guest »/>
> </security-setting>
> </security-settings>
>
> <address-settings>
> <address-setting match= »# »>
> <dead-letter-address>jms.queue.DLQ</dead-letter-address>
> <expiry-address>jms.queue.ExpiryQueue</expiry-address>
> <redelivery-delay>0</redelivery-delay>
> <max-size-bytes>10485760</max-size-bytes>
> <address-full-policy>BLOCK</address-full-policy>
> <message-counter-history-day-limit>10</message-counter-history-day-limit>
> </address-setting>
> </address-settings>
>
> <jms-connection-factories>
> <connection-factory name= »InVmConnectionFactory »>
> <connectors>
> <connector-ref connector-name= »in-vm »/>
> </connectors>
> <entries>
> <entry name= »java:/ConnectionFactory »/>
> </entries>
> </connection-factory>
> <connection-factory name= »RemoteConnectionFactory »>
> <connectors>
> <connector-ref connector-name= »netty »/>
> </connectors>
> <entries>
> <entry name= »RemoteConnectionFactory »/>
> <entry name= »java:jboss/exported/jms/RemoteConnectionFactory »/>
> </entries>
> <connection-ttl>6000000</connection-ttl>
> </connection-factory>
> <pooled-connection-factory name= »hornetq-ra »>
> <transaction mode= »xa »/>
> <connectors>
> <connector-ref connector-name= »in-vm »/>
> </connectors>
> <entries>
> <entry name= »java:/JmsXA »/>
> </entries>
> </pooled-connection-factory>
> </jms-connection-factories>
>
> <jms-destinations>
> <jms-queue name= »testQueue »>
> <entry name= »queue/test »/>
> <entry name= »java:jboss/exported/jms/queue/test »/>
> </jms-queue>
> <jms-topic name= »testTopic »>
> <entry name= »topic/test »/>
> <entry name= »java:jboss/exported/jms/topic/test »/>
> </jms-topic>
> </jms-destinations>
> </hornetq-server>
> </subsystem>
La partie la plus intéressante est la partie JMSJava Messaging Service-DESTINATIONS qui permet de créer des queue et des topic ainsi que de configurer leurs noms.
Deux types de noms sont présent: par exemple pour testQueue, vous avez le nom interne (depuis le serveur) et le nom externe depuis une autre application (si vous souhaitez exposer vos Queues).
Le nom interne est: queue/test tandis que le nom externe est : java:jboss/exported/jms/queue/test.
En remontant un peu dans le fichier, vous trouverez les factorys, de même deux factory sont présentes (remote et local) avec leurs noms JNDI. Ces factorys font références à des connecteur (ici netty). Pour chaque connecteur vous avez la possibilité de choisir les acceptors (flux entrants). Pensez bien à configurer: avec la bonne adresse IP sinon vous ne pourrez pas vous connecter à votre QUEUE/TOPIC.
Attention, il est aussi important de sécuriser l’accès à vos queues en créer une sécurité:
> <security-domain name= »messaging » cache-type= »default »>
> <authentication>
> <login-module code= »UsersRoles » flag= »required »>
> <module-option name= »usersProperties » value= »${jboss.server.config.dir}/messaging-users.properties »/>
> <module-option name= »rolesProperties » value= »${jboss.server.config.dir}/messaging-roles.properties »/>
> </login-module>
> </authentication>
> </security-domain>
Les fichiers messaging-users.properties et messaging-roles.properties sont bien sur à créer.
Enfin il ne reste plus qu’à configurer les ports pour votre messagerie de la sorte:
> import javax.annotation.PostConstruct;
> import javax.annotation.PreDestroy;
> import javax.annotation.Resource;
> import javax.ejb.ActivationConfigProperty;
> import javax.ejb.EJBException;
> import javax.ejb.MessageDriven;
> import javax.ejb.MessageDrivenBean;
> import javax.ejb.MessageDrivenContext;
> import javax.inject.Inject;
> import javax.jms.Connection;
> import javax.jms.ConnectionFactory;
> import javax.jms.JMSException;
> import javax.jms.Message;
> import javax.jms.MessageListener;
> import javax.jms.ObjectMessage;
> import javax.jms.Session;
>
> import fr.axopen.logging.message.JmsMessage;
>
> @MessageDriven(activationConfig = {
> @ActivationConfigProperty(propertyName = « acknowledgeMode », propertyValue = « Auto-acknowledge »),
> @ActivationConfigProperty(propertyName = « destinationType », propertyValue = « javax.jms.Queue »),
> @ActivationConfigProperty(propertyName = « destination », propertyValue = « java:jboss/exported/jms/queue/test »),
>
> })
> public class ListingQueue implements MessageDrivenBean, MessageListener {
> /**
> *
> */
> private static final long serialVersionUID = 1L;
> @Resource(mappedName = « java:/JmsXA »)
> private ConnectionFactory factory;
>
> private Connection connection;
>
> private Session session;
>
> @SuppressWarnings(« unused »)
> private MessageDrivenContext messageDrivenContext;
>
> @PreDestroy
> protected void preDestroy() throws JMSException {
> session.close();
> connection.close();
> }
>
> @PostConstruct
> protected void postConstruct() throws JMSException {
> connection = factory.createConnection();
> session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
> }
>
> @Override
> public void setMessageDrivenContext(MessageDrivenContext ctx)
> throws EJBException {
> this.messageDrivenContext = ctx;
> }
>
> @Override
> public void ejbRemove() throws EJBException {
> }
>
> @Override
> public void onMessage(Message message) {
>
> try {
>
> } catch (JMSException jmse) {
> throw new RuntimeException(jmse);
> }
> }
>
> }
Enfin si vous souhaitez vous connecter à la file JMS à distance, voici un exemple:
## Exemple d’envoi d’un message JMS
import java.io.PrintWriter;
> import java.io.StringWriter;
> import java.util.Date;
> import java.util.HashMap;
> import java.util.List;
> import java.util.Map;
> import java.util.Properties;
>
> import javax.jms.Connection;
> import javax.jms.JMSException;
> import javax.jms.MessageProducer;
> import javax.jms.ObjectMessage;
> import javax.jms.Queue;
> import javax.jms.QueueConnectionFactory;
> import javax.jms.Session;
> import javax.naming.Context;
> import javax.naming.InitialContext;
> import javax.naming.NamingException;
> import javax.servlet.ServletRequest;
> import javax.servlet.http.HttpServletRequest;
>
> import org.apache.commons.lang.exception.ExceptionUtils;
> import org.hornetq.api.core.TransportConfiguration;
> import org.hornetq.api.jms.HornetQJMSClient;
> import org.hornetq.api.jms.JMSFactoryType;
> import org.hornetq.core.remoting.impl.netty.NettyConnectorFactory;
> import org.hornetq.core.remoting.impl.netty.TransportConstants;
> import org.hornetq.jms.client.HornetQConnectionFactory;
>
> import com.workinlive.framework.Config;
>
> import fr.axopen.logging.message.JmsMessage;
> import fr.axopen.logging.message.TypeMessageEnum;
>
> public class JmsConnectionFactory {
> private static JmsConnectionFactory instance;
>
> private Context mContext;
> Connection mConnection = null;
>
> QueueConnectionFactory mConnectionFactory;
> Queue mQueue = null;
> HornetQConnectionFactory mHornetConnectionFactory;
> private boolean mIsOperationnel = false;
>
> private void connect() {
> try {
> System.out.println(« JMS Connection »);
> Properties props = new Properties();
> props.put(Context.INITIAL\_CONTEXT\_FACTORY,
> « org.jboss.naming.remote.client.InitialContextFactory »);
> props.put(Context.PROVIDER\_URL, Config.JMS\_PROVIDER_URL);
> props.put(Context.SECURITY\_PRINCIPAL, Config.JMS\_SECURITY_PRINCIPAL);
> props.put(Context.SECURITY_CREDENTIALS,
> Config.JMS\_SECURITY\_CREDENTIALS);
>
> mContext = new InitialContext(props);
>
> final Map<String, Object> p = new HashMap<String, Object>();
> TransportConfiguration tc;
>
> p.put(TransportConstants.HOST\_PROP\_NAME, Config.JMS\_HOST\_LOGGING);
> p.put(TransportConstants.PORT\_PROP\_NAME, Config.JMS\_HOST\_PORT);
>
> tc = new TransportConfiguration(
> NettyConnectorFactory.class.getName(), p);
>
> mHornetConnectionFactory = HornetQJMSClient
> .createConnectionFactoryWithoutHA(JMSFactoryType.QUEUE_CF,
> tc);
>
> mQueue = (Queue) mContext.lookup(Config.JMS\_JNDI\_QUEUE);
>
> mConnection = mHornetConnectionFactory.createConnection();
>
> mIsOperationnel = true;
> } catch (NamingException e) {
> e.printStackTrace();
> System.err.println(« Problème de connexion JMS »);
> } catch (JMSException e) {
> e.printStackTrace();
> System.err.println(« Erreur de connexion JMS »);
> }
>
> }
>
> private JmsConnectionFactory() {
> connect();
>
> }
>
> public static JmsConnectionFactory getInstance() {
> if (instance == null) // 1
> instance = new JmsConnectionFactory(); // 2
> return instance; // 3
> }
>
> public Connection getConnection() {
> if (mConnection == null || !mIsOperationnel) {
> closeSession();
> mIsOperationnel = true;
> connect();
> }
>
> return mConnection;
> }
>
> public Queue getQueue() {
> return mQueue;
> }
>
> public void closeSession() {
> try {
> if (mContext != null) {
> mContext.close();
> }
> } catch (NamingException e) {
> e.printStackTrace();
> }
> try {
> if (mHornetConnectionFactory != null)
> mHornetConnectionFactory.close();
> } catch (Exception e) {
> e.printStackTrace();
> }
> try {
> if (mConnection != null)
> mConnection.close();
> } catch (JMSException e) {
> e.printStackTrace();
> }
>
> }
>
> public boolean isOperationnel() {
> return mIsOperationnel;
> }
>
> public void setOperationnel(boolean pIsOperationnel) {
> mIsOperationnel = pIsOperationnel;
> }
N'hésitez pas si vous avez des questions!
Découvrez la planche #55 !
Il s’agit d’un modèle d’architecture qui s’appuie sur les concepts d’architecture centralisée (un core model partagé par toute une organisation) et d’architecture spécifique (des fonctionnalités spécifiques à un domaine sont implémentés afin de répondre à
Connaître et comprendre les différents modèles de gestion des données de référence (MDM)