Spring JMS and ActiveMQ

19
Spring JMS with ActiveMQ ENTERPRISE MESSAGING

Transcript of Spring JMS and ActiveMQ

Page 1: Spring JMS and ActiveMQ

Spring JMS with ActiveMQENTERPRISE MESSAGING

Page 2: Spring JMS and ActiveMQ

Point-to-Point messaging

Page 3: Spring JMS and ActiveMQ

Queue’s Messages are delivered once and only once

◦ Kept in the queue when listener is not available◦ Sent to only one consumer when multiple are available

◦ Client acknowledge: wait for consumer to acknowledge before removing the message◦ Prefetch: multiple messages can be reserved for a consumer◦ Client timeout: if no ack or reject is received, queue will consider the consumer dead◦ Order not guaranteed with multiple queue’s

◦ Redelivery Policy◦ Set on client side◦ Retry after reject or use Dead Letter Queue

Page 4: Spring JMS and ActiveMQ

Selectors and Message Groups Selectors: Server side filtering

◦ Consumer can register a filter when connecting◦ Filtering will be done on the server◦ ActiveMQ supports selectors for JMS Headers and XPaths for XML Messages.

◦ No JSON

Message Groups: guaranteed ordering◦ If messages are correlated and relative order is important

◦ Add JMSXGroupID Header◦ All messages with the same groupId will be processed by the same consumer◦ Group mappings are kept in-memory on the server.

◦ Need to close groups properly◦ Could fail after a failover

Page 5: Spring JMS and ActiveMQ

Publish/Subscribe

Page 6: Spring JMS and ActiveMQ

Topics Write one message, will be received by all subscribers.

◦ Looser coupling between producer and consumer

When no subscribers are available, the message is not saved. Perfect for frontend – backend communication

◦ Backend post a teaserChange on a topic◦ All frontends showing the teaserList are subscribed on that topic

Not suited for server – to – server communication◦ Clustered service will receive each messages on every node

Page 7: Spring JMS and ActiveMQ

CompositeTopic a.k.a. VirtualTopic

Configure queue’s on the server which listen to a topic◦ Queue’s will buffer messages when subscribers are temporary offline◦ Messages will be received exactly once per Queue

◦ Queue per interested service◦ Decouple producer from consumer

◦ Unless queue’s are full :-)

<virtualDestinations> <compositeTopic name="redsys.publishing.publishfeed"> <forwardTo> <queue physicalName="redsys.moonriser.consumer.publishing.publishfeed"/> <queue physicalName="redsys.sitemanagement.consumer.publishing.publishfeed"/> <queue physicalName="redsys.publishingeventprocessor.consumer.publishing.publisheventfeed"/> </forwardTo> </compositeTopic>

Page 8: Spring JMS and ActiveMQ

ActiveMQ Storage configuration ActiveMQ will try to keep as much messages in memory as possible

Flushes to disk if one queue goes over 69% mem, or total mem usage goes over 80%

If disk storage gets over 80%, producers are first slowed down, then blocked

Selectors don’t work on flushed messages◦ Need to wait until other messages are consumed

Page 9: Spring JMS and ActiveMQ

JMS API

Page 10: Spring JMS and ActiveMQ

Spring JMS

Page 11: Spring JMS and ActiveMQ

Synchronous Messaging

// Use the default destination jmsTemplate.convertAndSend("Hello World!"); // Use a different destination jmsTemplate.convertAndSend(“TEST.BAR”, “Hello World!”); // Use a default destination String textMessage1 = (String) jmsTemplate.receiveAndConvert(); // Use a different destination String textMessage2 = (String) jmsTemplate.receiveAndConvert(“TEST.BAR”);

<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"

p:brokerURL="tcp://localhost:61616" /><bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"

p:connectionFactory-ref="connectionFactory"p:defaultDestination-ref="destination" />

Page 12: Spring JMS and ActiveMQ

MessageConvertors Maps java objects to message payloads

◦ ObjectMessage: java serialization◦ TextMessage: Jackson (JSON) or Jaxb (XML)

◦ Jackson inserts a JMS Header with the fully qualified classname by default◦ Can reuse Spring MVC ObjectMapper

Page 13: Spring JMS and ActiveMQ

Asynchronous Messaging

class MyMessageListener{public Result onMessage(Action a){ // input parameters will be unmarshalled if necessary (jackson/jaxb) // can also receive message headers as input parameters // non-void results will be sent to a response queue // auto-acknowledges if no exceptions thrown}

}

<bean id="connectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory"p:brokerURL="tcp://localhost:61616" />

<bean id="messageListener“ class="org.bsnyder.spring.jms.listener.MyMessageListener" /><jms:listener-container concurrency="5-10“container-type=“simple|default”>

<jms:listener destination="FOO.TEST" ref="messageListener“ method=“onMessage”/></jms:listener-container>

Page 14: Spring JMS and ActiveMQ

MessageListenerContainer options

• DefaultMessageListenerContainer

– Spring launches threads◦ while(…){ consumer.receive(); }

– Allows for dynamic scaling of queue consumers

– Participates in external transactions

• SimpleMessageListenerContainer

– consumer.setMessageListener(myListener);◦ JMS Provider manages ThreadPool

– No external transaction support

– Works better with MockRunner JMS

Page 15: Spring JMS and ActiveMQ

JMS Resource Pooling Managed ConnectionFactory

◦ JCA Resource Adapter in JBoss◦ ConnectionFactory bound in JNDI, no pooling in application

Unmanaged broker◦ Define pure ActiveMQConnectionFactory in Spring◦ Wrap in org.apache.activemq.pool.PooledConnectionFactory

◦ Also possible: Spring CachingConnectionFactory◦ Caches Sessions, too

Page 16: Spring JMS and ActiveMQ

ActiveMQ Client Configuration ActiveMQ namespace for spring configuration

Same configuration format as server

<connectionFactory xmlns="http://activemq.apache.org/schema/core" brokerURL="${activeMQ.brokerURL}" userName="${activeMQ.username}" password="${activeMQ.password}"> <redeliveryPolicyMap> <redeliveryPolicyMap> <defaultEntry> <redeliveryPolicy maximumRedeliveries="2"/> </defaultEntry> </redeliveryPolicyMap> </redeliveryPolicyMap> </connectionFactory>

Page 17: Spring JMS and ActiveMQ

Transactions JmsTransactionManager

◦ Injected in JmsTemplate and (Default)MessageListenerContainers◦ Transactional behaviour across JMS Senders/Receivers◦ All calls use the same JMS Session◦ Acknowledgements are only processed when whole session is committed

JtaTransactionManager◦ JMS Sessions are synchronized with XA Database transactions◦ Here be dragons…

Page 18: Spring JMS and ActiveMQ

Testing Unit tests

◦ Call message listeners directly◦ Mockito.mock(JmsTemplate.class)

Component Integration Tests◦ Use mockrunner-jms

System Tests◦ Use embedded ActiveMQ broker

<amq:broker persistent="false" useJmx="false" id="embeddedBroker"> <amq:transportConnectors> <amq:transportConnector uri="tcp://localhost:#{freePortSelector}"/> </amq:transportConnectors></amq:broker><amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost"/>

@Beanpublic JMSMockObjectFactory jmsMockObjectFactory() { return new JMSMockObjectFactory();}@Beanpublic ConnectionFactory connectionFactory() { return jmsMockObjectFactory().getMockConnectionFactory();}@Beanpublic JMSTestModule jmsTestModule() { return new JMSTestModule(jmsMockObjectFactory());}

Page 19: Spring JMS and ActiveMQ

Q&A