Spring JMS

1,772 views

Published on

Spring with Java Messaging Service

Published in: Technology, Business
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,772
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
57
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Spring JMS

  1. 1. Spring way of messaging
  2. 2. JMS Basics The application hands the message to be send to amessage broker. The message broker ensures the message delivery tothe specified destination. JMS messages are addressed with a destination. Destination are of two types: queues (point-to-pointmodel) and topics (publish-subscribe model).
  3. 3. Point-to-point & Publish-subscribe Point-to-Point: Each message has exactly one sender and one receiver. When a receiver asks for the next message in the queue, themessage is removed from the queue and delivered to thereceiver. Each message in a message queue is delivered to only onereceiver. Publish-Subscribe: Messages are sent to a topic which is listened by multiplereceivers. All subscribers to a topic will receive a copy of the message.
  4. 4. Benefits of JMS The client doesn’t need to wait around for it to beprocessed or even delivered. JMS messages are data-centric and the client isn’t fixedto a specific method signature. JMS clients are unaware of service location and onlyknow the queue or topic through which the messageswill be sent. JMS clients are assured of guaranteed message deliveryeven if the service is unavailable when a message issent and is stored until the service is available again.
  5. 5. Setting up ActiveMQ in Spring Add the incubator-activemq-4.1.0.jar to the application’sclasspath to access ActiveMQ’s API. ActiveMQConnectionFactory is the JMS connection factoryfor ActiveMQ, to send messages through the messagebroker. <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL"value="tcp://localhost:61616"/> </bean> The brokerURL property tells the connection factory wherethe message broker is located
  6. 6. Declaring an ActiveMQ messagedestination A message destination is declared either a queue or topic, forpassing on the messages. ActiveMQ queue Declaration: <bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg index="0" value="rantz.marketing.queue"/> </bean> ActiveMQ topic Declaration: <bean id="rantzDestination" class="org.apache.activemq.command.ActiveMQTopic"> <constructor-arg index="0" value="rantz.marketing.topic"/> </bean>
  7. 7. Conventional JMS Sender ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616"); try { conn = cf.createConnection(); session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); Destination destination = new ActiveMQQueue("myQueue"); MessageProducer producer = session.createProducer(destination); TextMessage message = session.createTextMessage(); message.setText("Hello world!"); producer.send(message); } catch (JMSException e) { // handle Message}
  8. 8. Conventional JMS Receiver ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616"); try { conn = cf.createConnection(); session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); Destination destination = new ActiveMQQueue("myQueue"); MessageConsumer consumer = session.createConsumer(destination); conn.start(); Message message = consumer.receive(); TextMessage textMessage = (TextMessage) message; System.out.println("GOT A MESSAGE: " + textMessage.getText()); } catch (JMSException e) { // handle Message} } finally { … }
  9. 9. JMS Template JMS Template handles creating a connection,obtaining a session, and the actual sending andreceiving of messages. It handles any clumsy JMSException that may bethrown along the way. When JMSException is thrown, JmsTemplate willcatch it and rethrow it as one of the uncheckedsubclasses of JmsException inorg.springframework.jms.* package.
  10. 10. Wiring the JMS Template JmsTemplate needs to get connections to the messagebroker, and hence sets a connectionFactory propertywith a bean that implements JMS’s ConnectionFactoryinterface. <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory"ref="connectionFactory" /> </bean>
  11. 11. Sending Messages with JMS Templates public void sendMotoristInfo(final Motorist motorist) { jmsTemplate.send( destination, new MessageCreator() { public Message createMessage(Session session) throws JMSException { MapMessage message = session.createMapMessage(); message.setString("Name", motorist.getName()); return message; } }); } private JmsTemplate jmsTemplate; // Injected private Destination destination; // Injected
  12. 12. Setting a default destination <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="defaultDestination" ref="rantzDestination" /> </bean> The call to JmsTemplate’s send() method can be simplified slightly byremoving the first parameter: jmsTemplate.send( new MessageCreator() { … }); JmsTemplate assumes that the message sent to the default destinationwhen the send() method only takes a MessageCreator.
  13. 13. Consuming messages public SpammedMotorist receiveSpammedMotorist() { MapMessage message = (MapMessage) jmsTemplate.receive(); SpammedMotorist motorist = new SpammedMotorist(); try { motorist.setFirstName(message.getString("firstName")); motorist.setLastName(message.getString("lastName")); motorist.setEmail(message.getString("email")); } catch (JMSException e) { throw JmsUtils.convertJmsAccessException(e); } return motorist; } private JmsTemplate jmsTemplate; //injected
  14. 14. Consuming messages: Timeout JmsTemplate’s receive() method is synchronous, blocking the calluntil a message appears on the destination. The receiveTimeout property can be used to configureJmsTemplate to time out on receives after specified time interval. <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="defaultDestination" ref="rantzDestination" /> <property name="receiveTimeout" value="60000" /> </bean>
  15. 15. Converting messages Spring supports message conversion through itsMessageConverter interface: public interface MessageConverter { public Message toMessage(Object object, Session session); public Object fromMessage(Message message); } For sending messages, the toMessage() method converts anobject to a Message. On the receiving end, the fromMessage() method convertsan incoming Message into an Object.
  16. 16. Implementation of MessageConverter public class MotoristMessageConverter implements MessageConverter { public Object fromMessage(Message message) throws JMSException, MessageConversionException { if(!(message instanceof MapMessage)) { throw new MessageConversionException("Message isnt a MapMessage"); } MapMessage mapMessage = (MapMessage) message; SpammedMotorist motorist = new SpammedMotorist(); motorist.setFirstName(mapMessage.getString("firstName")); return motorist; } public Message toMessage(Object object, Session session) throws JMSException,MessageConversionException { if(!(object instanceof Motorist)) { throw new MessageConversionException("Object isnt a Motorist"); } Motorist motorist = (Motorist) object; MapMessage message = session.createMapMessage(); message.setString("firstName", motorist.getFirstName()); return message; } }
  17. 17. Sending/Receiving converted messages The convertAndSend() method of JmsTemplate can besimply called instead of explicitly calling the toMessage()method before sending a message. JmsTemplate’s convertAndSend() method automaticallycalls the toMessage() method before sending the messageto the destination. The receiveAndConvert() method of JmsTemplate can besimply called instead of explicitly calling the fromMessage()to convert the message returned from JmsTemplate’sreceive(). Unless specified, both the convertAndSend() andreceiveAndConvert(), send and receive messagesrespectively from the default destination.
  18. 18. Wiring a message converter <bean id="motoristConverter" class="com.roadrantz.marketing.MotoristMessageConverter" / <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="defaultDestination" ref="rantzDestination" /> <property name="messageConverter" ref="motoristConverter" /> </bean>
  19. 19. Spring JMS Gateway Support public class RantzMarketingGatewayImpl extends JmsGatewaySupport implements RantzMarketingGateway { public void sendMotoristInfo(final Motorist motorist) { getJmsTemplate().send("rantz.marketing.queue", new MessageCreator() { public Message createMessage(Session session) throws JMSException { MapMessage message = session.createMapMessage(); message.setString("firstName", motorist.getFirstName()); return message; } }); } }
  20. 20. Spring JMS Gateway Support A JmsTemplate object can be directly injected into thejmsTemplate property, or by wiring the connection factoryinto the connectionFactory property. JmsGatewaySupport automatically creates a JmsTemplateobject based on the injected connection factory bean wiredinto the connectionFactory property. Shortcomings to wiring connection factory are as follows: Can only specify a default destination on a JmsTemplate. Can only wire a message converter into a JmsTemplate.
  21. 21. Spring Message Driven Beans public class MarketingMdp implements MessageListener { public void onMessage(Message message) { MapMessage mapMessage = (MapMessage) message; try { SpammedMotorist motorist = new SpammedMotorist(); motorist.setFirstName(mapMessage.getString("firstName")); motorist.setLastName(mapMessage.getString("lastName")); motorist.setEmail(mapMessage.getString("email")); processMotoristInfo(motorist); } catch (JMSException e) { // handle—somehow } } private void processMotoristInfo(SpammedMotorist motorist) { … } } <bean id="rantzMdp“ class="com.roadrantz.marketing.MarketingMdp" />
  22. 22. Message Listener Container A message listener container watches a JMS destination formessages and retrieves the messages on arrival. The retrieved messages are passed on to a MessageListenerimplementation by calling the onMessage() method. onMessage() method is to receive and translate the message. SimpleMessageListenerContainer is the simplest of the messagelistener containers, configured as follows: <bean class="org.springframework.jms.listener. ➥ SimpleMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="rantzDestination" /> <property name="messageListener" ref="rantzMdp" /> </bean>
  23. 23. Spring Message Listener ContainersContainer classorg.springframework.jms.listener.*OperationSimpleMessageListenerContainer This is the simplest message listenercontainer. It works with a fixed number ofJMS sessions and does not supporttransactions.DefaultMessageListenerContainer This message listener container builds uponSimpleMessageListenerContainer byadding support for transactionsserversession.ServerSessionMessageListenerContainerThis is the most powerful of the messagelistener containers. LikeDefaultMessageListenerContainer, itsupports transactions. However it is uniquein that it allows for dynamic managementof JMS sessions.
  24. 24. Transactional MDPs DefaultMessageListenerContainer adds transaction support to theSimpleMessageListenerContainer. <bean class="org.springframework.jms.listener.➥ DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="rantzDestination" /> <property name="messageListener" ref="rantzMdp" /> <property name="transactionManager" ref="jmsTransactionManager" /> </bean> The transactionManager property is wired with a reference to a transaction manager suchas JmsTransactionManager: <bean id="jmsTransactionManager“ class="org.springframework.jms.connection. ➥ JmsTransactionManager"> <property name="connectionFactory" ref="connectionFactory" /> </bean> The transactionManager property of DefaultMessageListenerContainer is optional.
  25. 25. Pure POJO MDP The message listener container calls the onMessage() methodwhen a message arrives, when its messageListener propertybeing wired with an implementation of MessageListener. <bean class="org.springframework.jms.listener. ➥ SimpleMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <property name="destination" ref="rantzDestination" /> <property name="messageListener" ref="purePojoMdp" /> </bean>
  26. 26. MessageListenerAdapter MessageListenerAdapter is a MessageListener that delegates to a bean andmethod. By default, MessageListenerAdapter calls a handleMessage() methodwhen a message arrives. <bean id="purePojoMdp“class="org.springframework.jms.listener.adapter. ➥ MessageListenerAdapter"> <property name="delegate" ref="rantzMdp" /> <property name="defaultListenerMethod“ value="processMotoristInfo" /> </bean> The MessageListenerAdapter above calls the processMotoristInfo()method (as it’s the defaultListenerMethod) on the rantzMdp bean when amessage arrives on the destination. When MessageListenerAdapter receives a message, it considers themessage type and the value of the defaultListenerMethod and tries to findan appropriate listener method signature to invoke.
  27. 27. Mapping of JMS Message to MDPMessage type Method parameterTextMessage String or TextMessageMapMessage java.util.Map or MapMessageBytesMessage byte[] or BytesMessageObjectMessage java.io.Serializable or ObjectMessage The listener method can be written to take eitherthe original JMS message or a simpler type.
  28. 28. Converting MDP messages Spring message converters are used to translate messages to andfrom domain-specific Java types. MessageListenerAdapter has a messageConverter property to setthe corresponding message converter. <bean id="purePojoMdp“ class="org.springframework.jms.listener.adapter. ➥ MessageListenerAdapter"> <property name="delegate" ref="rantzMdp" /> <property name="defaultListenerMethod“value="processMotoristInfo" /> <property name="messageConverter" ref="motoristConverter" /> </bean>
  29. 29. Lingo Lingo is a Spring-based remoting option that bridgesthe gap between RPC and asynchronous messaging. Lingo provides a service exporter to export beanfunctionality as a Lingo service and a clientside proxyto transparently wire a reference to a remote Lingoservice on the calling side. Lingo remoting carries information over a JMS queueor topic, making the service call held in thequeue/topic until the service is available again.
  30. 30. Exporting Lingo Service Lingo provides JmsServiceExporter, a service exporter, wereservices are made available through JMS. The service implementation implements serviceInterface and is apure POJO wired into a MessageListenerAdapter to be used asmessage-driven POJO. <bean id="server" class="org.logicblaze.lingo.jms.JmsServiceExporter"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="destination" /> <property name="service" ref="rantzMdp" /> <property name="serviceInterface" value="com.roadrantz.marketing.MarketingService" /> </bean>
  31. 31. Lingo JMS Proxy Lingo provides JmsProxyFactoryBean, a proxy factory bean thatproduces proxies to remote Lingo-exported services. <bean id="marketing" class="org.logicblaze.lingo.jms.JmsProxyFactoryBean"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="destination" /> <property name="serviceInterface" value="com.roadrantz.marketing.MarketingService" /> </bean> Invoking a Lingo-exported service is no different from invoking anRMI service, a web service, or even a method on another bean.

×