2010-03-22 229 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