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.
Configuring Open MQ
There are two ways to configure and administer the Open MQ server product:
- The first option is to use the JMS configuration capability built into the GlassFish's administrative infrastructure, such as Admin Console and the asadmin CLI utility. This option has the advantage of being simple, because we use the familiar GlassFish administration interfaces. The drawback of this option, however, is that the capability is limited. For example, we cannot create a multi-broker cluster.
- The second option relies on the tools provided in the Open MQ binary discussed in the previous section, such as imqbrokerd and imqadmin. This option has the advantage of having full control of the Open MQ. The drawback of this approach is that we need to use a completely different set of tools, rather than the GlassFish Server.
In the following sections, we discuss the essential configuration tasks for Open MQ:
- Configuring the Open MQ runtime environment
- Configuring the physical destinations within Open MQ
- Configuring administrative objects, including connection factories and destination
First, let's look at how to configure Open MQ using the GlassFish administration interfaces.
Configuring Open MQ within GlassFish
By default, when we start the GlassFish Server, the server process starts the Open MQ's default broker using a separate thread. Once successfully started, the broker listens on the default port 7676 for client connection requests.
Configuring the Open MQ Runtime
To configure the Open MQ Runtime environment, complete the following steps:
- Log on to the Admin Console.
- In the navigation panel, expand the Configuration node, and click the Java Message Service node, as shown in the following image.
The Admin Console displays the properties of the JMS Service configured with Open MQ as the JMS provider. Using the Admin Console, we can configure many properties that determine how GlassFish maintains the connection with the Open MQ broker. For example, whether GlassFish will attempt to reconnect to the Open MQ broker if a connection is lost, and the frequency with which reconnection attempts are carried out. The Admin Console Help document provides detailed definitions for these properties.
These properties can also be managed using the get or set commands of theasadmin CLI utility. For example, to check if reconnection attempts are allowed, we can use the following command:
# cd $AS_INSTALL/bin
# ./asadmin get server.jms-service.reconnect-enabled
Also, as we can see in this diagram, the default runtime type of Open MQ isEMBEDDED. The embedded execution type runs both the GlassFish Server and the Open MQ in the same process, thus, it has a very small memory footprint. However, it is not very reliable, because both GlassFish and Open MQ run in the same JVM. If one of them has issues, such as a memory leak, then the other server will also be affected.
The other two runtime types are LOCAL and REMOTE. In the LOCAL runtime type, GlassFish and Open MQ run in two separate JVM processes. When we use the asadmin CLI to start/stop the GlassFish Server, the Open MQ process is also started/stopped. The LOCAL runtime mode is more reliable because the server processes are independent of each other.
Under the REMOTE runtime type, the GlassFish Server does not control the life cycle of the Open MQ server. Instead, GlassFish will communicate with the Open MQ broker instance running on the host identified by the Default_JMS_Host property, as shown in the screenshot. Notice that value of the Default_JMS_Host property must be predefined as a valid JMS host. This can be done by clicking the JMS Hosts node in the navigation panel, and adding new JMS host values.
Notice that when we switch the runtime nodes, we need to restart GlassFish to make sure that the change is persistent.
Under the EMBEDDED and LOCAL types, we can use the GlassFish Admin Console to create and delete physical JMS destinations in the Open MQ broker instance. To do this, click the Physical Destinations node in the navigation panel. The main content panel lists the existing destinations, and it also provides the options for creating and deleting physical destinations. Physical destinations can also be created using the create-jmsdest command of the asadmin CLI utility.
Now that we have Open MQ runtime configured, in the next section, let's discuss how to configure JMS resources in GlassFish so that they can be used by our applications, such as message-driven beans and clients that produce messages.
Configuring the JMS Resources
To configure JMS Resources, complete the following steps:
- Log on to the Admin Console.
- In the navigation panel, expand the Resources node, and then expand the JMS Resources node.
The Admin Console displays the JMS resources, as shown in the following screenshot.
As we can see, the two types of JMS resources we can configure are JMS Connection Factories, and Destination Resources.
To create a connection factory, click the Connection Factories node in the navigation panel, and click New in the main content panel. In the new connection factory form, we need to specify the following information:
- The JNDI name of the connection factory, which typically starts with a prefixjms, such as jms/MyCF.
- The type of the connection factory, which should be javax.jms. ConnectionFactory for JMS 1.1 compliant JMS providers and clients, as it provides a unified interface for both queue and topic connection factories.
- Necessary additional properties. If we are using the Open MQ running in the EMBEDDED or LOCAL mode, then we don't need to provide any additional information. If we are using a remote JMS broker, then we should add a new property—AddressList—and set the value to a comma-separated list of host:port combinations. This list describes the locations where the Open MQ broker or broker cluster is running.
To create a destination resource, in the Admin Console, click the Destination Resources node in the navigation panel, and click New in the main content panel. In the new destination resource form, we need to specify the following information:
- The JNDI name of the destination, which typically starts with a prefix jms, such as jms/MyQueue.
- The name of the Physical Destination applied to the destination resource.
- The type of the connection factory, which could be javax.jms.Queue or javax.jms.Topic.
Once the JMS resources are created, we can create and deploy applications to take advantage of these resources. In the example directory, a very simple MDB and a JMS application client are provided. Please refer to the example README file for more information.
As discussed earlier in the Open MQ architecture, physical destinations are maintained by the Open MQ broker instance, not by GlassFish. Due to this, the GlassFish Admin Console does not provide options to configure properties of the physical destination, such as durable subscriptions for topics. In order to configure these properties, we have to use the Open MQ's standalone tools, which will be presented later in this article.
If you have read this article you may be interested to view :