Using MDB-Topic as cluster-wide event listener
Yesterday I had the problem that I need to send a broadcast message in an application which should be processed by every running node. This message should be the initiator to clear a local cache on each node. So I had the idea to use JMS as API using a topic and every node will listen on that topic. I am using this on JBoss 5.1.0.GA.
First of all the need to define an Topic. This could be done in an own service.xml, which is located directly in the deploy directory or (my preferred way) in the ear.
?Download topic-service.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | < ?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="org.jboss.jms.server.destination.TopicService" name="jboss.messaging.destination:service=Topic,name=MyEvents" xmbean-dd="xmdesc/Topic-xmbean.xml"> <depends optional-attribute-name="ServerPeer"> jboss.messaging:service=ServerPeer </depends> <depends> jboss.messaging:service=PostOffice</depends> <attribute name="Clustered">true</attribute> </mbean> </server> |
Especially the attribute “Clustered” is important. Otherwise you would only have a local topic and not a cluster-wide.
Next we have to define our listener:
?Download ClusterEventsListener.java
1 2 3 4 5 6 7 8 9 10 11 12 | @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "topic/MyEvents") }, messageListenerInterface = MessageListener.class) @Depends(value = { "jboss.messaging:service=PostOffice", "jboss.messaging.destination:name=MyEvents,service=Topic" }) public class ClusterEventsListener implements MessageListener { public void onMessage(Message message) { //do some stuff System.out.println("received an event"); } } |
That’s all, now you can easily send some events using standard JMS commands, for example:
?Download SendEventImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | @Stateless public class SendEventImpl implements SendEvent { @Resource(mappedName = "topic/MyEvents") private Topic eventTopic; @Resource(mappedName = "ConnectionFactory") private TopicConnectionFactory eventQueueFactory; public void sendEvent() { try { TopicConnection cnn = null; TopicSession sess = null; TopicPublisher publisher = null; try { cnn = eventQueueFactory.createTopicConnection(); sess = cnn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE); publisher = sess.createPublisher(eventTopic); TextMessage message = sess.createTextMessage("hello world"); publisher.send(message); } finally { try { if (publisher != null) publisher.close(); } catch (Throwable e) { log.error("closing sender", e); } try { if (sess != null) sess.close(); } catch (Throwable e) { log.error("closing session", e); } try { if (cnn != null) cnn.close(); } catch (Throwable e) { log.error("closing connection", e); } } } catch (JMSException e) { throw new RuntimeException(e); } } } |