
Gestion des Queues et Topics sous Jboss 7. @MessageDriven et configuration
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!
Accessibilité: Liste des points de vigilance sur l’accessibilité des applications web et la prise en compte des différents handicaps.
Face à l'explosion des coûts liés au cloud public, une nouvelle discipline s'impose : le FinOps. Dans un contexte où les entreprises adoptent massivement les infrastructures cloud pour leur flexibilité et leur scalabilité, les mauvaises surprises sur la facture sont malheureusement devenues monnaie courante. Optimiser ses dépenses cloud n'est plus un luxe, mais une nécessité pour garantir la rentabilité des projets et maitriser ses budgets IT. Mais pas de panique ! Cet article vous dévoile tout ce que vous devez savoir sur le FinOps, ses principes clés, et les bonnes pratiques pour maîtriser vos coûts tout en tirant le meilleur parti de vos ressources cloud.
Et si le meilleur moyen de reprendre le contrôle sur son système d'information, c'était de revenir à l'essentiel ? Chez AXOPEN, on lance un petit slogan en 2025 – un brin provocateur, mais sincère : "Kubernetes is all you need".