Presentation is loading. Please wait.

Presentation is loading. Please wait.

Java Messaging Service (JMS)

Similar presentations


Presentation on theme: "Java Messaging Service (JMS)"— Presentation transcript:

1 Java Messaging Service (JMS)

2 Goals Understand the basic concepts behind messaging and the Java Messaging Service (JMS) API Be able to define a destination using a JMS provider Be able to create a Java SE JMS producer and consumer publisher/subscriber sender/receiver v121128 JMS

3 Objectives Messaging Overview JMS Overview JMS Examples JMS API Detail

4 Messaging Communication between applications that exchange messages
Message forms a single, encapsulated, unit of communication between applications De-couples Producer and Consumer of the Message Message-Oriented-Middleware (MOM) category of application communication uses asynchronous message passing versus synchronous request/reply Advantages Producer and Consumer operate independently Messages can be persisted when consumer unavailable Messages can be retrieved even after producer is unavailable Qualities of service can be applied independent of clients Resource utilization can be applied by messaging provider v121128 JMS

5 MOM Architecture: Direct Connections
Producer/Consumer communicate over a TCP/IP connection Directly aware of state of link Producer cannot send messages when Consumer unavailable Consumer cannot receive messages when Producer unavailable Separate messages must be sent to separate clients Producer must be aware of what Consumer needs Security and QoS must be implemented by entirely within clients Good for realtime status networks v121128 JMS

6 MOM Architecture: Unicast Connections
Producer/Consumer communicate over a Uni-cast IP No concept of an end-to-end link Producer issues messages whether Consumer available or not MOM can add acknowledgment and queuing mechanisms Consumer cannot receive messages when Producer unavailable Producer only needs to send one message Consumers able to control when they receive Security and QoS must be implemented by entirely within clients Good for high performance publish/subscribe networks v121128 JMS

7 MOM Architecture: Broker-based
Producer/Consumer communicate to a separate broker No concept of an end-to-end link Producer issues messages whether Consumer available or not application can add acknowledgment mechanisms Consumer can receive messages when Producer unavailable Producer only needs to send one message Consumers able to control when they receive Security and QoS can be implemented within broker (thin client) Good for fully decoupling messaging complexity from clients v121128 JMS

8 MOM Architecture: Multi-Broker
Clients unaware of physical topology MOM Brokers link can honor time-of-day bandwidth constraints conserve bandwidth between sites by only sending what is needed point of site-to-site firewall control form alternate route routing v121128 JMS

9 Messaging Domains: Key Concepts
Producer produces message Destination target of produced message source of consumed message hosted by messaging provider Consumer consumes message v121128 JMS

10 Messaging Domains: Queuing
Sender a Producer sends message to a Queue with a specific target/intent Queue a Destination delivers message to, at most, one receiver Receiver a Consumer intended target of message v121128 JMS

11 Messaging Domains: Publish/Subscribe
Publisher a Producer publishes message to Topic with no specific target/intent Topic a Destination delivers message to active Subscribers Subscriber a Consumer has registered interest in a Topic durable subscription – lives beyond active client connection non-durable subscription – only exists during client connection v121128 JMS

12 Messaging Domains: Request/Reply
Requestor sends message to a destination appropriate to be available to a Replier receives reply for request Request Destination can be Topic or Queue Reply Destination can be Topic or Queue (typically a Queue) Replier receives request message from destination sends reply message to destination specified in request v121128 JMS

13 Messaging and Transactions
Each interaction with Destination can be made part of an existing ACID transaction Transaction #1 Requestor begins some work sends message to a destination appropriate to be available to a Replier Transaction #2 Replier receives request message from destination performs work sends reply message to destination specified in request Transaction #3 receives reply for request completes work v121128 JMS

14 JMS Background Vendor-neutral API to access enterprise messaging systems. Similar API role as JDBC JDBC is an API for accessing RDBMS JMS is an API for accessing enterprise messaging systems API between the application (JMS client) and the messaging provider (JMS provider); not between providers Similar non-role as JDBC JDBC won't cause data inserted into an HSQL instance to magically show up in an Oracle instance JMS won't cause a message sent to a JBossMQ destination to magically show up in a BEA instance's destination Its a Java API; no other languages addressed JMS providers accommodate other language clients using proprietary non-Java APIs v121128 JMS

15 Not Specified By JMS Security Load Balancing/Fault Tolerance
How are destinations secured Load Balancing/Fault Tolerance How do Topics scale to many publishers/subscribers How does a provider account for broker failure Error Notifications What happens when storage exhausted FIFO?, LIFO? retention Administration How are destinations and connection factories added Message Repository How is storage allocated Wire Protocol RMI? SOAP/HTTP? Other? Interoperability with non-Java clients v121128 JMS

16 JMS Examples Notifier Scheduler Publish/Subscribe
non-durable and durable subscriptions One-way Message traffic Scheduler Request/Reply request queue temporary response queue dead letter queue Transactional receive/send Load distribution v121128 JMS

17 JMS Notifier Example src/ |-- main | `-- java | `-- ejava
| |-- Publisher.java | `-- Subscriber.java `-- test |-- java | `-- ejava | `-- examples | `-- jmsnotifier | `-- JMSNotifierIT.java `-- resources |-- jmsNotifier-ant.xml |-- jmsNotifier.properties |-- jndi.properties `-- log4j.xml v121128 JMS

18 JMS Notifier: Topic Configuration
JBOSS_HOME/standalone/configuration/standalone.xml <subsystem xmlns="urn:jboss:domain:messaging:1.1"> <hornetq-server> ... <security-settings> <security-setting match="#"> <permission type="send" roles="publisher user"/> <permission type="consume" roles="subscriber user"/> <permission type="createDurableQueue" roles="subscriber user"/> <permission type="deleteDurableQueue" roles="user"/> <permission type="createNonDurableQueue" roles="subscriber user"/> <permission type="deleteNonDurableQueue" roles="user"/> </security-setting> </security-settings> <jms-destinations> <jms-topic name="jmsNotifier-testTopic1"> <entry name="java:jboss/exported/topic/ejava/examples/jmsNotifier/topic1“/> </jms-topic> v121128 JMS

