简体   繁体   English

JMS消息传递实现

[英]JMS messaging implementation

I've been struggling with this "simple" task for more expirienced people, I'm stuck for 2 days now need help. 对于那些经验丰富的人来说,我一直在为这个“简单”的任务而苦苦挣扎,我被困了2天,现在需要帮助。 I've changed things arround like zillion times now, finally I stumbled upon this spring JMS tutorial . 我现在已经改变了很多次,最后我偶然发现了这个春季JMS教程

What I want to do, Send a message and receive it. 我想做什么,发送消息并接收它。 I've been also reading this book chapter 8 on messaging. 我也一直在读这本关于消息传递的第8章。 It really nicely explains 2 type of messaging and there is nice example for publish-and-subscribe type but now example for point-to-point messaging( this is the one I need ). 它非常好地解释了两种类型的消息传递,并且publish-and-subscribe类型有一个很好的例子,但现在 point-to-point消息传递的例子( 这是我需要的 )。

I'm able to send message to the queue on my own, but don't have a clue how to receive thats why I tried with this spring tutorial here is what I've got so far : 我能够自己发送消息到队列,但是没有线索如何接收这些为什么我尝试使用这个春季教程这是我到目前为止所得到的:

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

re-edited applicationcontext.xml 重新编辑了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> 

Didn't really know that learning curve for this is so long, I mean the idea is very simple: 真的不知道这个学习曲线这么长,我的意思很简单:

  1. Send message to the destination queue 将消息发送到目标队列
  2. Receive message from the destination queue 从目标队列接收消息

To receive messages, you do the following (so does book say): 要接收消息,请执行以下操作 (书中也是如此):

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.

Once you've done this, methods on the MessageConsumer enable you to either query the Destination for messages or to register for message notification. 完成此操作后,MessageConsumer上的方法使您可以查询消息的目标或注册消息通知。

Can somebody please direct me towards right direction, is there a tutorial which explains in details how to receive message from the queue?I have the working send message code, didn't post it here because this post is too long as it is. 有人可以指导我朝着正确的方向发展,有没有一个教程详细解释如何从队列接收消息?我有工作发送消息代码,没有在这里发布,因为这篇文章太长了。 EDIT: 编辑:

I added to my jboss messaging destination-service.xml this Mbean : 我添加到我的jboss消息传递destination-service.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>

From your Spring example URL you forgot: 从你忘记的Spring示例网址:

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

Which connects the queue to the listener :) 这将队列连接到监听器:)

EDIT 编辑

You wrote in the comments: 你在评论中写道:

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

and

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

The first problem is I think a nullPointerException on the line jmsTemplate.convertAndSend . 第一个问题是我认为行jmsTemplate.convertAndSend上的jmsTemplate.convertAndSend Your jmsTemplate has not been initialized. 您的jmsTemplate尚未初始化。

I believe that is because the init-method is not convertAndSend. 我相信这是因为init-method不是convertAndSend。 You should not need an init-method at all. 您根本不需要init方法。 You should set the properties in the applicationcontext.xml, about so: 您应该在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>

That should fix the errors while sending (BTW why do you use JMSTemplate102 and not JMSTemplate?). 这应该在发送时修复错误(BTW为什么你使用JMSTemplate102而不是JMSTemplate?)。

The other question, you configure the queue names by setting properties on the beans. 另一个问题是,您可以通过在bean上设置属性来配置队列名称。 In this case you seem to be listening to the queueDestination queue/ReceiverQueue as your jmsContainer is configured to handle calls on that queue by your listener. 在这种情况下,您似乎正在侦听queueDestination队列/ ReceiverQueue,因为您的jmsContainer配置为处理侦听器对该队列的调用。

Where the heck did is the messageListener bean defined in the applicationcontext.xml? heck做的是applicationcontext.xml中定义的messageListener bean?

if you use ref="someName" somewhere there should also be a <bean name="someName" somewhere. 如果你在某处使用ref="someName"某处也应该有一个<bean name="someName"

EDIT 编辑

also have a look at this example which seems to have a bit more configuration code explained. 还看一下这个例子似乎有更多的配置代码解释。 the pubSubDomain is false means it's point-to-point :) pubSubDomain是false意味着它是点对点的:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM