views:

2874

answers:

4

I am building a site that uses a simple AJAX Servlet to talk JMS (ActiveMQ) and when a message arrives from the topic to update the site.

I have Javascript that creates an XMLHttpRequest for data. The Servlet processes the Get Request and sends back JSON. However I have no idea how to connect my Servlet into my ActiveMQ Message Broker. It just sends back dummy data right now.

I am thinking the Servelt should implement the messagelistener. Then onMessage send data to the JavaScript page. But I'm not sure how to do this.

A: 

You probably need to get a JMS connection from JNDI, like this:

Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
    "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,
    "tcp://hostname:61616");
javax.naming.Context ctx = new InitialContext(props);
// lookup the connection factory
javax.jms.TopicConnectionFactory factory = 
    (javax.jms.TopicConnectionFactory)ctx.lookup("ConnectionFactory");
// create a new TopicConnection for pub/sub messaging
javax.jms.TopicConnection conn = factory.getTopicConnection();
// lookup an existing topic
javax.jms.Topic mytopic = (javax.jms.Topic)ctx.lookup("MyTopic");
// create a new TopicSession for the client
javax.jms.TopicSession session = 
    conn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE);
// create a new subscriber to receive messages
javax.jms.TopicSubscriber subscriber = session.createSubscriber(mytopic);
jodonnell
Okay... this is a good way to connect to my Topic, thanks. I already have code like this is another Java Client. But I want the Servelt to implement the messagelistener. Then onMessage send data to the Javascript page.
Bernie Perez
+1  A: 

The problem with having a servlet implement MessageListener is that servlets are synchronous and MessageListeners are asynchronous. Instead you should create some other object to act as the MessageListener and update some state somewhere (possibly a database or a JMX MBean or a Stateful Session EJB) when messages come in. Then the servlet can query that state to see if there's data to report back to the client, and your web page can periodically ping the servlet to ask for fresh data.

jodonnell
Thanks jodonnell.. I have never wrote a JMX MBean or Stateful Session EJB but after a quick google search I think this is the right path to look down. Thanks for the help.
Bernie Perez
+1  A: 

Have you tried reading the answers for this question which links to the ActiveMQ Ajax support. Basically ActiveMQ has native support for Ajax so you can use its JavaScript library to directly subscribe from an ActiveMQ topic.

Also see the ActiveMQ web samples which show how to do things like real time chat or real time stock portfolio screens using Ajax with ActiveMQ

James Strachan
+1  A: 

As James Strachan says - http://activemq.apache.org/ajax.html is an ideal out-of-the-box solution for your problem.

If you still want to create such solution manually you can just create JMS connection in your Ajax servlet (connection per request). Consider using Spring JMS template for that reason ( http://static.springsource.org/spring/docs/2.5.x/reference/jms.html ). Then just receive the message in the Servlet doGet/doPost method. Consider low timeout value for receiving in that case. Such solution will work for the Queues and durable Topics.

For non-durable Topics consider external message listener. Spring MessageListenerContainer is an excellent tool for that purpose:

<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer
   <property name="connectionFactory" ref="jmsFactory"/>
   <property name="destination" ref="myTopic" />
   <property name="messageListener" ref="lastTenUpdatesCache" />
</bean>

Bean lastTenUpdatesCache will be a singleton bean implementing MesssageListener. This bean would be responsible for caching last ten messages (just putting it into a java.util list). It will be injected into your Ajax servlet so in your doGet/doPost method you can ask it about last 10 messages sent to the topic.

Henryk Konsek