JMS support on GlassFish
Message-based solutions are playing an increasingly important role nowadays, as more and more systems need to be integrated together and need to communicate with each other in a loosely-coupled manner. In this section, we briefly introduce the core concepts of messaging system and the JMS standard, and then describe how GlassFish supports JMS resources.
Message-based systems and JMS
A simplified view of a typical message-based system is illustrated in the following figure.
As shown in the figure, the communication pattern of a messaging-based system is different from the client-server paradigm, where application components communicate with each other directly. Instead, in a message-based system, the communication among application components (producers and consumers) is mediated by a message service provider. As a result of this, a message service provider is sometimes referred to as a Message Oriented Middleware (MOM). The producer creates a message that contains relevant data, and sends it to a destination resource maintained by the message service provider. The message is then routed to consumer components that are registered to the specific destination.
Another distinct feature of a message-based system is that the message service provider effectively makes the communication between producers and consumers asynchronous. When a producer sends a message, consumers do not need to be available because the message service provider can persist the message until the consumer becomes available. In fact, the producer and consumer do not need to have any knowledge of each other, as long as the message is in a format that is agreed upon. This feature further decouples the producers and consumers.
JMS defines a standard Java API for application components to create, send, receive, and process messages. It also provides a standard API that simplifies how application components interact with a JMS-compliant message service provider (JMS provider for short). It defines the connection factory and destinations of the JMS provider in the form of administered objects, which can be registered in a JNDI naming service. An application component can use the standard JNDI API to perform a lookup operation to retrieve these resources. This approach reduces the vendor-dependency when we build a JMS application.
JMS defines the two messaging approaches as follows:
- Point-to-Point (PTP): A producer sends messages to a queue destination, which retains the messages until they are successfully routed to a consumer. Furthermore, each message is received by only one consumer.
- Publish/Subscribe (Pub/Sub): A producer sends messages to a topic destination. By default, the topic does not retain these messages. Instead, it immediately routes them to all the consumers registered for the topic. Due to this, if a message arrives at a topic when there is no active consumer, the message will be lost. To address this, JMS allows a consumer to be registered to the topic as durable subscriber. In this case, the JMS provider will retain the messages for this consumer until it becomes available.
The JMS API became an integral part of the Java EE since version 1.3 as the standard to integrate with messaging systems. Subsequent Java EE revisions further enhanced the JMS API and messaging system integration in the following areas:
- Message-Driven Beans (MDB): An MDB is a container-managed component that can asynchronously consume messages sent to a JMS destination. Due to this, we can consider an MDB as an asynchronous message listener component. The application server’s MDB container provides services for MDBs such as life cycle management, instance pooling and naming services. These services eliminate a lot of boiler-plate code necessary to create a message listener object. Due to this, when implementing an MDB, the developer only needs to focus on the logic about how to process messages delivered to the MDB. Furthermore, the MDB container’s instance pooling service can significantly improve the throughput of processing messages routed to a specific MDB.
- Java Connector Architecture (JCA): Through JCA resource adapters, JMS providers can be easily integrated into different application servers. Once integrated, application components can treat them as standard JCA resources, and interact with the resources in a provider-independent manner.
GlassFish support for JMS
The GlassFish Server contains a built-in JMS service provider, the Open MQ (https://mq.dev.java.net). It also includes a generic JCA resource adapter that can be used to integrate with most JMS providers. GlassFish also provides a configurable MDB container implementation to host message driven beans. In this article, we discuss how GlassFish integrates with two different JMS providers—the Open MQ and Apache ActiveMQ (http://activemq.apache.org). We also discuss how we can configure the MDB container and MDB components to work with a JMS service provider.
One of the most commonly asked questions is “Which JMS provider is better, or at least which open source JMS provider is better?”. The answer to this question typically depends heavily on the experience of the individual or organization. Most reputable JMS implementations, including Open MQ and ActiveMQ are capable of processing large volumes of messages efficiently.
Between Open MQ and ActiveMQ, my personal favorite choice is the former. The reason is not because Open MQ is bundled in GlassFish. It is actually because my experience with the Open MQ product dates back to the days of its commercial ancestor, the Sun ONE Message Queue. I have always appreciated its straightforward administration interface and thorough documentation. Furthermore, I have successfully created many production deployments by using the product. Make no mistake though; I have also witnessed organizations using ActiveMQ successfully in production. Also, ActiveMQ is under active development, and it is bundled in several very good open source products as the default JMS provider.
Now, let’s discuss how GlassFish works with the Open MQ product (https://mq.dev.java.net).
Getting started with Open MQ
An evolution of the Sun Java System Message Queue (formerly Sun ONE Message Queue), Open MQ is a very active open source sub-project of GlassFish. Open MQ implements a high-performance JMS provider. In addition to its high performance, and being fully JMS compliant, Open MQ provides many other features, such as message broker cluster support, SOAP/HTTP message support, C/C++ Client API support, and so on. Due to this, some people said Open MQ was the best kept secret within the Sun middleware software stack.
The GlassFish Server is shipped with the Open MQ product. In addition, the GlassFish administration infrastructure provides some basic capabilities for configuring the Open MQ.
The open source distribution of the GlassFish server you download from the GlassFish project site includes the “community edition” of Open MQ. This edition does not include some of the additional features such as C-API support. If you need to use these features, you can either download or install the Sun supported GlassFish Enterprise Server distribution, or download and install a full version of the Open MQ product. We should expect that in future versions of GlassFish, the bundled Open MQ will be a feature-complete distribution.
By default, the bundled Open MQ is configured to have a small footprint without many advanced features. In this section, we will first get familiar with the Open MQ product, and later in this article we will show you how to configure the Open MQ to work with GlassFish and Java EE application components.
First, let’s examine the high-level architecture of GlassFish, and learn the meaning of some critical concepts along the way.
The architecture of Open MQ
The high-level architecture of Open MQ is illustrated in the following figure.
The main components illustrated in this figure are explained as follows:
- The Broker can be considered as a complete instance of the message provider. A broker contains physical destinations (both queues and topics), and it is responsible for routing messages sent from producers to the appropriate destination, and delivering messages from destinations to registered consumers. The broker supports multiple connection mechanisms between application components and the broker, and it can also be configured with different performance and security features.
- In order to simplify and standardize the JMS programming model, JMS defines two types of administered objects—connection factories and destinations. A Connection Factory is an object that encapsulates all the vendor-specific information necessary for a client to establish a connection to the broker, and the destination object provides a logical reference to a physical destination. These two administered objects are registered in a JNDI-compliant object store, and a client can perform a standard JNDI lookup to retrieve these objects. Once these objects are retrieved, the client can produce and consume messages.
A client can create these objects programmatically. For example, a client may want to use some vendor-specific features or APIs that cannot be encapsulated in a standard manner. However, this practice is highly discouraged.
The directory structure of Open MQ
The binary of the Open MQ software bundled with GlassFish is installed at$AS_INSTALL/imq. The high-level directory structure and essential files are described as follows:
- The bin directory contains the command line and GUI utilities for administering and controlling the MQ. The essential utilities include:
- imqadmin: The Open MQ GUI-based administration console.
- imqbrokerd: The broker management utility.
- imqcmd: The command-line administration utility of Open MQ.
- imqdbmgr: The utility to manage a JDBC-based message store.
- imqkeytool: The utility to generate self-signed SSL certifi cate for a broker.
- imqobjmgr: The utility to manage administered objects, including connection factory and destinations.
- imqusermgr: The utility to manage the flat file user repository for the Open MQ.
- The demo directory contains a variety of demo applications for Open MQ.
- The etc directory contains the Open MQ server-wide configuration file— imqenv.conf. This file effectively defines the environment variables for the Open MQ installation. For example, you should find the following line near the end of the file:IMQ_DEFAULT_VARHOME=/opt/glassfish/domains/domain1/imq This line specifi es that by default, all the brokers created within this Open MQ installation will be inside the /opt/glassfish/domains/domain1/imq directory.
- The include directory contains the C API header files for building C-based clients.
- The javadoc contains the Java API documentation for Open MQ.
- The lib directory contains the Java and C libraries for the Open MQ.
- The var directory is empty. In a standalone installation, this directory is the default root directory for all the brokers created.
Once GlassFish is installed, a default OpenMQ broker, imqbroker is also created within the default domain in $AS_INSTALL/domains/domain1/imq/instances/imqbroker. The main content of this directory includes:
- The etc directory contains two files, the passwd is a password file for users configured for the broker, and the accesscontrol.properties file allows us to specify different types of access controls for different users.
- The fs370 directory is the flat file-based persistence store for messages and transactions.
- The log directory contains the rotated log files of running the broker.
- The props directory contains the config.properties file, which describes most of the properties configured for the broker.
In the following section, we show you how to configure Open MQ.