Java JMS 消息传递实现
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2492560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JMS messaging implementation
提问by Gandalf StormCrow
I've been struggling with this "simple" task for more expirienced people, I'm stuck for 2 days now need help. I've changed things arround like zillion times now, finally I stumbled upon this spring JMS tutorial.
对于更多有经验的人,我一直在为这项“简单”的任务而苦苦挣扎,我被困了 2 天,现在需要帮助。我现在已经改变了无数次,最后我偶然发现了这个春季 JMS 教程。
What I want to do, Send a message and receive it. I've been also reading this bookchapter 8 on messaging. 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).
我想做什么,发送消息并接收它。我也一直在阅读这本书关于消息传递的第 8 章。它真的很好地解释了 2 种类型的消息传递,并且有很好的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:
真的不知道这个学习曲线这么长,我的意思是这个想法很简单:
- Send message to the destination queue
- 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 上的方法使您可以查询 Destination 以获取消息或注册消息通知。
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 :
我将这个 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>
采纳答案by extraneon
From your Spring example URL you forgot:
从您忘记的 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>
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
. Your jmsTemplate has not been initialized.
第一个问题是我觉得一个nullPointerException就行了jmsTemplate.convertAndSend
。您的 jmsTemplate 尚未初始化。
I believe that is because the init-method is not convertAndSend. You should not need an init-method at all. You should set the properties in the applicationcontext.xml, about so:
我相信这是因为 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>
That should fix the errors while sending (BTW why do you use JMSTemplate102 and not JMSTemplate?).
这应该在发送时修复错误(顺便说一句,你为什么使用 JMSTemplate102 而不是 JMSTemplate?)。
The other question, you configurethe queue names by setting properties on the beans. 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.
另一个问题,您通过在 bean 上设置属性来配置队列名称。在这种情况下,您似乎正在侦听 queueDestination 队列/ReceiverQueue,因为您的 jmsContainer 被配置为处理您的侦听器对该队列的调用。
Where the heck did is the messageListener bean defined in the applicationcontext.xml?
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 examplewhich seems to have a bit more configuration code explained. the pubSubDomain is false means it's point-to-point :)
也看看这个例子,它似乎解释了更多的配置代码。pubSubDomain 为 false 意味着它是点对点的 :)