19 JMS Notifier: jmsNotifier-ant.xml
publisher target(s) run Publisher <target name="publisher"> <java classname="ejava.examples.jmsnotifier.Publisher"> <classpath> <path refid="demo.classpath"/> </classpath> <arg value="-jndi.name.connFactory"/> <arg value="${jndi.name.connFactory}"/> <arg value="-jndi.name.destination"/> <arg value="${jndi.name.testTopic}"/> <arg value="-name"/> <arg value="${publisher.name}"/> <arg value="-sleep"/> <arg value="${publisher.sleep}"/> <arg value="-max"/> <arg value="${publisher.max}"/> </java> </target> v121128 JMS

20 JMS Notifier: jmsNotifier-ant.xml
subscriber target(s) run Subscriber <target name="subscriber"> <java classname="ejava.examples.jmsnotifier.Subscriber"> <classpath> <path refid="demo.classpath"/> </classpath> <arg value="-jndi.name.connFactory"/> <arg value="${jndi.name.connFactory}"/> <arg value="-jndi.name.destination"/> <arg value="${jndi.name.testTopic}"/> <arg value="-name"/> <arg value="${subscriber.name}"/> <arg value="-sleep"/> <arg value="${subscriber.sleep}"/> <arg value="-max"/> <arg value="${subscriber.max}"/> <arg value="-durable"/> <arg value="${subscriber.durable}"/> <arg value="-selector"/> <arg value="${subscriber.selector}"/> </java> </target> v121128 JMS

21 JMS Notifier: jmsNotifier.properties
m2.repo and jboss.home must be set by local environment M2_REPO=${m2.repo} JBOSS_HOME=${jboss.home} javaee.classpath=${M2_REPO}/javax/javaee/javaee/5/javaee-5.jar commons.logging.classpath=${M2_REPO}/commons-logging/commons- logging/1.0.4/commons-logging jar:${M2_REPO}/xerces/xercesImpl/2.6.2/xercesImpl jar log4j.classpath=${M2_REPO}/log4j/log4j/1.2.13/log4j jar jbossall-client.classpath=${JBOSS_HOME}/client/jbossall-client.jar jndi.name.connFactory=ConnectionFactory jndi.name.testTopic=topic/ejava/examples/jmsNotifier/topic1 publisher.name=Publisher0 publisher.sleep=1000 publisher.max=0 subscriber.name=Subscriber0 subscriber.sleep=0 subscriber.max=0 subscriber.durable=false subscriber.selector= v121128 JMS

22 Running Publisher jmsNotifier> mvn process-test-resources; ant -f target/test- classes/jmsNotifier-ant.xml init publisher ... init: [copy] Copying 1 file to /apps/jboss/server/default/deploy publisher: [java] Publisher args:-jndi.name.connFactory ConnectionFactory - jndi.name.destination topic/ejava/examples/jmsNotifier/topic1 -name Publisher0 -sleep max 0 [java] -publisher Publisher0 starting: maxCount=0, sleepTime1000 [java] -published message(1):ID: [java] -published message(2):ID: [java] -published message(3):ID: v121128 JMS

23 Running Subscriber0 Subscriber0 receives all messages
jmsNotifier> mvn process-test-resources; ant -f target/test- classes/jmsNotifier-ant.xml subscriber -emacs ... subscriber: -subscriber Subscriber0 starting:durable=false, selector= -Subscriber0 received message #5, msgId=ID: , body=count = 196 -Subscriber0 received message #6, msgId=ID: , body=count = 197 -Subscriber0 received message #7, msgId=ID: , body=count = 198 -Subscriber0 received message #8, msgId=ID: , body=count = 199 -Subscriber0 received message #9, msgId=ID: , body=count = 200 -Subscriber0 received message #10, msgId=ID: , body=count = 201 -Subscriber0 received message #11, msgId=ID: , body=count = 202 -Subscriber0 received message #12, msgId=ID: , body=count = 203 -Subscriber0 received message #13, msgId=ID: , body=count = 204 v121128 JMS

24 Running Subscriber0 Subscriber1 receives all messages matching selector jmsNotifier> ant -f target/test-classes/jmsNotifier-ant.xml subscriber1 -emacs ... subscriber1: -subscriber Subscriber1 starting:durable=false, selector=count- ((count/4)*4)=0 -Subscriber1 received message #1, msgId=ID: , body=count = 196 -Subscriber1 received message #2, msgId=ID: , body=count = 200 -Subscriber1 received message #3, msgId=ID: , body=count = 204 v121128 JMS

