【问题标题】:JMS messaging implementationJMS 消息传递实现
【发布时间】:2010-03-22 23:13:11
【问题描述】:

我一直在为更有经验的人处理这个“简单”的任务,我被困了 2 天,现在需要帮助。我现在已经改变了无数次,最后我偶然发现了this spring JMS tutorial

我想做什么,发送消息并接收它。我也一直在阅读this book 第 8 章关于消息传递的内容。它很好地解释了 2 种消息传递类型,publish-and-subscribe 类型有一个很好的例子,但现在 point-to-point 消息传递的例子(这是我需要的一个)。

我可以自己向队列发送消息,但不知道如何接收这就是我尝试这个春季教程的原因,这是我到目前为止所得到的:

重新编辑的发件人:

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; 
            } 
        }); 
    } 
} 

接收者:

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");
        }
    }
}

重新编辑 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> 

真的不知道学习曲线这么长,我的意思是这个想法很简单:

  1. 向目标队列发送消息
  2. 从目标队列接收消息

要接收消息,请执行以下操作(书上也是这么说的):

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.

完成此操作后, MessageConsumer 使您能够 查询消息的目的地或 注册消息通知。

谁能指引我正确的方向,有没有详细解释如何从队列接收消息的教程?我有有效的发送消息代码,没有在这里发布,因为这篇文章太长了是。 编辑:

我将这个 Mbean 添加到我的 jboss 消息传递destination-service.xml 中:

<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>

【问题讨论】:

  • 我以为你在做 PTP 消息传递,但这是你在做的异步消息传递。
  • 嗯,我想实现点对点,但显然我没有到达那里
  • 你现在似乎有一个叫做receiver的bean和一个叫做messageListener的bean,两个都是监听器:)
  • 而且 Sender 中的队列名称 testQueue 似乎不是您正在监听的那个。
  • @extraneon 好的,我更新了我的代码 appcontext.xml 和发件人.. 但我仍然收到此错误: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 示例侦听器如何知道无论如何要听哪个队列,我没有'没有指定,不知道怎么做。

标签: java spring jboss jms


【解决方案1】:

从您忘记的 Spring 示例 URL 中:

<!-- 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>

将队列连接到侦听器:)

编辑

您在 cmets 中写道:

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

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

第一个问题是我认为jmsTemplate.convertAndSend 上出现了nullPointerException。您的 jmsTemplate 尚未初始化。

我相信这是因为 init 方法不是 convertAndSend。您根本不需要 init 方法。你应该在applicationcontext.xml中设置属性,大概是这样:

<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>

这应该可以解决发送时的错误(顺便说一句,你为什么使用 JMSTemplate102 而不是 JMSTemplate?)。

另一个问题,您配置通过设置bean 的属性来配置队列名称。在这种情况下,您似乎正在侦听 queueDestination queue/ReceiverQueue,因为您的 jmsContainer 被配置为处理侦听器对该队列的调用。

到底是在 applicationcontext.xml 中定义的 messageListener bean 在哪里?

如果您在某处使用ref="someName",则在某处也应该使用&lt;bean name="someName"

编辑

还可以看看this example,它似乎有更多的配置代码 解释。 pubSubDomain 为 false 表示它是点对点的 :)

【讨论】:

  • @extraneon 这不仅仅是我忘记的东西,显然还有更多内容要添加,我更新了我的发件人、appcontext 并将 mbean 添加到目标服务
猜你喜欢
  • 2011-02-26
  • 2011-01-29
  • 2016-02-23
  • 2019-07-18
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 2017-01-23
  • 1970-01-01
相关资源
最近更新 更多