Upload
bruce-snyder
View
7.387
Download
0
Embed Size (px)
DESCRIPTION
Citation preview
Enterprise Messaging With Spring JMS
Bruce Snyder, Senior Software Engineer, SpringSource
Friday, July 8, 2011
Agenda
• Very brief introduction to JMS • Synchronous JMS With Spring • Asynchronous JMS With Spring
2
Friday, July 8, 2011
What is JMS?
• JMS is:– An API for client-side communications with a JMS provider – Included in Java EE
• Also stand alone
• JMS is not: – A spec for a message broker implementation
3
Friday, July 8, 2011
JMS is an Abstraction
4
Friday, July 8, 2011
JMS Message
5
Friday, July 8, 2011
Point-to-Point Messaging
6
Friday, July 8, 2011
Publish/Subscribe Messaging
7
Friday, July 8, 2011
Typical JMS Use
8
Friday, July 8, 2011
Raw JMS
9
Friday, July 8, 2011
JMS With Spring
10
Friday, July 8, 2011
Managed vs. Non-Managed JMS
• Managed– JMS provider in a Java EE container – JMS resource pooling – Transaction support – Support for EJBs
• Non-Managed– Stand alone JMS provider – Manual setup of JMS resources – No guarantee of transactions
• Spring supports both environments
11
Friday, July 8, 2011
JMS With Spring
12
Friday, July 8, 2011
Spring JMS
• JMS Template– Send and receive messages
synchronously
• Message Listener Container – Receive messages asynchronously – Message-Driven POJOs (MDPs)
13
Friday, July 8, 2011
JmsTemplate
• browse() – Browse messages in a queue
• convertAndSend() – Send messages synchronously– Convert a Java object to a JMS message
• send() – Send a message synchronously using a MessageCreator
• receive() and receiveAndConvert() – Receive messages synchronously
• execute() – Provides access to callbacks for more complex scenarios
• receiveSelected() and receiveSelectedAndConvert()– Receive filtered messages synchronously
14
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
15
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616" /> <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg value="FOO.TEST" /> </bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" p:connectionFactory-ref="connectionFactory" p:defaultDestination-ref="destination" />
<bean id="messageProducer" class="org.bsnyder.spring.jms.producer.SimpleMessageProducer" p:jmsTemplate-ref="jmsTemplate" />
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
16
// Use the default destination jmsTemplate.convertAndSend("Hello World!");
// Use a different destinationjmsTemplate.convertAndSend(“TEST.BAR”, “Hello World!”);
// Use a different destinationString textMessage1 = (String) jmsTemplate.receiveAndConvert();
// Use a different destinationString textMessage2 = (String) jmsTemplate.receiveAndConvert(“TEST.BAR”);
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• Using send() with a MessageCreator
17
// Use a MessageCreator callback jmsTemplate.send(destination, new MessageCreator() { public Message createMessage(Session session) throws JMSException { TextMessage message = session.createTextMessage("Hello World!"); message.setIntProperty("someBusinessId", 22); return message; } });
// Receive raw JMS message TextMessage message = jmsTemplate.receive();
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• Using execute() and the SessionCallback
18
// Use a SessionCallbackjmsTemplate.execute(new SessionCallback() { public Object doInJms(Session session) throws JMSException { Queue queue = session.createQueue("MY.TEST.QUEUE"); MessageProducer producer = session.createProducer(queue); TextMessage message = session.createTextMessage("Hello World!"); producer.send(message); }});
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• Using execute() with the ProducerCallback
19
// Use a ProducerCallbackjmsTemplate.execute(new ProducerCallback() { public Object doInJms(Session session, MessageProducer producer) throws JMSException { TextMessage message = session.createTextMessage("Hello World!"); producer.send(destination, message); } return null; }});
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• Using JMS selector expression
20
// Using a selector expression String selectorExpression = “Timestamp BETWEEN 1218048453251 AND 1218048484330”;
jmsTemplate.receiveSelected(destination, selectorExpression);
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• Resolving JMS destinations – DynamicDestinationResolver (default)
• Look up destinations via a simple text name • Just calls session.createQueue() and session.createTopic()
– JndiDestinationResolver• Option to fall back to DynamicDestinationResolver
– BeanFactoryDestinationResolver• Look up beans that are javax.jms.Destination objects
21
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• MessageConverter – SimpleMessageConverter
• String <-> javax.jms.TextMessage• Map <-> javax.jms.MapMessage• Serializable object <-> javax.jms.ObjectMessage• byte[] <-> javax.jms.BytesMessage
22
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• JmsException hierarchy – Spring-specific unchecked exceptions – Corresponds to JMSException
• Advantage – Automatic clean up of JMS resources
23
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• Automatically participates in transactions • Provides support for:
– Java EE transactions – Spring local transactions (Spring JmsTransactionManager)– Spring global transactions (Spring JtaTransactionManager)
• XA requires an XA capable ConnectionFactory • XA resource enlistment is provider specific
24
Synchronous
Friday, July 8, 2011
The Spring JmsTemplate
• JmsTemplate does not provide resource pooling – Utilizes fresh connection/session for every invocation
• JMS resource pooling is responsibility of JMS provider
• Spring provides support – SingleConnectionFactory
• Returns same connection for all calls to createConnection()• Ignores all calls to close()
– CachingConnectionFactory• Extends SingleConnectionFactory to add Session caching and
automatic Connection recovery
25
Synchronous
Friday, July 8, 2011
Spring JMS
• JMS Template– Send and receive messages
synchronously
• Message Listener Container – Receive messages asynchronously – Message-Driven POJOs (MDPs)
26
Friday, July 8, 2011
Managed vs. Non-Managed JMS
• Non-Managed – JMS MessageConsumer registers a MessageListener – Manual lifecycle management
• Managed – EJB Message-Driven Beans
27
Asynchronous
Friday, July 8, 2011
JMS Transaction Support
• Non-Managed XA Transactions – A JMS MessageConsumer can use various acknowledge
modes • AUTO_ACKNOWLEDGE• CLIENT_ACKNOWLEDGE• DUPS_OK_ACKNOWLEDGE• local JMS transaction
– Standard JMS does not support asynchronous message consumption as part of a XA transaction
• Managed XA Transactions – Officially supported only by EJBs
28
Asynchronous
Friday, July 8, 2011
Spring Message-Driven POJOs
• DefaultMessageListenerContainer– Most commonly used container – Allows for dynamic scaling of queue consumers– Participates in external transactions
• SimpleMessageListenerContainer– Very basic – Static configuration– No external transaction support
29
Asynchronous
Friday, July 8, 2011
DefaultMessageListenerContainer
• Highly configurable – Dynamic scale up/down of consumers
• Threads managed by the container – Customizable via the Spring TaskExecutor
• Resource caching– Connection, Session, MessageConsumer – Default is to cache nothing so as work in Java EE
environments– See the setCacheLevel() method for more info
• Works in managed and non-managed environments• Supports XA message consumption
30
Asynchronous
Friday, July 8, 2011
SimpleMessageListenerContainer
• No dynamic scaling of consumers • No support for XA transactions
31
Asynchronous
Friday, July 8, 2011
Supported Types of Message Listeners
• javax.jms.MessageListener interface – Standard Java EE interface – Threading is up to you
• SessionAwareMessageListener interface– Spring-specific interface – Provides access to the Session object
• Very useful for request-response messaging• MessageListenerAdapter interface
– Spring-specific interface – Allows for type-specific message handling – No JMS dependencies whatsoever
32
Asynchronous
Friday, July 8, 2011
MessageListener
• Standard JMS MessageListener • Uses an onMessage() method
33
public class MyMessageListener implements MessageListener { private static Logger LOG = Logger.getLogger(MyMessageListener.class); public void onMessage(Message message) throws JMSException { try { LOG.info("Consumed message: “ + message); // Do some processing here } catch (JMSException e) { LOG.error(e.getMessage(), e); } }
Asynchronous
Friday, July 8, 2011
DefaultMessageListenerContainer
• XML configuration
34
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616" />
<bean id="messageListener" class="org.bsnyder.spring.jms.listener.SimpleMessageListener" />
<jms:listener-container concurrency="5-10"> <jms:listener destination="FOO.TEST" ref="messageListener"/> </jms:listener-container>
Asynchronous
Friday, July 8, 2011
DefaultMessageListenerContainer
• Use more than one listener
35
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616" />
<bean id="widgetListener" class="org.bsnyder.spring.jms.listener.WidgetMessageListener" />
<bean id="gadgetListener" class="org.bsnyder.spring.jms.listener.GadgetMessageListener" />
<jms:listener-container concurrency="5-10"> <jms:listener destination="PRODUCTS.WIDGETS" ref="widgetListener"/> <jms:listener destination="PRODUCTS.GADGETS" ref="gadgetListener"/> </jms:listener-container>
Asynchronous
Friday, July 8, 2011
SessionAwareMessageListener
• Provides access to the session• Uses an onMessage() method
36
public class MySessionAwareMessageListener implements SessionAwareMessageListener { private static Logger LOG = Logger.getLogger(MySessionAwareMessageListener.class); public void onMessage(Message message, Session session) throws JMSException { try { LOG.info("Consumed message: “ + ((TextMessage)message).getText()); // Send a reply message TextMessage newMessage = session.createTextMessage(“This is a test”); MessageProducer producer = session.createProducer(message.getJMSReplyTo()); LOG.info("Sending reply message "); producer.send(newMessage); } catch (JMSException e) { LOG.error(e.getMessage(), e); } }}
Asynchronous
Friday, July 8, 2011
DefaultMessageListenerContainer
• XML configuration
37
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" p:brokerURL="tcp://localhost:61616" />
<bean id="messageListener" class="org.bsnyder.spring.jms.listener.MySessionAwareMessageListener" />
<jms:listener-container concurrency="5-10"> <jms:listener destination="FOO.TEST" ref="messageListener"/> </jms:listener-container>
Asynchronous
Friday, July 8, 2011
MessageListenerAdapter
• Handles all message content types• No reply message is sent (void return)
38
public interface MessageDelegate { void processMessage(String text); void processMessage(Map map); void processMessage(byte[] bytes); void processMessage(Serializable obj); }
Asynchronous
Friday, July 8, 2011
MessageListenerAdapter
39
<bean id="messageDelegate" class="org.springframework.jms.listener.adapter.MessageListenerAdapter" p:defaultListenerMethod="processMessage"> <constructor-arg> <bean class="org.bsnyder.spring.jms.adapter.MessageDelegateImpl" /> </constructor-arg> <property name="messageConverter"> <null/> </property> </bean>
<jms:listener-container concurrency="5-10"> <jms:listener destination="FOO.TEST" ref="messageDelegate" /> </jms:listener-container>
Asynchronous
Friday, July 8, 2011
MessageListenerAdapter
• Handles all raw JMS message types• No reply message is sent (void return)
40
public interface MessageDelegate { void processMessage(TextMessage message); void processMessage(MapMessage message); void processMessage(BytesMessage message); void processMessage(ObjectMessage message); }
Asynchronous
Friday, July 8, 2011
MessageListenerAdapter
41
<bean id="messageDelegate2" class="org.springframework.jms.listener.adapter.MessageListenerAdapter" p:defaultListenerMethod="processMessage"> <constructor-arg> <bean class="org.bsnyder.spring.jms.adapter.MessageDelegate2Impl" /> </constructor-arg> <property name="messageConverter"> <null/> </property> </bean>
<jms:listener-container concurrency="5-10"> <jms:listener destination="FOO.TEST2" ref="messageDelegate2" /> </jms:listener-container>
Asynchronous
Friday, July 8, 2011
Local Transactions
42
Asynchronous
<bean id="messageDelegate" class="org.springframework.jms.listener.adapter.MessageListenerAdapter" p:defaultListenerMethod="processMessage"> <constructor-arg> <bean class="org.bsnyder.spring.jms.adapter.MessageDelegateImpl" /> </constructor-arg> <property name="messageConverter"> <null/> </property> </bean>
<jms:listener-container concurrency="5-10" acknowledge=”transacted”> <jms:listener destination="FOO.TEST" ref="messageDelegate" /> </jms:listener-container>
Friday, July 8, 2011
Global Transactions
43
Asynchronous
<bean id="activemqXaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory" p:brokerURL="tcp://localhost:61616" />
<bean id="atomikosConnectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="simpleTransaction"/> <property name="xaConnectionFactory" ref="activemqXaConnectionFactory"/> </bean>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.J2eeTransactionManager" /> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.J2eeUserTransaction" /> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" p:transactionManager-ref="atomikosTransactionManager" p:userTransaction-ref="atomikosUserTransaction"> </bean>...
Friday, July 8, 2011
Global Transactions
44
Asynchronous
...
<bean id="messageDelegate" class="org.springframework.jms.listener.adapter.MessageListenerAdapter" p:defaultListenerMethod="processMessage"> <constructor-arg> <bean class="org.bsnyder.spring.jms.adapter.MessageDelegateImpl" /> </constructor-arg> <property name="messageConverter"> <null/> </property> </bean>
<jms:listener-container concurrency="5-10" connection-factory="atomikosConnectionFactory" transaction-manager="transactionManager" acknowledge="transacted"> <jms:listener destination="FOO.TEST" ref="messageDelegate" /> </jms:listener-container>
Friday, July 8, 2011
Q&A
Thank You!
Friday, July 8, 2011