10.2 Introducing the JMS The JMS is a formal J2EE specification for enterprise messaging servers. JMS defines Java interfaces for both clients and servers. JMS vendors supply implementations of those interfaces. Mobile MOM servers that implement JMS are guaranteed to work with all J2EE application servers. In addition, using JMS in mobile MOM solutions allows existing enterprise Java developers to leverage their skills. Now, let's have a look at the overall JMS architecture from its public interfaces.
10.2.1 Top-Level Interfaces Table 10.1 lists the top-level interfaces in the javax.jms package. Built on top of those general-purpose interfaces, JMS provides subinterfaces to support two important messaging models.Table 10.1. Interfaces in the javax.jms Package|
Message | Represents a message to be exchanged. It supports both text and binary messages as well as message headers. | Destination | Represents a delivery destination maintained by the JMS server. The JMS server forwards messages to their destination clients, stores messages for unavailable clients, and handles delivery failures and acknowledgments. | MessageConsumer | Represents a client that receives messages. It has to be associated with a Destination. To receive messages synchronously, we can use the receive() method. It blocks the I/O until a new message arrives. | MessageListener | This is a callback interface for a MessageConsumer to receive messages asynchronously. Once the listener object is registered with a MessageConsumer, the listener's onMessage() method is called when a new message arrives. | MessageProducer | Represents a client that sends out messages. A MessageProducer sends messages to a Destination. | Connection | Represents a data channel between the JMS client and server. JMS implementations can support connections via many protocols besides the TCP/IP. Connection objects are usually obtained through a factory method, which is in turn configured in the JNDI directory. | Session | Represents a persistent connection where the client state information is maintained. The Session interface declares factory methods for the client to create message, publisher, and consumer objects. |
10.2.2 Publish-and-Subscribe Model In the publish-and-subscribe model, the message Destinations are Topics. Messages sent to a topic are duplicated and distributed to all the subscribers of that topic (see Figure 10.1). If a subscriber is temporarily unavailable, the server will hold the message and try later.
![](/image/library/english/10153_10fig01.gif) A client can start a new topic or send messages to an existing topic. Listing 10.1 illustrates how a publisher client works.Listing 10.1. A JMS publisher in action
// The startup process is a tedious bootstrap // process until we get the TopicPublisher object Properties env = new Properties(); InitialContext jndi = new InitialContext(env); TopicConnectionFactory factory = (TopicConnectionFactory) jndi.lookup("MyBroker"); TopicConnection conn = factory.createTopicConnection(username, password); TopicSession pubSess = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Topic topub = (Topic)jndi.lookup("My topic"); TopicPublisher publisher = pubSess.createPublisher(topub); conn.start(); // Now, let's send a message! StreamMessage mesg = pubSess.createStreamMessage(); mesg.writeString("something important"); mesg.writeFloat( 123.45 ); // complete writing your message content // mesg.setJMSReplyTo( replyTopic ); publisher.publish(mesg, DeliveryMode.PERSISTENT, Message.DEFAULT_PRIORITY, 18000);
Once a topic is created, any authorized client can subscribe to it and start to receive messages. Listing 10.2 illustrates how to receive messages from a topic asynchronously through the MessageListener.Listing 10.2. A JMS subscriber in action
// Provide an implementation of the listener public class MyListener implements MessageListener { public MyListener () { } // This is the only method we need to implement public void onMessage (Message mesg) { TextMessage tmesg = (TextMessage) mesg; String text = tmesg.getText(); // do something ... } } // The startup process is a tedious bootstrap // process until we get the TopicSubscriber object. // Then we set the listener as an instance of the // MyListener class Properties env = new Properties(); InitialContext jndi = new InitialContext(env); TopicConnectionFactory factory = (TopicConnectionFactory) jndi.lookup("MyBroker"); TopicConnection conn = factory.createTopicConnection(username, password); TopicSession subSess = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); Topic tosub = (Topic)jndi.lookup("Interesting topic"); TopicSubscriber subscriber = subSess.createSubscriber(tosub); subscriber.setMessageListener(new MyListener()); conn.start();
10.2.3 Point-to-Point Model In the point-to-point model, the message Destinations are Queues. Multiple senders and receivers can connect to a queue. But each message in the queue is consumed only once. Once a message is delivered to a receiver, it is removed from the queue (see Figure 10.2).
![](/image/library/english/10153_10fig02.gif) Code snippets in Listings 10.3 and 10.4 illustrate how to work with point-to point-message queues. Notice how strikingly similar they are compared with listings 10.1 and 10.2.Listing 10.3. A JMS queue sender in action
// The startup process is a tedious bootstrap // process until we get the QueueSender object Properties env = new Properties(); InitialContext jndi = new InitialContext(env); QueueConnectionFactory factory = (QueueConnectionFactory) jndi.lookup("MyBroker"); QueueConnection conn = factory.createQueueConnection(username, password); QueueSession sendSess = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue toque = (Queue)jndi.lookup("My queue"); QueueSender sender = sendSess.createSender(toque); conn.start(); // Now, let's send a message! StreamMessage mesg = sendSess.createStreamMessage(); mesg.writeString("something important"); mesg.writeFloat( 123.45 ); // complete writing your message content // mesg.setJMSReplyTo( replyTopic ); sender.send(mesg, DeliveryMode.PERSISTENT, Message.DEFAULT_PRIORITY, 18000);
Listing 10.4. A JMS queue receiver in action
// Provide an implementation of the listener public class MyListener implements MessageListener { public MyListener () { } // This is the only method we need to implement public void onMessage (Message mesg) { TextMessage tmesg = (TextMessage) mesg; String text = tmesg.getText(); // do something ... } } // The startup process is a tedious bootstrap // process until we get the QueueReceiver object. // Then we set the listener as an instance of the // MyListener class Properties env = new Properties(); InitialContext jndi = new InitialContext(env); QueueConnectionFactory factory = (QueueConnectionFactory) jndi.lookup("MyBroker"); QueueConnection conn = factory.createQueueConnection(username, password); QueueSession recSess = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue recque = (Queue)jndi.lookup("Interesting topic"); QueueReceiver receiver = recSess.createReceiver(recque); receiver.setMessageListener(new MyListener()); conn.start();
10.2.4 Combine the Two Messaging Models The publish-subscribe and point-to-point messaging models often work together. For example, in a marketplace application, sellers send out multicast messages to buyers who subscribe to certain topics. Interested buyers can get back to the seller via the specified queues.Although JMS is a powerful and standard tool for enterprise messaging, it is designed for the J2EE platform. Most JMS providers are hence too heavy for mobile applications. The next two sections introduce two mobile JMS or JMS-like solution providers: iBus//Mobile from Softwired and WebSphere MQ Everyplace from IBM. |