25 JMS Scheduler src/ |-- main | `-- java | `-- ejava | `-- examples
| |-- Requestor.java | `-- Worker.java `-- test |-- java | `-- ejava | `-- examples | `-- jmsscheduler | `-- JMSSchedulerIT.java `-- resources |-- jmsScheduler-ant.xml |-- jmsScheduler.properties |-- jndi.properties `-- log4j.xml v121128 JMS

26 JMS Scheduler: Queue Configuration
JBOSS_HOME/standalone/configuration/standalone.xml <subsystem xmlns="urn:jboss:domain:messaging:1.1"> <hornetq-server> ... </security-settings> <security-setting match="jms.queue.jmsScheduler-requestQueue"> <permission type="send" roles="requestor"/> <permission type="consume" roles="worker"/> <permission type="createNonDurableQueue" roles="requestor"/> </security-setting> <security-setting match="jms.queue.jmsScheduler-DLQ"> <permission type="send" roles="worker"/> <permission type="consume" roles="admin"/> <jms-destinations> <jms-queue name="jmsScheduler-requestQueue"> <entry name="java:jboss/exported/queue/ejava/examples/jmsScheduler/requestQueue"/> </jms-queue> <jms-queue name="jmsScheduler-DLQ"> <entry name="java:jboss/exported/queue/jmsScheduler/DLQ"/> v121128 JMS

27 JMS Scheduler: jmsScheduler-ant.xml
requestor target(s) run Requestor <target name="requestor"> <java classname="ejava.examples.jmsscheduler.Requestor"> <classpath> <path refid="demo.classpath"/> </classpath> <arg value="-jndi.name.connFactory"/> <arg value="${jndi.name.connFactory}"/> <arg value="-jndi.name.destination"/> <arg value="${jndi.name.testQueue}"/> <arg value="-jndi.name.DLQ"/> <arg value="${jndi.name.DLQ}"/> <arg value="-name"/> <arg value="${requestor.name}"/> <arg value="-sleep"/> <arg value="${requestor.sleep}"/> <arg value="-max"/> <arg value="${requestor.max}"/> </java> </target> v121128 JMS

28 JMS Scheduler: jmsScheduler-ant.xml
worker target(s) run Worker <target name="worker"> <java classname="ejava.examples.jmsscheduler.Worker"> <classpath> <path refid="demo.classpath"/> </classpath> <arg value="-jndi.name.connFactory"/> <arg value="${jndi.name.connFactory}"/> <arg value="-jndi.name.destination"/> <arg value="${jndi.name.testQueue}"/> <arg value="-jndi.name.DLQ"/> <arg value="${jndi.name.DLQ}"/> <arg value="-name"/> <arg value="${worker.name}"/> <arg value="-max"/> <arg value="${worker.max}"/> </java> </target> v121128 JMS

29 JMS Scheduler: jmsScheduler.properties
m2.repo and jboss.home must be set by local environment M2_REPO=${m2.repo} JBOSS_HOME=${jboss.home} javaee.classpath=${M2_REPO}/javax/javaee/javaee/5/javaee-5.jar commons.logging.classpath=${M2_REPO}/commons-logging/commons- logging/1.0.4/commons-logging jar:${M2_REPO}/xerces/xercesImpl/2.6.2/xercesImpl jar jbossall-client.classpath=${JBOSS_HOME}/client/jbossall-client.jar log4j.classpath=${M2_REPO}/log4j/log4j/1.2.13/log4j jar jndi.name.connFactory=ConnectionFactory jndi.name.testQueue=queue/ejava/examples/jmsScheduler/requestQueue jndi.name.DLQ=queue/ejava/examples/jmsScheduler/DLQ requestor.name=Requestor0 requestor.sleep=5000 requestor.max=10 requestor1.name=Requestor1 requestor1.sleep=10 requestor1.max=0 worker.name=Worker0 worker.max=0 v121128 JMS

30 jmsScheduler: Requestor0
Requestor sends request to queue and tracks reply jmsScheduler> mvn process-test-resources; ant -f target/test-classes/jmsScheduler- ant.xml init requestor -emacs ... Requestor args:-jndi.name.connFactory ConnectionFactory -jndi.name.destination queue/ejava/examples/jmsScheduler/requestQueue -jndi.name.DLQ queue/ejava/examples/jmsScheduler/DLQ -name Requestor0 -sleep max 10 -requester Requestor0 starting: maxCount=10, sleepTime5000 -published message(1):ID: -outstanding requests=1 -recieved response for:1, from Worker0, outstanding=0 -published message(2):ID: -recieved response for:2, from Worker1, outstanding=0 -published message(3):ID: -recieved response for:6, from Worker0, outstanding=0 -published message(7):ID: -recieved response for:10, from Worker0, outstanding=0 -requester Requestor0 stopping, count=10 v121128 JMS

31 jmsScheduler: Worker0 Worker0 takes next request, processes, and replies jmsScheduler> ant -f target/test-classes/jmsScheduler-ant.xml worker -emacs worker: Worker args:-jndi.name.connFactory ConnectionFactory -jndi.name.destination queue/ejava/examples/jmsScheduler/requestQueue -jndi.name.DLQ queue/ejava/examples/jmsScheduler/DLQ -name Worker0 -max 0 -worker Worker0 starting -Worker0 received message #1, req=1, replyTo=QUEUE.JMS_TQ3, delay=0 -committing session -Worker0 received message #2, req=3, replyTo=QUEUE.JMS_TQ3, delay=0 -Worker0 received message #3, req=5, replyTo=QUEUE.JMS_TQ3, delay=10 -Worker0 received message #4, req=6, replyTo=QUEUE.JMS_TQ3, delay=10 -Worker0 received message #5, req=7, replyTo=QUEUE.JMS_TQ3, delay=10 -Worker0 received message #6, req=8, replyTo=QUEUE.JMS_TQ3, delay=100 -Worker0 received message #7, req=9, replyTo=QUEUE.JMS_TQ3, delay=100 -Worker0 received message #8, req=10, replyTo=QUEUE.JMS_TQ3, delay=0 v121128 JMS

32 jmsScheduler: Worker1 Worker1 competes for requests
Quits after 3 requests 2 completed successfully 3rd never committed jmsScheduler> ant -f target/test-classes/jmsScheduler-ant.xml worker1 -emacs Buildfile: target/test-classes/jmsScheduler-ant.xml worker1: Worker args:-jndi.name.connFactory ConnectionFactory -jndi.name.destination queue/ejava/examples/jmsScheduler/requestQueue -jndi.name.DLQ queue/ejava/examples/jmsScheduler/DLQ -name Worker1 -max 3 -worker Worker1 starting -Worker1 received message #1, req=2, replyTo=QUEUE.JMS_TQ3, delay=0 -committing session -Worker1 received message #2, req=4, replyTo=QUEUE.JMS_TQ3, delay=10 -Worker1 received message #3, req=6, replyTo=QUEUE.JMS_TQ3, delay=10 -worker Worker1 stopping v121128 JMS

33 JMS API v121128 JMS

34 JMS API Destination ConnectionFactory Connection Session Message
an identifier for a queue or topic in the provider ConnectionFactory encapsulates a set of properties for creating connections to provider Connection represents a physical connection to the provider Session a context for sending/receiving messages for a Thread factory for creating remaining JMS objects Message unit of communication MessageProducer used to send messages MessageConsumer used to receive messages MessageListener optionally implemented by client to receive messages asynchronously ExceptionListener optionally implemented by client to receive JMSExceptions relative to the connection v121128 JMS

35 ConnectionFactory Administered Object
commonly obtained from JNDI Parent interface for specialized factories TopicConnectionFactory, QueueConnectionFactory, XAConnectionFactory Encapsulates a set of connection attributes set by administrator clientId listen address ConnectionFactory connFactory = (ConnectionFactory)jndi.lookup(connFactoryJNDIName); Connection connection = null; try { connection = connFactory.createConnection(); } finally { if (connection != null) { connection.close(); } v121128 JMS

36 Connection Client's active connection to JMS provider
typically represents an open tcp/ip socket to provider allocates resources outside of client JVM Authentication performed when created Supports an ExceptionListener Thread-safe object heavyweight no designed need for multiple connections Parent interface for specialized factories TopicConnection, QueueConnection, XAConnection Created in stopped state stopped – no messages being delivered started – messages can be received Messages can be sent in both started and stopped state v121128 JMS

37 Session Single Threaded context for producing and consuming message
Session session = null; try { session = connection.createSession(false,//isTransacted Session.AUTO_ACKNOWLEDGE);//ackMode ... } finally { if (session != null) { session.close(); } Parent interface for specialized factories TopicSession, QueueSession, XASession Typical to use single session as part of a transaction synchronously block on receive send result commit Receiving and sending on separate threads need separate sessions v121128 JMS

38 Session (cont.) isTransacted – form local transaction within provider
false – session either joins JTA or no tx outside JTA session = connection.createSession(false,//isTransacted Session.AUTO_ACKNOWLEDGE);//ackMode ... producer.send(message); //automatically committed true – session forms its own transaction context session = connection.createSession(true,//isTransacted Message message1 = consumer.receive(); producer.send(message2); session.commit(); //commit outstanding session messages -or- session.rollback(); //rollback outstanding session messages v121128 JMS

39 Session (cont.) Session retains consumed messages until acknowledged
Acknowledgement Modes session = connection.createSession(false,//transacted Session.AUTO_ACKNOWLEDGE);//ackMode AUTO_ACKNOWLEDGE message automatically acknowledged by session when client receives (receive()) or processes (onMessage) message CLIENT_ACKNOWLEDGE messages are manually acknowledged any acknowledged message acknowledges all prior messages consumed message.acknowledge(); //manually ack this and all //preceding messages DUPS_OK_ACKNOWLEDGE similar to AUTO_ACKNOWLEDGE session lazily acknowledges messages can result in duplicate messages v121128 JMS

40 Session (cont.) Factory for TemporaryTopics and TemporaryQueues
Topic tempTopic = session.createTemporaryTopic(); Queue tempQueue = session.createTemporaryQueue(); May optionally create queues and topics not portable Topic topic = session.createTopic(topicName); Queue queue = session.createQueue(queueName); v121128 JMS

41 Session (cont.) Factory for QueueBrowsers
look at messages on queue without removing them QueueBrowser qbrowser = session.createBrowser((Queue)destination); for (Enumeration e = qbrowser.getEnumeration(); e.hasMoreElements(); ) { Message m = (Message) e.nextElement(); log.debug("browsing message=" + m.getJMSMessageID()); } changes in queue between getting enumeration and accessing message undefined by specification v121128 JMS

42 Session (cont.) Factory for provider-specific messages
Message message = session.createMessage(); <T>Message message = session.create<T>Message(); Factory for MessageProducers and MessageConsumers MessageProducer producer = session.createProducer(destination); producer.send(message); MessageConsumer consumer = session.createConsumer(destination); Message message = consumer.receive(); v121128 JMS

43 MessageConsumer Used to receive messages from a destination
Parent interface for specialized message consumers TopicSubscriber QueueReceiver Two approaches to receive messages Client may poll message consumer for messages Client have messages asynchronously delivered as they arrive v121128 JMS

44 MessageConsumer (cont.)
Client may poll message consumer for messages MessageConsumer.receive(timeout) : Message private class SyncClient implements MyClient { private MessageConsumer consumer; public SyncClient(MessageConsumer consumer) { this.consumer = consumer; } public int getCount() { return count; } public Message getMessage() throws JMSException { Message message=consumer.receiveNoWait(); return message; ... MessageConsumer syncConsumer = session.createConsumer(destination); SyncClient syncClient = new SyncClient(syncConsumer); Message message = syncClient.getMessage(); v121128 JMS

45 MessageConsumer (cont.)
Client may implement an interface to have message consumer asynchronously deliver them as they arrive MessageListener.onMessage(Message message) callback may not throw an exception private class AsyncClient implements MessageListener { LinkedList<Message> messages = new LinkedList<Message>(); public void onMessage(Message message) { try { messages.add(message); //process message } catch (JMSException ex) { log.fatal("error handling message", ex); } public Message getMessage() { return (messages.isEmpty() ? null : messages.remove()); ... MessageConsumer asyncConsumer = session.createConsumer(destination); AsyncClient asyncClient = new AsyncClient(); asyncConsumer.setMessageListener(asyncClient); Message message = asyncClient.getMessage(); v121128 JMS

46 MessageConsumer (cont.)
Selectors can be applied to reduce noise to MessageConsumer sql-like selector based on JMS and user properties null or empty string equivalent to no selector String selector1 = "level in ('warn', 'fatal')"; asyncConsumer = session.createConsumer(destination, selector1); AsyncClient asyncClient = new AsyncClient(); asyncConsumer.setMessageListener(asyncClient); ... String selector2 = "level in ('info','warn', 'fatal')"; syncConsumer = session.createConsumer(destination, selector2); SyncClient syncClient = new SyncClient(syncConsumer); String levels[] = {"debug", "info", "warn", "fatal"}; MessageProducer producer = session.createProducer(destination); Message message = session.createMessage(); for (String level : levels) { message.setStringProperty("level", level); producer.send(message); } ... //for Topics assertEquals(2, asyncClient.getCount()); assertEquals(3, syncClient.getCount()); v121128 JMS

47 MessageConsumer (cont.)
Durable subscriptions can be used for TopicSubscribers messages stored while TopicSubscriber not physically connected consumes resources on server MessageConsumer nonDurableConsumer = session.createConsumer(destination); ... nonDurableConsumer.receive(); //won't receive messages sent while //physically disconnected //the Connection.clientID is needed for Durable Subscriptions connection.setClientID("testDurableSubscription"); MessageConsumer durableConsumer = session.createDurableSubscriber((Topic)destination,"async1"); durableConsumer.receive(); //will receive messages not yet consumed //that have been sent after initial //registration v121128 JMS

48 MessageProducer Used to send messages to a destination
Parent interface for specialized message consumers TopicPublisher QueueSender Created from Session MessageProducer producer = session.createProducer(destination); destination can be null Can set other defaults with MessageProducer properties deliveryMode priority timeToLive Can set certain optimizations disableTimestamp disableMessageID v121128 JMS

49 MessageProducer (cont.)
Priority int value (0 lowest, 9 highest) 0-4 normal, 4 default, and 5-9 expedited int priorities[] = {9,0,8,1,7,2,6,3,6,4,5}; for (int i=0; i<msgCount; i++) { for (int priority : priorities) { producer.setPriority(priority); producer.send(message); } -onMessage received (1):ID: , priority=9 -onMessage received (2):ID: , priority=8 -onMessage received (3):ID: , priority=7 -onMessage received (4):ID: , priority=6 -onMessage received (5):ID: , priority=6 -onMessage received (6):ID: , priority=5 -onMessage received (7):ID: , priority=4 -onMessage received (8):ID: , priority=3 -onMessage received (9):ID: , priority=2 -onMessage received (10):ID: , priority=1 -onMessage received (11):ID: , priority=0 v121128 JMS

50 MessageProducer (cont.)
Priority can alternately be specified on send producer.send(message, Message.DEFAULT_DELIVERY_MODE, priority, Message.DEFAULT_TIME_TO_LIVE); -onMessage received (1):ID: , priority=9 -onMessage received (2):ID: , priority=8 -onMessage received (3):ID: , priority=7 -onMessage received (4):ID: , priority=6 -onMessage received (5):ID: , priority=6 -onMessage received (6):ID: , priority=5 -onMessage received (7):ID: , priority=4 -onMessage received (8):ID: , priority=3 -onMessage received (9):ID: , priority=2 -onMessage received (10):ID: , priority=1 -onMessage received (11):ID: , priority=0 v121128 JMS

51 MessageProducer (cont.)
Priority MessageProducer, not message, priority used message.setJMSPriority(priority); producer.send(message); -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 -sent (0)msgId=ID: , priority=4 v121128 JMS

52 MessageProducer (cont.)
Time To Live (TTL) Used to timeout undelivered messages 0 indicates no timeout long ttlMsecs[] = {100, 0, 10000, 100, 10000}; for (long ttl : ttlMsecs) { producer.setTimeToLive(ttl); producer.send(message); } -sent msgId=ID: , expiration= , 97msecs -sent msgId=ID: , expiration=0, 0msecs -sent msgId=ID: , expiration= , 10000msecs -sent msgId=ID: , expiration= , 100msecs -sent msgId=ID: , expiration= , 10000msecs -waiting 1000msecs for some messages to expire -onMessage received (1):ID: , expiration=0, 0msecs -onMessage received (2):ID: , expiration= , 8981msecs -onMessage received (3):ID: , expiration= , 8976msecs v121128 JMS

53 MessageProducer (cont.)
Time To Live (TTL) can alternately specify on send producer.send(message, Message.DEFAULT_DELIVERY_MODE, Message.DEFAULT_PRIORITY, ttl); -sent msgId=ID: , expiration= , 99msecs -sent msgId=ID: , expiration=0, 0msecs -sent msgId=ID: , expiration= , 9998msecs -sent msgId=ID: , expiration= , 98msecs -sent msgId=ID: , expiration= , 9995msecs -waiting 1000msecs for some messages to expire -onMessage received (1):ID: , expiration=0, 0msecs -onMessage received (2):ID: , expiration= , 8965msecs -onMessage received (3):ID: , expiration= , 8971msecs v121128 JMS

54 MessageProducer (cont.)
Delivery Mode pertains only to transit of message to destination no impact on actual delivery, timeout, or storage issues PERSISTENT instructs provider to log message to persistent storage before completing the send more robust, slower NON_PERSISTENT allows provider to buffer messages prior performing any logging to persistent storage more efficient, faster producer.send(message, mode.mode, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); -total messages per test=10000 -mode:NON_PERSISTENT total=5066msecs , ave=0.5066msecs -mode:PERSISTENT total=5746msecs , ave=0.5746msecs v121128 JMS

55 Messages Contents Header Properties Body standard header fields
application-specific properties supports message filtering (using selectors) Body Stream – stream of Java primitive values Map – string names and Java primitive values Text – java.lang.String body (supports XML) Object – Serializable Object body Bytes – raw byte format v121128 JMS

56 Message Header JMSMessageID : String unique key
assigned a provider-supplied value on send values start with “ID:” disabled with MessageProvider.setDisableMessageID() can be optionally changed by recipient JMSTimestamp : long time when message given to provider to be sent assigned by during send not actual time sent (queuing, re-transmit, etc.) diabled with MessageProvider.setDisableTimestamp() v121128 JMS

57 Message Header (cont.) JMSCorrelationID : String
links message to something another message – JMSMessageID value must start with “ID:” processing context – application String value must not start with “ID:” provider-specific legacy format value contains raw byte[] JMSCorrelationIDAsBytes : byte[] used only by providers with legacy correlationID formats not portable v121128 JMS

58 Message Header (cont.) JMSReplyTo : Destination
signals a request for a reply sets Destination for reply producer.send(replyTo, message, ...); JMSDestination : Destination contains the Destination messages was sent to set during send() received messages contain Destination sent to JMSDeliveryMode : int JMSRedelivered : boolean an indication that message has been received, but not successfully ackowledged, before v121128 JMS

59 Message Header (cont.) JMSType : String JMSExpiration : long
no meaning or format defined by spec spec suggests flexible use of field at deployment time to be portable across providers JMSExpiration : long a point in time, after which, the undelivered message may be expired from storage calculation of the time-to-live value and GMT assigned during send() 0 value indicates message does not expire spec does not define a notification of expiration (or delivery!) JMSPriority : int 0 (lowest) to 9 (highest) v121128 JMS

60 Example Header Values log.debug("message2.JMSMessageID=" + message2.getJMSMessageID()); log.debug("message2.JMSTimestamp=" + message2.getJMSTimestamp()); try { log.debug("message2.JMSCorrelationIDAsBytes=" + message2.getJMSCorrelationIDAsBytes()); } catch (JMSException ex) { log.debug("message2.JMSCorrelationIDAsBytes=" + ex); } log.debug("message2.JMSCorrelationID=" +message2.getJMSCorrelationID()); ... log.debug("message2.JMSPriority=" + message2.getJMSPriority()); -message2.JMSMessageID=ID: -message2.JMSTimestamp= -message2.JMSCorrelationIDAsBytes=javax.jms.JMSException: JMSCorrelationID is a string -message2.JMSCorrelationID=null -message2.JMSReplyTo=null -message2.JMSDestination=TOPIC.ejava/jms/topic1 -message2.JMSDeliveryMode=2 -message2.JMSRedelivered=false -message2.JMSType=null -message2.JMSExpiration=0 -message2.JMSPriority=4 v121128 JMS

61 ReplyTo Example: request
Create a set of separate ReplyTo queues producer = session.createProducer(destination); Destination replyDestinations[] = { session.createTemporaryQueue(), ... }; for(Destination replyTo : replyDestinations) { replyConsumers.add(session.createConsumer(replyTo)); } Send a “request” with the replyTo destination Message message = session.createMessage(); Map<String, Message> responses = new HashMap<String, Message>(); message.setJMSReplyTo(replyTo); producer.send(message); responses.put(message.getJMSMessageID(), null); v121128 JMS

62 ReplyTo Example: reply
Create reply objects public void setSession(Session session) throws JMSException { producer = session.createProducer(null); reply = session.createMessage(); } Send reply to requested destination public void onMessage(Message message) { try { //process request Destination replyDestination = message.getJMSReplyTo(); reply.setJMSCorrelationID(message.getJMSMessageID()); producer.send(replyDestination, reply); } catch (JMSException ex) { ... v121128 JMS

63 ReplyTo Example: handle response
Check for replies for(int d=0; d<replyDestinations.length; d++) { Message m = replyConsumers.get(d).receiveNoWait(); if (m != null) { responses.put(message.getJMSCorrelationID(), m); } Sample output -sent (1)msgId=ID: , replyTo=QUEUE.JMS_TQ21 -sent (2)msgId=ID: , replyTo=QUEUE.JMS_TQ22 -sent (3)msgId=ID: , replyTo=QUEUE.JMS_TQ23 -sent (4)msgId=ID: , replyTo=QUEUE.JMS_TQ24 -onMessage received (1):ID: , replyTo=QUEUE.JMS_TQ21 -onMessage received (2):ID: , replyTo=QUEUE.JMS_TQ22 -onMessage received (3):ID: , replyTo=QUEUE.JMS_TQ23 -onMessage received (4):ID: , replyTo=QUEUE.JMS_TQ24 v121128 JMS

64 Message Properties Supports application-defined header fields Names
String cannot be null cannot be empty strings “JMSX” property name prefix is reserved JMXGroupID JMSXGroupSeq JMS_vendor_name – property prefix is reserved Values boolean, byte, short, int, long, float, double, String accessed through typed setters/getters or setObjectProperty/getObjectProperty v121128 JMS

65 Message Properties (cont.)
Names retrieved using getPropertyNames() Read/Write by sender Read-only by receiver Message.clearProperties() permits write access to property area Header values are never read-only v121128 JMS

66 Message Properties (cont.)
Example using Message properties Message message = session.createMessage(); message.setBooleanProperty("booleanProperty", true); message.setByteProperty("byteProperty", (byte)0x01); message.setDoubleProperty("doubleProperty", 1.01); message.setFloatProperty("floatProperty", (float)1.02); message.setIntProperty("intProperty", 3); message.setLongProperty("longProperty", 5L); message.setObjectProperty("intPropertyAsObject", 3); message.setShortProperty("shortProperty", (short)4); message.setStringProperty("stringProperty", "hello JMS world"); producer.send(message); Message message2 = consumer.receive(1000); -message2.byteProperty (:java.lang.Byte)=1 -message2.longProperty (:java.lang.Long)=5 -message2.shortProperty (:java.lang.Short)=4 -message2.doubleProperty (:java.lang.Double)=1.01 -message2.stringProperty (:java.lang.String)=hello JMS world -message2.intPropertyAsObject (:java.lang.Integer)=3 -message2.floatProperty (:java.lang.Float)=1.02 -message2.booleanProperty (:java.lang.Boolean)=true -message2.intProperty (:java.lang.Integer)=3 -message2.JMSXDeliveryCount (:java.lang.Integer)=1 v121128 JMS

67 Message Forms StreamMessage MapMessage TextMessage ObjectMessage
stream of Java primitive values MapMessage string names and Java primitive values TextMessage java.lang.String body (supports XML) ObjectMessage Serializable Object body BytesMessage raw byte format Message only contains JMS Header and application properties v121128 JMS

68 Example MessageTest Framework
private class Replier implements MessageListener { private MessageProducer producer; public void onMessage(Message request) { try { Message reply = null; if (request instanceof StreamMessage) { reply = getReply((StreamMessage)request); } else ... reply.setJMSCorrelationID( request.getJMSMessageID()); producer.send(replyDestination, reply); } catch (Exception ex) { log.fatal("error handling message", ex); protected Message getReply(<T>Message request) throws JMSException { ... //detailed on following slides return reply; v121128 JMS

69 StreamMessage used to send a stream of Java primitive values
filled and read sequentially based on java.io.DataInput/OutputStream interfaces values can be accessed explicitly streamMessage.writeInt(3) int value = streamMessage.readInt(); values can be accessed generically streamMessage.writeObject(new Integer(3)); Object value = streamMessage.readObject(); write-only mode first created clearBody() called used by sender to re-use a previously sent message read-only mode when received when reset() called used to reset the stream to the first byte v121128 JMS

70 StreamMessage Example
Example request StreamMessage request = session.createStreamMessage(); request.writeString("add"); request.writeInt(2); request.writeInt(3); request.setJMSReplyTo(replyDestination); producer.send(request); StreamMessage response = (StreamMessage)replyConsumer.receive(); int result = response.readInt(); assertEquals("wrong answer:" + result, 5, result); Example reply String operator = request.readString(); int operand1 = request.readInt(); int operand2 = request.readInt(); int result = ("add".equals(operator) ? operand1 + operand2 : -1); StreamMessage reply = session.createStreamMessage(); reply.writeInt(result); v121128 JMS

71 MapMessage Used to send name/primitive value pairs
name – String value – Java primitive Values can be accessed explicitly mapMessage.setInt(“name”, 3); int value = mapMessage.getInt(“name”); Values can be accessed generically mapMessage.setObject(“name”, new Integer(3)); Object value = mapMessage.getObject(“name”); read/write mode when created clearBody() called read-only mode when received v121128 JMS

72 MapMessage Example Example request Example reply
MapMessage request = session.createMapMessage(); request.setString("operator", "add"); request.setInt("operand1", 2); request.setInt("operand2", 3); request.setJMSReplyTo(replyDestination); producer.send(request); MapMessage response = (MapMessage)replyConsumer.receive(); int result = response.getInt("result"); assertEquals("wrong answer:" + result, 5, result); Example reply String operator = request.getString("operator"); int operand1 = request.getInt("operand1"); int operand2 = request.getInt("operand2"); int result = ("add".equals(operator) ? operand1 + operand2 : -1); MapMessage reply = session.createMapMessage(); reply.setInt("result", result); v121128 JMS

73 TextMessage Sends a String message Used for text.based messages
XML Property lists Only a single value, only accessed as String textMessage.setText(“hello world”); String value = textMessage.getText(); read/write mode when created clearBody() called read-only when received v121128 JMS

74 TextMessage Example Example TextMessage request
TextMessage request = session.createTextMessage(); Properties props = new Properties(); props.put("operator", "add"); props.put("operand1", new Integer(2).toString()); props.put("operand2", new Integer(3).toString()); StringWriter bodyText = new StringWriter(); props.list(new PrintWriter(bodyText)); request.setText(bodyText.toString()); request.setJMSReplyTo(replyDestination); producer.send(request); TextMessage response = (TextMessage)replyConsumer.receive(); String resultStr = response.getText(); int result = Integer.parseInt(resultStr); assertEquals("wrong answer:" + result, 5, result); v121128 JMS

75 TextMessage Example Example TextMessage reply
Properties props = new Properties(); props.load(new ByteArrayInputStream(request.getText().getBytes())); String operator = props.getProperty("operator"); int operand1 = Integer.parseInt(props.getProperty("operand1")); int operand2 = Integer.parseInt(props.getProperty("operand2")); int result = ("add".equals(operator) ? operand1 + operand2 : -1); TextMessage reply = session.createTextMessage(); reply.setText(new Integer(result).toString()); v121128 JMS

76 ObjectMessage Sends a Serializable Object
Only a single value, accessed as Serializable objectMessage.setObject(new Integer(3)); Object value = (Object)objectMessage.getObject(); read/write when created clearBody() called read-only when received v121128 JMS

77 ObjectMessage Example
Example ObjectMessage request ObjectMessage request = session.createObjectMessage(); Map<String, Serializable> body = new HashMap<String,Serializable>(); body.put("operator", "add"); body.put("operand1", new MyInteger(2)); //use a custom class as an body.put("operand2", new MyInteger(3)); //example of serializable request.setObject((Serializable)body); request.setJMSReplyTo(replyDestination); producer.send(request); ObjectMessage response = (ObjectMessage)replyConsumer.receive(); int result = ((MyInteger)response.getObject()).getValue(); assertEquals("wrong answer:" + result, 5, result); v121128 JMS

78 ObjectMessage Example
Example ObjectMessage reply Map<String, Object> body = (Map<String, Object>)request.getObject(); String operator = (String)body.get("operator"); int operand1 = ((MyInteger)body.get("operand1")).getValue(); int operand2 = ((MyInteger)body.get("operand2")).getValue(); int result = ("add".equals(operator) ? operand1 + operand2 : -1); ObjectMessage reply = session.createObjectMessage(); reply.setObject(new MyInteger(result)); Example Serializable Application Class used //this class is used to provide an example of a custom class sent //within a serializable payload private class MyInteger implements Serializable { private static final long serialVersionUID = 1L; private int value; public MyInteger(int value) { this.value = value; } public int getValue() { return value; } } v121128 JMS

79 BytesMessage Send a stream of uninterpreted bytes
based on java.io.DataInput/OutputStream intended for messages with legacy formats available for use for messages with binary content legacy messages may not permit use of full set of JMS Headers any JMS Properties values can be accessed explicitly bytesMessage.writeInt(3); int value = bytesMessage.readInt(); values can be written (but not read) generically bytesMessage.writeObject(new Integer(3)); write-only mode when created clearBody() called read-only when received reset() called v121128 JMS

80 BytesMessage Example Example BytesMessage request
ByteArrayOutputStream bos = new ByteArrayOutputStream(); bos.write("add".getBytes()); bos.write(2); bos.write(3); BytesMessage request = session.createBytesMessage(); request.writeBytes(bos.toByteArray()); request.setJMSReplyTo(replyDestination); producer.send(request); BytesMessage response = (BytesMessage)replyConsumer.receive(); int result = response.readInt(); assertEquals("wrong answer:" + result, 5, result); v121128 JMS

81 BytesMessage Example Example BytesMessage reply
log.debug("body=" + request.getBodyLength() + " bytes"); byte buffer[] = new byte[10]; request.readBytes(buffer, 3); String operator = new String(buffer); int operand1 = request.readByte(); int operand2 = request.readByte(); int result = (operator.startsWith("add") ? operand1 + operand2 :-1); BytesMessage reply = session.createBytesMessage(); reply.writeInt(result); v121128 JMS

82 (Simple) Message Example
Example request Message request = session.createMessage(); request.setStringProperty("operator", "add"); request.setIntProperty("operand1", 2); request.setIntProperty("operand2", 3); request.setJMSReplyTo(replyDestination); producer.send(request); Message response = replyConsumer.receive(); int result = response.getIntProperty("result"); assertEquals("wrong answer:" + result, 5, result); Example reply String operator = request.getStringProperty("operator"); int operand1 = request.getIntProperty("operand1"); int operand2 = request.getIntProperty("operand2"); int result = ("add".equals(operator) ? operand1 + operand2 : -1); Message reply = session.createMessage(); reply.setIntProperty("result", result); v121128 JMS

83 Queue/Topic Requestor
Meant to simplify request/reply scenarios Too simple for realistic use! no timeouts no mixing of request/reply destination types users encouraged to create more robust implementations Helper is provided a non-transacted session destination Helper creates temporary destination Example QueueRequest requestor = new QueueRequestor(session, targetQueue); Message reply = resquestor(request); TopicRequest requestor = new TopicRequestor(session, targetTopic); v121128 JMS

84 Building JMS Modules v121128 JMS

85 Dependencies JMS API JMS Provider (HornetQ) Driver
<dependency> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> <scope>provided</scope> </dependency> JMS Provider (HornetQ) Driver <groupId>org.hornetq</groupId> <artifactId>hornetq-jms-client</artifactId> <scope>test</scope> <artifactId>hornetq-core</artifactId> <groupId>org.jboss.netty</groupId> <artifactId>netty</artifactId> JBoss RMI Dependencies <groupId>ejava.common</groupId> <artifactId>jboss-rmi-client</artifactId> <type>pom</type> v121128 JMS

86 JSE Classpath Option #1: build-classpath
Use dependency-plugin to build classpath to M2_REPO <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>build-classpath</goal> </goals> </execution> </executions> <configuration> <outputFile>target/test-classes/dependency-classpath</outputFile> </configuration> </plugin> $ cat target/test-classes/dependency-classpath /home/jcstaff/.m2/repository/javax/jms/jms/1.1/jms-1.1.jar:/home/jcstaff/.m2/repository/commons- logging/commons-logging/1.1.1/commons-logging- … v121128 JMS

87 JSE Classpath Option #2: copy-dependencies
Use dependency-plugin to build classpath to M2_REPO <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> </execution> </executions> <configuration> <outputFile>target/test-classes/dependency-classpath</outputFile> </configuration> </plugin> $ ls target/dependency activation jar jboss-as-process-controller Final.jar jboss-remoting GA.jar commons-logging jar jboss-as-protocol Final.jar jboss-rmi-client pom dtdparser jar jboss-as-remoting Final.jar jboss-sasl Final.jar v121128 JMS

88 Setting JSE Classpath Account for either
Long Classpath reference into M2_REPO Very large classpath Directory Classpath Many MB in dependency copies <project name="jmsScheduler" basedir=".."> <property file="test-classes/${ant.project.name}.properties"/> <loadfile property="dependency-classpath" srcFile="test-classes/dependency-classpath" failonerror="false"/> <path id="demo.classpath"> <pathelement path="test-classes"/> <pathelement path="classes"/> <fileset dir="." includes="dependency/*.jar"/> <pathelement path="${dependency-classpath}"/> </path> v121128 JMS

89 Summary Messaging Overview JMS Overview JMS Examples JMS API Detail
decouples Producer from Consumer JMS Overview Java API for interfacing with enterprise messaging providers JMS Examples defining destinations publish/subscribe request/reply queuing access controls transactional receive/send DLQ JMS API Detail see JMS Javadoc v121128 JMS

90 References Java Messaging Service API
summary.html “Enterprise JavaBeans 3.0, 5th Edition”; Burke & Monsen-Haefel; ISBN X; O'Reilly v121128 JMS


Download ppt "Java Messaging Service (JMS)"

Similar presentations


Ads by Google