Sample E-mail Sender Application
The queue application I present here includes two JMS client applicationsone that sends simulated e-mail messages to an e-mail inbox, and another that reads the e-mail messages off the queue. The EmailSender
class in Listing One is a message producer that sends messages to a simulated e-mail inbox, which is simply a JMS queue that is read by the e-mail reader application at a later time. (The complete source code for the sender/reader application is available electronically; see www.ddj.com/code/.)
package emaildemo; import javax.jms.*; import javax.naming.*; public class EmailSender { private Connection connection = null; private Session session = null; private MessageProducer prod = null; public EmailSender() { try { InitialContext jndi = new InitialContext(); // Lookup a JMS connection factory ConnectionFactory conFactory = (ConnectionFactory)jndi.lookup("ConnectionFactory"); // Create a JMS connection connection = conFactory.createConnection("",""); // Create a JMS session object session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Get the JMS queue that represents the simulated inbox Destination inbox = (Destination)jndi.lookup("Inbox"); if ( inbox == null ) inbox = session.createQueue("Inbox"); // Create a producer to place messages into the inbox prod = session.createProducer(inbox); // The Connection must be started for messages to fly connection.start(); } catch ( Exception e ) { e.printStackTrace(); } } public void sendEmail(String subject, String body) throws Exception { ... } public static void main(String[] args) { ... } }
Listing One
The EmailSender
class initializes the JMS session in its constructor, and contains one additional method that lets the caller send e-mail messages to the queue representing the simulated e-mail inbox.
In the constructor, the first step is to use Java Naming and Directory Interface (java.sun.com/products/jndi) to get access to the JMS provider's javax.jms.ConnectionFactory
object. The provider-specific JNDI details are typically placed within a configuration file named jndi.properties. The Java VM automatically looks for the presence of this file when you instantiate the InitialContext
class.
Once a ConnectionFactory
object is obtained, a call to its createConnection
method returns a JMS javax.jms.Connection
object. This object represents an actual connection to the JMS provider. Because it's threadsafe and consumes a considerable amount of system resources to maintain, your application should require only one active Connection
object during its lifetime. Opening multiple connections to a JMS provider is usually unnecessary and a waste of resources.
Next, via a call to the Connection
object's createSession
method, the code creates a javax.jms.Session
object. A Session
object represents a working message session, and can only be used by one thread at a time within your code. Therefore, you should create a Session
object for each message producer and consumer thread in your application. The Session
object is used as a factory to create javax.jms.Destination
, javax.jms.Producer
, javax.jms
.Consumer
, and javax.jms.Message
objects.
The Session
object is used to create a reference to the "Inbox" queue by looking it up via JNDI and creates it on the fly if it's not found. Next, a message producer is created for the "Inbox" queue, which is used to send simulated e-mail messages. Finally, a call is made to the Connection
object's start
method to begin the flow of messages for the queue (and all destinations created through this JMS connection).
The sample application instantiates the EmailSender
class (available electronically) and calls its sendEmail
method twice to simulate sending two individual e-mail messages to the "Inbox" queue. The sendEmail
method first creates a plain-old Java object (POJO) that represents the e-mail message, of class Email
. Next, the Session
object (which was created in the constructor) is used to create a javax.jms.ObjectMessage
object that in turn is used to encapsulate the Email
POJO. Finally, the JMS message is actually sent via a call to the send
method on the queue's Producer
object.
Running the e-mail sender application results in the output in Figure 4. Because the simulated inbox is implemented as a JMS queue, the reader application does not need to be running at the same time as the sender.
Figure 4: Running e-mail sender application.
All of the messages sent to the queue will remain in the queue until the reader application executes and removes them.