I am trying to get messages from a topic - using JMSTemplate.receive - no messages come back even though I see them by going to the activeMQ admin console? How would I do it if jmsTemplate is not working?
I am trying to get messages from a topic - using JMSTemplate.receive - no messages come back even though I see them by going to the activeMQ admin console? How would I do it if jmsTemplate is not working?
I just ran a test and it worked fine for me.
Are you using a timeout? Is the receive() active when you publish? Messages in topics are only received by active consumers by default. Consider using a message listener container and a durable subscription (or use a queue).
Gary P. Russell
Spring Integration Team
SpringSource, a division of VMware
using the MessageListener is not ideal fro my environment bec. I only want to get the messages when the user requests it - otherwise I don't need it - so that's wh I need it working synchronously.
Do Topics work Synchronously in the Spring environment?
Here is how I instantiate the jmsTemplate, sender & receiver in the applicationcontext.xml
<bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFacto ry">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="testTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="testNotifications" />
</bean>
<bean id="jmsSender" class="com.myJmsSender">
<property name="jmsTemplate">
<ref bean="jmsTemplate" />
</property>
</bean>
<bean id="jmsReceiver" class="com.myJmsReceiver">
<property name="jmsTemplate">
<ref bean="jmsTemplate" />
</property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" >
<property name="connectionFactory">
<ref bean="activeMQConnectionFactory" />
</property>
<property name="defaultDestination" ref="testTopic"></property>
</bean>
Yes, like I said, I just tested it and it worked fine for me. I had a jmsTemplate (similar configuration to yours) with a thread blocked in its receive() method, published a message to the topic and the template.receive() returned the message.Do Topics work Synchronously in the Spring environment?
You can't publish the message and then call receive(); that's not how JMS topics work (regardless of Spring).
Gary P. Russell
Spring Integration Team
SpringSource, a division of VMware
Heres my jmsReceiver class, do I have to run it in a separate thread when I call JMSMessageReceiver .getMessages
public class JMSMessageReceiver {
protected final Log logger = LogFactory.getLog(JMSMessagePublisher.class);
private JmsTemplate jmsTemplate;
public JmsTemplate getjmsTemplate() {
return jmsTemplate;
}
public void setjmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public List<String> getMessages() {
List<String> messages = new ArrayList<String>();
Message msg = null;
while((msg = jmsTemplate.receive()) != null){
try {
TextMessage textMessage = (TextMessage) msg;
if (msg != null) {
messages.add(textMessage.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
return messages;
}
Please use [ code ] ... [ / code] tags (no spaces inside the brackets) when posting code and config.
Are you saying you get zero messages? I would expect you to get one, but there is definitely a window to lose messages this way (the consumer only lives during the receive() and, like I said, if you're not consuming during the publish you will lose messages.
For this application, you should probably drop down to some of the lower-level JmsTemplate APIs, such as...
Code:jmsTemplate.execute(new SessionCallback<Object>() { public Object doInJms(Session session) throws JMSException { MessageConsumer consumer = session.createConsumer(destination); while (true) { Message message = consumer.receive(); System.out.println(message); } } });
Gary P. Russell
Spring Integration Team
SpringSource, a division of VMware
Thanks alot for your help - I see what happens when my application gets deployed my jmsReceiver is not actually added as a topic consumer to ActiveMQ - it only gets registered in activeMQ at the first call to jmsTemplate.recieve -is there a way I can make sure it gets registered as a consumer on the application startup & not at the first time that I call receive?
You can use a durable subscription, BUT earlier you said you only wanted to receive Messages when a client asks for them. If that's not the case, registering a MessageListener container is definitely simpler.
Mark Fisher
Spring Integration Lead
SpringSource, a division of VMware
http://www.springsource.com
http://www.springsource.org/spring-integration
http://blog.springsource.com/main/author/markf
I ended up calling jmsTemplate.receive when the setJmsTemplate gets called on the JMSReceiver instantiation from the applicationContext.xml- this way it establishes a connection, so when messages do come in & when the client asks for it it will receive them - is that Ok?
On the MessageListener part how do I define a clientID on startup - when I set it to be durable?
I have seen posts which say do not use jmsTemplate.receive - is that true? if not how else should I be receiving messages synchronously?
As I said, receive() on a topic has issues, because the consumer only lives within its scope, when it returns there is no consumer; if someone publishes another message while you are processing the current one, you will miss it. Use execute() with the SessionCallback as I described above.
A Queue has no such issues. Is there some reason you need to use a topic rather than a queue for this? Do you have a requirement for multiple consumers to get a message?
The DefaultMessageListenerContainer has a clientId property - use setClientId().
Gary P. Russell
Spring Integration Team
SpringSource, a division of VMware