EJB Messaging, Part I: JMS and JavaMail

he proliferation of enterprise applications (CRM, ERP, SCM, etc.) and disparate enterprise resources (RDBMS/OODBMS, legacy data store, data warehouse, XML/flat file repository, etc.) has required many a developer to integrate these applications into cohesive systems. In such an environment, enterprise messaging has arisen as a dominant integration solution and an increasingly important component of loosely coupled, yet reliable, enterprise frameworks.

Implementing enterprise messaging across a message-oriented middleware (MOM) system enables disparate systems to exchange messages in a reliable, loosely coupled manner, which improves overall performance and system maintainability.

This month’s 10-Minute Solution is the first in a two-part series examining the messaging options available to Enterprise Java Beans (EJBs) developers. This first part explains how EJBs participate in a messaging exchange and explores Java Message Service (JMS) and JavaMail resources, comparing their relative strengths and weaknesses as enterprise messaging conduits for your EJBs. Part 2 will take a close look at message-driven beans.

Author’s Note: This 10-Minute Solution requires a fundamental knowledge of several enterprise Java APIs, including EJB, JMS, JavaMail, and JNDI.



How can session and entity EJBs participate in a messaging exchange?



By utilizing resource manager connection factories, EJBs access extra-container resources, such as JMS and JavaMail sessions, for enterprise messaging.

EJBs and Resource Manager Connection Factories
An EJB’s participation in a messaging exchange begins with the resource manager. A resource manager is a J2EE component that manages the life cycle of a resource type, from connection pooling to transaction support to network communication. Through JNDI, the resource manager obtains factory objects called resource manager connection factories, which the container manages and maintains. EJBs use these resource manager connection factories to access extra-container resources (standard enterprise components that are not a core part of a J2EE container). JMS sessions and JavaMail sessions are among the resources an EJB can access with resource manager connection factories.

The EJB API uses the factory design pattern to provide access to resource manager connection objects. The factory pattern uses one class object (the factory) that returns references to objects of another class. This way, the factory class encapsulates the management of the resource connection objects, allowing caching, object recycling, and other types of optimizations. Additionally, the factory pattern separates the container’s implementation from the EJB code, allowing the maximum degree of extensibility and scalability.

The information corresponding to a resource manager connection factory is described in the bean’s deployment descriptor:

                         This is a textual description of 
the resource.
jms/topicConnFactory javax.jms.TopicConnectionFactory Container Sharable

The element identifies the JNDI name to which the connection factory reference should be bound. It is this name that is used in the enterprise bean code to obtain a reference. The element indicates the factory object type. The and elements declare how the factory will be managed.

Two of the elements, and , are optional.

EJBs and JMS Messaging
In order for your enterprise bean to obtain a connection to a JMS session, you must do one of the following:

  • Perform a JNDI lookup to obtain a connection factory reference
  • Obtain a connection via the factory reference
  • Use the topic or queue connection object in the normal fashion for JMS
The container typically maintains a single connection with the message broker, with multiple sessions (each with its own transaction context and acknowledgement mode) being allocated via the connection factory references. Two classes create these resource manager connection factory objects in JMS: javax.jms.QueueConnectionFactory and javax.jms.TopicConnectionFactory.

In addition to the standard deployment descriptor tags, JMS requires an additional declaration. The element defines administered objects, which are essentially container-managed singleton components. In the case of JMS, it declares a topic or queue for the J2EE container to manage:

    This is a textual description of the resource.   jms/PointToPoint   javax.jms.QueueConnectionFactory   Container   jms/MyQueue   javax.jms.Queue

The following code sample demonstrates how to obtain a reference to a JMS QueueConnection object based on the deployment descriptor settings above:

// Obtain the initial JNDI contextContext context = new InitialContext();// JNDI lookup to obtain resource manager connection factory referencejavax.jms.QueueConnectionFactory factory = (javax.jms.QueueConnectionFactory)             context.lookup(“java:comp/env/jms/PointToPoint”);// JNDI lookup to obtain a reference to the queue declared in the 
deployment descriptorjavax.jms.Queue queue = (javax.jms.Queue) context.lookup(“java:comp/env/jms/MyQueue”);// Invoke factory object to create connection objectjavax.jms.QueueConnection connection = factory.createQueueConnection();// Obtain a JMS session from the connection objectjavax.jms.QueueSession session = connection.createTopicSession( true, 0 );

At this point, you have a reference to a javax.jms.Session object and you are free to build QueueSender and QueueReceiver objects to be used in a point-to-point message exchange with other JMS clients.

EJBs and JavaMail Messaging
Obtaining a JavaMail session is considerably easier than obtaining a JMS session. You obtain a JavaMail session reference directly via a JNDI lookup; no additional method calls are required.

Assuming the following deployment descriptor settings:

    This is a textual description 
of the resource.
mail/Email javax.mail.Session Container

The code required to obtain a JavaMail session is as follows:

// Obtain the initial JNDI contextContext context = new InitialContext();// JNDI lookup to obtain resource manager connection 
factory referencejavax.mail.Session session = (javax.mail.Session) context.lookup(“java:comp/env/mail/Email”);

At this point you have a reference to a javax.jms.Session object and you are free to build QueueSender and QueueReceiver objects to be used in a point-to-point message exchange with other JMS clients.

JMS vs. JavaMail for EJB Messaging
In general, the choice between JMS and JavaMail is determined by the recipient’s technological infrastructure and the business case. If the recipients can receive e-mail (via SMTP, POP3, IMAP, etc.), then they can receive a message sent via the JavaMail API. If the only protocol available is HTTP, then you will need to use JMS. If both are available, examine the business case to make your determination.

Both JMS and JavaMail can create a loosely coupled, asynchronous messaging system. Both provide guaranteed delivery, and both support messaging models such as point-to-point and publish/subscribe. If the messaging exchange needs to be machine-driven (an application responds to the message) rather than human-driven, JMS provides a much cleaner and more powerful solution than JavaMail. Also, if the application requires messages to be exchanged with a transactional awareness or a complex routing scheme, or if it requires messages to be pulled sequentially off of a queue, JMS is clearly the way to go.

Flexibility and Reliability in Your Enterprise Architecture
Enterprise messaging is a powerful tool that lends tremendous flexibility and reliability to any enterprise architecture. In our world of increasingly disparate components and backend systems, messaging provides a clean abstraction layer that affords the right balance between system coupling and effective system communication. In this 10-Minute Solution, I explored two messaging options available to EJB developers, JMS and JavaMail, as extra-container resources. In the next, I will explore message-driven beans.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: