Contact Us 1-800-596-4880

JMS Connector - Mule 4

JMS Connector v1.7

Anypoint Connector for JMS (JMS Connector) enables your app to do messaging using the JMS implementation of your choice. Its main features include:

  • Pub/Sub pattern support on any given destination.

  • Listen/Reply pattern support on any given destination.

  • Publish-Consume pattern support on any given destination, with fixed or temporary reply Queue.

  • Fully compliant with JMS 2.0, 1.1, and 1.0.2 specifications.

Release Notes: JMS Connector Release Notes
Exchange: JMS Connector

The JMS documentation set provides information about multiple versions of the JMS connector.

For information about each Mule 4 JMS Connector version, see:

POM File Information

<dependency>
  <groupId>org.mule.connectors</groupId>
  <artifactId>mule-jms-connector</artifactId>
  <version>x.x.x</version>
  <classifier>mule-plugin</classifier>
</dependency>

Replace x.x.x with the version that corresponds to the connector you are using. To specify a version, view JMS Connector in Anypoint Exchange and click Dependency Snippets.

Configure the Connector

Out of the box, the JMS connector comes with a fine tuned set of default values, both for publishing and consuming messages. This means that the only requirement is for you to configure which connection should be used.

This example sets a minimal connection to an in-memory ActiveMQ broker the JMS connector:

<jms:config name="JMS_Config">
  <jms:active-mq-connection/>
</jms:config>

Define Global Defaults

The JMS config allows you to define multiple parameters that will be used as a default while consuming or publishing messages. This way, you can define a global default behavior for all the operations associated the config and then override each parameter only in the operations that require a custom behavior.

For example, we can define a default selector behavior when consuming a Message in any of the operations that are associated to this config, and also a default

<jms:config name="JMS_Config">
  <jms:active-mq-connection/>
  <jms:consumer-config selector="JMSType = `INVOICE`"/>
  <jms:producer-config timeToLive="60000"/>
</jms:config>

In this case, every operation consume or listener associated to this config will use this selector by default, while every time we do a publish or publish-consume, the outgoing Message will have a TTL of 60 seconds.

All of this properties can be overridden at operation level when required. Let’s say we need to publish a Message with a shorter TTL, we can do so using this config and overriding the parameter:

<jms:publish config-ref="JMS_Config" timeToLive="10000"/>

Connecting to a Broker

A JMS connection is defined by a set of general parameters that apply for any connection, as well as particular configurations related to the actual broker implementation that’s going to be used.

Select the JMS Spec

The main common parameter is the JMS specification used to select between all the supported specs, which are 2.0, 1.1, and 1.0.2b. This specification must be supported by the broker implementation associated to this connection, otherwise the connection fails.
Features available only in JMS 2.0 won’t work with any other specification.

Provide Credentials For Authentication

In order to do establish an authenticated connection, you need to configure the username and password in the connection element:

<jms:config name="JMS_Config">
  <jms:active-mq-connection username="${env.user}" password="${env.pass}"/>
</jms:config>

Configure Connections Caching

In order to connect with a broker and execute the required operations, the JMS Connector creates multiple Sessions, Consumers and Producers that can be cached and reused in order to increase the performance of the application. Because of this capability, the JMS Connector allows you to configure which caching-strategy to use when creating new Connections, caching by default both Consumers and Producers and preserving as many instances as possible in memory at the same time.

Customizing the cache configuration can be done directly in the connection declaration:

<jms:config name="JMS_Config">
  <jms:active-mq-connection>
    <jms:caching-strategy>
      <jms:default-caching sessionCacheSize="100" consumersCache="false" producersCache="true"/>
    </jms:caching-strategy>
  </jms:active-mq-connection>
</jms:config>

In the same way, you can completely disable the caching of Connections using the no-caching option:

<jms:config name="JMS_Config">
  <jms:generic-connection connectionFactory="customConnectionFactory">
    <jms:caching-strategy>
        <jms:no-caching/>
    </jms:caching-strategy>
  </jms:generic-connection>
</jms:config>
Disabling the sessions cache using the no-caching configuration is greatly discouraged and is meant to be used in cases where a custom ConnectionFactory is used that already handles it`s own cache.

Identify the Connection Client

The purpose of client identifier is to associate a connection and its objects with a state maintained on behalf of the client by a provider, and it is mandatory for identifying an unshared durable subscription.

<jms:config name="JMS_Config">
  <jms:active-mq-connection clientId="${env.clientId}"/>
</jms:config>
By definition, the client state identified by a clientId can be "in use" by only one Connection at a time.

Connect To ActiveMQ

Support for ActiveMQ 5 is provided out of the box by the connector using the active-mq-connection. With this connection, you can use both JMS 1.1 (the default) or JMS 1.0.2b specs, and configure all the general connection parameters for JMS, as well as the custom parameters only present in ActiveMQ.

Once we declare the active-mq-connection, all that`s left to do is set up the connection factory with our custom configuration. Every parameter in the connection comes with a default value, meaning that you are required to configure only the parameters relevant for your use case. Also, the ActiveMQ connection exposes parameters that are exclusive of ActiveMQ implementation, like initialRedeliveryDelay.

An example of a simple configuration of an ActiveMQ connection would be:

 <jms:config name="JMS_Config">
  <jms:active-mq-connection >
   <jms:factory-configuration brokerUrl="tcp://localhost:61616" />
  </jms:active-mq-connection>
 </jms:config>

Use Different Brokers

In cases where ActiveMQ 5 is not the chosen broker, we can use the generic-connection to declare a connection to any broker implementation. Out of the box, the connector provides a JNDI based connection factory builder that allows to configure the connection using JNDI in the context of the application.

For example, if we want to connect with Artemis to use the JMS 2.0 spec, we could define our connection factory in this way:

<jms:config name="JMS_Config">
    <jms:generic-connection specification="JMS_2_0">
        <jms:connection-factory>
            <jms:jndi-connection-factory connectionFactoryJndiName="ConnectionFactory" lookupDestination="ALWAYS">
                <jms:name-resolver-builder
                        jndiInitialContextFactory="org.apache.activemq.artemis.ActiveMQInitialContextFactory"
                        jndiProviderUrl="tcp://localhost:61616?broker.persistent=false&amp;broker.useJmx=false">
                    <jms:provider-properties>
                        <jms:provider-property key="queue.jndi-queue-in" value="in.queue"/>
                        <jms:provider-property key="topic.jndi-topic-in" value="in.topic"/>
                    </jms:provider-properties>
                </jms:name-resolver-builder>
            </jms:jndi-connection-factory>
        </jms:connection-factory>
    </jms:generic-connection>
</jms:config>

If you have configured a JNDI context on the connector, you can also look up destinations via JNDI using the lookupDestination attribute, which provides three different configurations:

  • NEVER: No lookup is done and the destinations are created using the existing JMS session

  • TRY_ALWAYS: First try to find the destination using JNDI, and in case it doesn’t exist, create it using the current JMS Session.

  • ALWAYS: If a queue/topic cannot be found via JNDI, fail with a JMS:DESTINATION_NOT_FOUND error

For more information regarding the generic-connection or jndi-connection-factory, see the connector reference docs.

Set Up the Connection Libraries

No matter what type of connection you are using, you always need to configure a library containing the JMS client implementation since the connector is not bound to any particular implementation.

ActiveMQ External Libraries

For an ActiveMQ connection, there are three possible libraries that need to be configured depending on your connection settings:

  • ActiveMQ JMS Client Library:

The activemq-client of your choice that provides a valid org.apache.activemq.ActiveMQConnectionFactory implementation.

This dependency is always required.

For example, you can use:

<dependency>
     <groupId>org.apache.activemq</groupId>
     <artifactId>activemq-client</artifactId>
     <version>5.14.5</version>
 </dependency>
  • ActiveMQ Broker Library:

The activemq-broker is only required when using an in-memory broker based on the VM transport (which is the one configured by default). This dependency should provide a valid org.apache.activemq.broker.Broker implementation.

For example, you can use:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-broker</artifactId>
    <version>5.14.5</version>
</dependency>
  • ActiveMQ KahaDB Library:

The activemq-kahadb-store is only required when using an persistent in-memory broker based on the VM transport (such as, vm://localhost?broker.persistent=true). This dependency provides a valid org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter implementation.

For example, you can use:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-kahadb-store</artifactId>
    <version>5.14.5</version>
</dependency>

Generic External Libraries

When using a jms:generic-connection, provide all the libraries that your ConnectionFactory and configuration of choice required. This will always depend on what are the implementations you choose, so be careful of adding all the dependencies to the application.

A common use case for this would be using the JMS 2.0 spec, thus you need a generic connection with a different client library, like Apache Artemis:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>artemis-jms-client-all</artifactId>
    <version>2.13.0</version>
</dependency>
View on GitHub