Implémentation de la messagerie JMS


J'ai eu du mal avec cette tâche "simple" pour les personnes plus expirienced, je suis coincé depuis 2 jours maintenant besoin d'aide. J'ai changé des choses comme des millions de fois maintenant, finalement je suis tombé sur ce tutoriel JMS de printemps.

Ce que je veux faire, Envoyer un message et le recevoir. J'ai aussi lu ce livre chapitre 8 sur la messagerie. Cela explique vraiment bien 2 types de messagerie et il y a un bel exemple pour le type publish-and-subscribe mais maintenant un exemple pour la messagerie point-to-point (c'est celui dont j'ai besoin).

Je suis capable d'envoyer un message à la file d'attente par moi-même, mais je n'ai aucune idée de comment recevoir c'est pourquoi j'ai essayé avec ce tutoriel de printemps voici ce que j'ai jusqu'à présent:

EXPÉDITEUR RÉ-ÉDITÉ:

package quartz.spring.com.example; 

import java.util.HashMap; 
import java.util.Map; 

import javax.jms.ConnectionFactory; 
import javax.jms.Destination; 
import javax.jms.JMSException; 
import javax.jms.Message; 
import javax.jms.Queue; 
import javax.jms.Session; 

import org.springframework.jms.core.MessageCreator; 
import org.springframework.jms.core.JmsTemplate; 
import org.springframework.jms.core.JmsTemplate102; 
import org.springframework.jms.core.MessagePostProcessor; 

public class JmsQueueSender { 

    private JmsTemplate jmsTemplate; 
    private Destination destination; 

    public void setConnectionFactory(ConnectionFactory cf) { 
        this.jmsTemplate = new JmsTemplate102(cf, false); 
    } 

    public void setQueue(Queue queue) { 
        this.destination = queue; 
    } 

    public void simpleSend() { 
        this.jmsTemplate.send(this.destination, new MessageCreator() { 
            public Message createMessage(Session session) throws JMSException { 
              return session.createTextMessage("hello queue world"); 
            } 
        }); 
    } 

    public void sendWithConversion() { 
        Map map = new HashMap(); 
        map.put("Name", "Mark"); 
        map.put("Age", new Integer(47)); 
        jmsTemplate.convertAndSend("ReceiverQueue", map, new MessagePostProcessor() { 
            public Message postProcessMessage(Message message) throws JMSException { 
                message.setIntProperty("AccountID", 1234); 
                message.setJMSCorrelationID("123-00001"); 
                return message; 
            } 
        }); 
    } 
} 

RÉCEPTEUR :

package quartz.spring.com.example;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class ExampleListener implements MessageListener {

    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                System.out.println(((TextMessage) message).getText());
            }
            catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
        }
        else {
            throw new IllegalArgumentException("Message must be of type TextMessage");
        }
    }
}

Ré-édité applicationcontext.xml

      <?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd"> 

    <bean id="sender" class="quartz.spring.com.example.JmsQueueSender" 
        init-method="sendWithConversion" /> 
    <bean id="receiver" class="quartz.spring.com.example.ExampleListener"> 
    </bean>  

    <bean id="jmsContainer" 
        class="org.springframework.jms.listener.DefaultMessageListenerContainer"> 
        <property name="connectionFactory" ref="connectionFactory" /> 
        <property name="destination" ref="queueDestination" /> 
        <property name="messageListener" ref="messageListener" /> 
    </bean> 

    <!-- Queue configuration --> 
    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"> 
        <property name="environment"> 
            <props> 
                <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop> 
                <prop key="java.naming.provider.url">jnp://localhost:1099</prop> 
                <prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop> 
                <prop key="java.naming.security.principal">admin</prop> 
                <prop key="java.naming.security.credentials">admin</prop> 
            </props> 
        </property> 
    </bean> 

    <bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> 
        <property name="jndiTemplate" ref="jndiTemplate" /> 
        <property name="jndiName" value="ConnectionFactory" /> 
    </bean> 

    <bean id="queueDestination" class="org.springframework.jndi.JndiObjectFactoryBean"> 
        <property name="jndiTemplate" ref="jndiTemplate" /> 
        <property name="jndiName"> 
            <value>queue/ReceiverQueue</value> 
        </property> 
    </bean> 
</beans> 

Je ne savais pas vraiment que la courbe d'apprentissage pour cela est si longue, je veux dire que l'idée est très simple:

  1. Envoyer un message au file d'attente de destination
  2. Recevoir un message de la file d'attente de destination

Pour recevoir des messages, procédez comme suit (le livre le dit aussi):

1 Locate a ConnectionFactory, typically using JNDI.
2 Use the ConnectionFactory to create a Connection.
3 Use the Connection to create a Session.
4 Locate a Destination, typically using JNDI.
5 Use the Session to create a MessageConsumer for that Destination.

Une fois que vous avez fait cela, les méthodes sur le MessageConsumer vous permet de interroger la destination des messages ou pour vous inscrire à une notification de message.

Quelqu'un peut-il me diriger vers la bonne direction, y a-t-il un tutoriel qui explique en détail comment recevoir un message de la file d'attente?J'ai le code d'envoi du message de travail, je ne l'ai pas posté ici car ce message est trop long. MODIFIER:

J'ai ajouté à mon service de destination de messagerie jboss.xml ce Mbean:

<mbean code="org.jboss.jms.server.destination.QueueService"
     name="jboss.messaging.destination:service=Queue,name=ReceiverQueue"
     xmbean-dd="xmdesc/Queue-xmbean.xml">
     <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
     <depends>jboss.messaging:service=PostOffice</depends>
   </mbean>
Author: Mark B, 2010-03-22

1 answers

De votre exemple d'URL Spring que vous avez oublié:

<!-- and this is the message listener container -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="destination" ref="destination"/>
    <property name="messageListener" ref="messageListener" />
</bean>

Qui relie la file d'attente à l'écouteur:)

MODIFIER

Vous avez écrit dans les commentaires:

but still I'm getting this error : org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sender' defined in ServletContext resource [/WEB-INF/conf/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException

Et

How does Example listener knows which queue to listen to anyways, I didn't specify to it, didn't know how

Le premier problème est que je pense qu'une NullPointerException sur la ligne jmsTemplate.convertAndSend. Votre jmsTemplate n'a pas été initialisé.

Je crois que c'est parce que la méthode init n'est pas convertAndSend. Vous ne devriez pas avoir besoin d'une méthode init du tout. Vous devez définir les propriétés dans le applicationcontext.xml, à propos de si:

<bean id="sender" class="quartz.spring.com.example.JmsQueueSender"> 
  <property name="queue" value="theNameOfYourQueue"> <!-- or in stead of value ref to a String which contains the shared queue name -->
  <property name="connectionFactory" ref="connectionFactory"/>
</bean>

Qui devrait corriger les erreurs lors de l'envoi (BTW pourquoi utilisez-vous JMSTemplate102 et non JMSTemplate?).

L'autre question, vous configurez les noms de file d'attente en définissant des propriétés sur les beans. Dans ce cas, vous semblez écouter la file d'attente/ReceiverQueue de queueDestination car votre jmsContainer est configuré pour gérer les appels sur cette file d'attente par votre auditeur.

Où le diable a fait est le bean messageListener défini dans le applicationcontext.xml?

Si vous utilisez ref="someName", quelque part, il convient également de <bean name="someName" quelque part.

MODIFIER

Voir Également cet exemple, qui semble avoir un peu plus de code de configuration expliquer. le pubSubDomain est faux signifie que c'est point à point:)

 3
Author: extraneon, 2010-03-22 15:13:11