2010-03-22 140 views
5

我一直在为更多经验丰富的人员努力完成这个“简单”任务,现在我需要帮助才能坚持2天。我已经把事情变成了几十亿次,最后我偶然发现了this spring JMS tutorialJMS消息传递实现

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

我能够将消息发送到队列我自己,但没有一个知道如何接受这就是为什么我在这里这个春天教程尝试就是我这么远:

重新编辑SENDER:

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

RECEIVER:

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方法,使您无论是 查询的消息或目的地 为消息通知注册。

有人可以请直接与我朝正确的方向,是有其解释详细介绍了如何从队列中接收消息的教程吗?我有工作发送短信代码,并没有张贴在这里,因为这个帖子太就这样。 编辑:

我添加到我的jboss消息目标服务。XML此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> 
+0

我以为你在做PTP消息传递,但这是你正在做的异步消息传递。 – 2010-03-22 13:45:07

+0

嗯,我想实现点到点,但显然我没有到达那里 – 2010-03-22 13:52:37

+0

你现在好像有一个名为接收器的bean和一个名为messageListener的bean,都是监听器:) – extraneon 2010-03-22 14:21:38

回答

3

从您忘记您的春季例如网址:

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

哪个队列连接到听者:)

编辑

你在写评论:

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的?)。

另一个问题,你配置队列名称通过设置豆的属性。在这种情况下,由于您的jmsContainer配置为由您的侦听器处理该队列上的调用,因此您似乎正在侦听queueDestination队列/ ReceiverQueue。

heck是在applicationcontext.xml中定义的messageListener bean?

如果您在某处使用ref="someName",某处还应该有<bean name="someName"

编辑

也看看this example这似乎有一点更多的配置代码 解释。 pubSubDomain为false意味着它是点对点:)

+0

@extraneon这不仅是我忘记的东西,显然还有一些要添加的内容,我更新了我的发件人,appcontext并将mbean添加到目标服务 – 2010-03-22 13:57:29