[[Messaging]]
= Messaging configuration

The JMS server configuration is done through the _messaging-activemq_
subsystem. In this chapter we are going outline the frequently used
configuration options. For a more detailed explanation please consult
the Artemis user guide (See "Component Reference").

[[required-extension-messaging]]
== Required Extension

The configuration options discussed in this section assume that the the
`org.wildfly.extension.messaging-activemq` extension is present in your
configuration. This extension is not included in the standard
`standalone.xml` and `standalone-ha.xml` configurations included in the
WildFly distribution. It is, however, included with the
`standalone-full.xml` and `standalone-full-ha.xml` configurations.

You can add the extension to a configuration without it either by adding
an `<extension module="org.wildfly.extension.messaging-activemq"/>`
element to the xml or by using the following CLI operation:

[source,options="nowrap"]
----
[standalone@localhost:9990 /]/extension=org.wildfly.extension.messaging-activemq:add
----

[[connectors]]
== Connectors

There are three kind of connectors that can be used to connect to
WildFly JMS Server

* `invm-connector` can be used by a local client (i.e. one running in
the same JVM as the server)
* `netty-connector` can be used by a remote client (and uses Netty over
TCP for the communication)
* `http-connector` can be used by a remote client (and uses Undertow Web
Server to upgrade from a HTTP connection)

[[jms-connection-factories]]
== JMS Connection Factories

There are three kinds of _basic_ JMS `connection-factory` that depends
on the type of connectors that is used.

There is also a `pooled-connection-factory` which is special in that it
is essentially a configuration facade for _both_ the inbound and
outbound connectors of the the Artemis JCA Resource Adapter. An MDB can
be configured to use a `pooled-connection-factory` (e.g. using
`@ResourceAdapter`). In this context, the MDB leverages the _inbound
connector_ of the Artemis JCA RA. Other kinds of clients can look up the
pooled-connection-factory in JNDI (or inject it) and use it to send
messages. In this context, such a client would leverage the _outbound
connector_ of the Artemis JCA RA. A `pooled-connection-factory` is also
special because:

* It is only available to local clients, although it can be configured
to point to a remote server.
* As the name suggests, it is pooled and therefore provides superior
performance to the clients which are able to use it. The pool size can
be configured via the `max-pool-size` and `min-pool-size` attributes.
* It should only be used to _send_ (i.e. produce) messages when looked
up in JNDI or injected.
* It can be configured to use specific security credentials via the
`user` and `password` attributes. This is useful if the remote server to
which it is pointing is secured.
* Resources acquired from it will be automatically enlisted any on-going
JTA transaction. If you want to send a message from an EJB using CMT
then this is likely the connection factory you want to use so the send
operation will be atomically committed along with the rest of the EJB's
transaction operations.

To be clear, the _inbound connector_ of the Artemis JCA RA (which is for
consuming messages) is only used by MDBs and other JCA-based components.
It is not available to traditional clients.

Both a `connection-factory` and a `pooled-connection-factory` reference
a `connector` declaration.

A `netty-connector` is associated with a `socket-binding` which tells
the client using the `connection-factory` where to connect.

* A `connection-factory` referencing a `netty-connector` is suitable to
be used by a _remote_ client to send messages to or receive messages
from the server (assuming the connection-factory has an appropriately
exported `entry`).
* A `pooled-connection-factory` looked up in JNDI or injected which is
referencing a `netty-connector` is suitable to be used by a _local_
client to send messages to a remote server granted the `socket-binding`
references an `outbound-socket-binding` pointing to the remote server in
question.
* A `pooled-connection-factory` used by an MDB which is referencing a
`remote-connector` is suitable to consume messages from a remote server
granted the `socket-binding` references an `outbound-socket-binding`
pointing to the remote server in question.

An `in-vm-connector` is associated with a `server-id` which tells the
client using the `connection-factory` where to connect (since multiple
Artemis servers can run in a single JVM).

* A `connection-factory` referencing an `in-vm-connector` is suitable to
be used by a _local_ client to either send messages to or receive
messages from a local server.
* A `pooled-connection-factory` looked up in JNDI or injected which is
referencing an `in-vm-connector` is suitable to be used by a _local_
client only to send messages to a local server.
* A `pooled-connection-factory` used by an MDB which is referencing an
`in-vm-connector` is suitable only to consume messages from a local
server.

A `http-connector` is associated with the `socket-binding` that
represents the HTTP socket (by default, named `http`).

* A `connection-factory` referencing a `http-connector` is suitable to
be used by a remote client to send messages to or receive messages from
the server by connecting to its HTTP port before upgrading to the
messaging protocol.
* A `pooled-connection-factory` referencing a `http-connector` is
suitable to be used by a local client to send messages to a remote
server granted the `socket-binding` references an
`outbound-socket-binding` pointing to the remote server in question.
* A `pooled-connection-factory` used by an MDB which is referencing a
`http-connector` is suitable only to consume messages from a remote
server granted the `socket-binding` references an
`outbound-socket-binding` pointing to the remote server in question.

The `entry` declaration of a `connection-factory` or a
`pooled-connection-factory` specifies the JNDI name under which the
factory will be exposed. Only JNDI names bound in the
`"java:jboss/exported"` namespace are available to remote clients. If a
`connection-factory` has an entry bound in the `"java:jboss/exported"`
namespace a remote client would look-up the `connection-factory` using
the text _after_ `"java:jboss/exported"`. For example, the "
`RemoteConnectionFactory`" is bound by default to
`"java:jboss/exported/jms/RemoteConnectionFactory"` which means a remote
client would look-up this `connection-factory` using "
`jms/RemoteConnectionFactory`". A `pooled-connection-factory` should
_not_ have any `entry` bound in the " `java:jboss/exported`" namespace
because a `pooled-connection-factory` is not suitable for remote
clients.

Since JMS 2.0, a default JMS connection factory is accessible to EE
application under the JNDI name `java:comp/DefaultJMSConnectionFactory.`
WildFly messaging subsystem defines a `pooled-connection-factory` that
is used to provide this default connection factory. Any parameter change
on this `pooled-connection-factory` will be take into account by any EE
application looking the default JMS provider under the JNDI name
`java:comp/DefaultJMSConnectionFactory.`

[source,xml,options="nowrap"]
----
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
    <server name="default">
        [...]
        <http-connector name="http-connector"
                        socket-binding="http"
                        endpoint="http-acceptor" />
        <http-connector name="http-connector-throughput"
                        socket-binding="http"
                        endpoint="http-acceptor-throughput">
            <param name="batch-delay"
                   value="50"/>
        </http-connector>
        <in-vm-connector name="in-vm"
                         server-id="0"/>
      [...]
      <connection-factory name="InVmConnectionFactory"
                            connectors="in-vm"
                            entries="java:/ConnectionFactory" />
      <pooled-connection-factory name="activemq-ra"
                            transaction="xa"
                            connectors="in-vm"
                            entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory"/>
      [...]
   </server>
</subsystem>
----

~(See standalone/configuration/standalone-full.xml)~

[[jms-queues-and-topics]]
== JMS Queues and Topics

JMS queues and topics are sub resources of the messaging-actively
subsystem. One can define either a `jms-queue` or `jms-topic`. Each
destination _must_ be given a `name` and contain at least one entry in
its `entries` element (separated by whitespace).

Each entry refers to a JNDI name of the queue or topic. Keep in mind
that any `jms-queue` or `jms-topic` which needs to be accessed by a
remote client needs to have an entry in the "java:jboss/exported"
namespace. As with connection factories, if a `jms-queue` or or
`jms-topic` has an entry bound in the "java:jboss/exported" namespace a
remote client would look it up using the text _after_
`"java:jboss/exported`". For example, the following `jms-queue`
"testQueue" is bound to "java:jboss/exported/jms/queue/test" which means
a remote client would look-up this \{\{kms-queue} using
"jms/queue/test". A local client could look it up using
"java:jboss/exported/jms/queue/test", "java:jms/queue/test", or more
simply "jms/queue/test":

[source,xml,options="nowrap"]
----
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
    <server name="default">
    [...]
    <jms-queue name="testQueue"
               entries="jms/queue/test java:jboss/exported/jms/queue/test" />
    <jms-topic name="testTopic"
               entries="jms/topic/test java:jboss/exported/jms/topic/test" />
</subsystem>
----

~(See standalone/configuration/standalone-full.xml)~

JMS endpoints can easily be created through the CLI:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] jms-queue add --queue-address=myQueue --entries=queues/myQueue
----

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=messaging-activemq/server=default/jms-queue=myQueue:read-resource
{
    "outcome" => "success",
    "result" => {
        "durable" => true,
        "entries" => ["queues/myQueue"],
        "selector" => undefined
    }
}
----

A number of additional commands to maintain the JMS subsystem are
available as well:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] jms-queue --help --commands
add
...
remove
To read the description of a specific command execute 'jms-queue command_name --help'.
----

[[dead-letter-redelivery]]
== Dead Letter & Redelivery

Some of the settings are applied against an address wild card instead of
a specific messaging destination. The dead letter queue and redelivery
settings belong into this group:

[source,xml,options="nowrap"]
----
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
   <server name="default">
      [...]
      <address-setting name="#"
                       dead-letter-address="jms.queue.DLQ"
                       expiry-address="jms.queue.ExpiryQueue"
                       [...] />
----

~(See standalone/configuration/standalone-full.xml)~

[[security-settings-for-artemis-addresses-and-jms-destinations]]
== Security Settings for Artemis addresses and JMS destinations

Security constraints are matched against an address wildcard, similar to
the DLQ and redelivery settings.

[source,xml,options="nowrap"]
----
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
   <server name="default">
      [...]
      <security-setting name="#">
          <role name="guest"
                send="true"
                consume="true"
                create-non-durable-queue="true"
                delete-non-durable-queue="true"/>
----

~(See standalone/configuration/standalone-full.xml)~

[[security-domain-for-users]]
== Security Domain for Users

By default, Artemis will use the " `other`" JAAS security domain. This
domain is used to authenticate users making connections to Artemis and
then they are authorized to perform specific functions based on their
role(s) and the `security-settings` described above. This domain can be
changed by using the `security-domain`, e.g.:

[source,xml,options="nowrap"]
----
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
   <server name="default">
       <security domain="mySecurityDomain" />
      [...]
----

[[using-the-elytron-subsystem]]
== Using the Elytron Subsystem

You can also use the elytron subsystem to secure the messaging-activemq
subsystem.

To use an Elytron security domain:

. Undefine the legacy security domain.
+
[source,options="nowrap"]
----
/subsystem=messaging-activemq/server=default:undefine-attribute(name=security-domain)
----
. Set an Elytron security domain.
+
[source,options="nowrap"]
----
/subsystem=messaging-activemq/server=default:write-attribute(name=elytron-domain, value=myElytronSecurityDomain)
----

[IMPORTANT]

You can only define either `security-domain` or `elytron-domain`, but
you cannot have both defined at the same time. If neither is defined,
WildFly will use the `security-domain` default value of `other`, which
maps to the `other` legacy security domain.

[[cluster-authentication]]
== Cluster Authentication

If the Artemis server is configured to be clustered, it will use the
`cluster` 's `user` and `password` attributes to connect to other
Artemis nodes in the cluster.

If you do not change the default value of <cluster-password>, Artemis
will fail to authenticate with the error:

[source,options="nowrap"]
----
HQ224018: Failed to create session: HornetQExceptionerrorType=CLUSTER_SECURITY_EXCEPTION message=HQ119099: Unable to authenticate cluster user: HORNETQ.CLUSTER.ADMIN.USER
----

To prevent this error, you must specify a value for
`<cluster-password>`. It is possible to encrypt this value by following
https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Application_Platform/6.1/html/Security_Guide/sect-Password_Vaults_for_Sensitive_Strings.html[this
guide].

Alternatively, you can use the system property
jboss.messaging.cluster.password to specify the cluster password from
the command line.

[[deployment-of--jms.xml-files]]
== Deployment of -jms.xml files

Starting with WildFly {wildflyVersion}, you have the ability to deploy a -jms.xml file
defining JMS destinations, e.g.:

[source,xml,options="nowrap"]
----
<?xml version="1.0" encoding="UTF-8"?>
<messaging-deployment xmlns="urn:jboss:messaging-activemq-deployment:1.0">
   <server name="default">
      <jms-destinations>
         <jms-queue name="sample">
            <entry name="jms/queue/sample"/>
            <entry name="java:jboss/exported/jms/queue/sample"/>
         </jms-queue>
      </jms-destinations>
   </server>
</messaging-deployment>
----

WARNING: This feature **is primarily intended for development** as destinations
deployed this way can not be managed with any of the provided management
tools (e.g. console, CLI, etc).

[[jms-bridge]]
== JMS Bridge

The function of a JMS bridge is to consume messages from a source JMS
destination, and send them to a target JMS destination. Typically either
the source or the target destinations are on different servers.
The bridge can also be used to bridge messages from other non Artemis
JMS servers, as long as they are JMS 1.1 compliant.

The JMS Bridge is provided by the Artemis project. For a detailed
description of the available configuration properties, please consult
the project documentation.

[[modules-for-other-messaging-brokers]]
=== Modules for other messaging brokers

Source and target JMS resources (destination and connection factories)
are looked up using JNDI.
If either the source or the target resources are managed by another
messaging server than WildFly, the required client classes must be
bundled in a module. The name of the module must then be declared when
the JMS Bridge is configured.

The use of a JMS bridges with any messaging provider will require to
create a module containing the jar of this provider.

Let's suppose we want to use an hypothetical messaging provider named
AcmeMQ. We want to bridge messages coming from a source AcmeMQ
destination to a target destination on the local WildFly messaging
server. To lookup AcmeMQ resources from JNDI, 2 jars are required,
acmemq-1.2.3.jar, mylogapi-0.0.1.jar (please note these jars do not
exist, this is just for the example purpose). We must _not_ include a
JMS jar since it will be provided by a WildFly module directly.

To use these resources in a JMS bridge, we must bundle them in a WildFly
module:

in JBOSS_HOME/modules, we create the layout:

[source,options="nowrap"]
----
modules/
`-- org
    `-- acmemq
        `-- main
            |-- acmemq-1.2.3.jar
            |-- mylogapi-0.0.1.jar
            `-- module.xml
----

We define the module in `module.xml`:

[source,xml,options="nowrap"]
----
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.acmemq">
    <properties>
        <property name="jboss.api" value="private"/>
    </properties>
 
 
    <resources>
        <!-- insert resources required to connect to the source or target   -->
        <!-- messaging brokers if it not another WildFly instance           -->
        <resource-root path="acmemq-1.2.3.jar" />
        <resource-root path="mylogapi-0.0.1.jar" />
    </resources>
 
 
    <dependencies>
       <!-- add the dependencies required by JMS Bridge code                -->
       <module name="javax.api" />
       <module name="javax.jms.api" />
       <module name="javax.transaction.api"/>
       <module name="org.jboss.remote-naming"/>
       <!-- we depend on org.apache.activemq.artemis module since we will send messages to  -->
       <!-- the Artemis server embedded in the local WildFly instance       -->
       <module name="org.apache.activemq.artemis" />
    </dependencies>
</module>
----

[[configuration]]
=== Configuration

A JMS bridge is defined inside a `jms-bridge` section of the
`messaging-activemq` subsystem in the XML configuration files.

[source,xml,options="nowrap"]
----
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
   <jms-bridge name="myBridge" module="org.acmemq">
      <source connection-factory="ConnectionFactory"
              destination="sourceQ"
              user="user1"
              password="pwd1"
              quality-of-service="AT_MOST_ONCE"
              failure-retry-interval="500"
              max-retries="1"
              max-batch-size="500"
              max-batch-time="500"
              add-messageID-in-header="true">
         <source-context>
            <property name="java.naming.factory.initial"
                      value="org.acmemq.jndi.AcmeMQInitialContextFactory"/>
            <property name="java.naming.provider.url"
                      value="tcp://127.0.0.1:9292"/>
         </source-context>
      </source>
      <target connection-factory"/jms/invmTargetCF"
              destination="/jms/targetQ" />
      </target>
   </jms-bridge>
</subsystem>
----

The `source` and `target` sections contain the name of the JMS resource
( `connection-factory` and `destination`) that will be looked up in
JNDI.
It optionally defines the `user` and `password` credentials. If they are
set, they will be passed as arguments when creating the JMS connection
from the looked up ConnectionFactory.
It is also possible to define JNDI context properties in the
`source-context` and `target-context` sections. If these sections are
absent, the JMS resources will be looked up in the local WildFly
instance (as it is the case in the `target` section in the example
above).

[[management-commands]]
=== Management commands

A JMS Bridge can also be managed using the WildFly command line
interface:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=myBridge/:add(module="org.acmemq",
      source-destination="sourceQ",
      source-connection-factory="ConnectionFactory",
      source-user="user1",
      source-password="pwd1",
      source-context={"java.naming.factory.initial" => "org.acmemq.jndi.AcmeMQInitialContextFactory",
                      "java.naming.provider.url" => "tcp://127.0.0.1:9292"},
      target-destination="/jms/targetQ",
      target-connection-factory="/jms/invmTargetCF",
      quality-of-service=AT_MOST_ONCE,
      failure-retry-interval=500,
      max-retries=1,
      max-batch-size=500,
      max-batch-time=500,
      add-messageID-in-header=true)
{"outcome" => "success"}
----

You can also see the complete JMS Bridge resource description from the
CLI:

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=*/:read-resource-description
{
    "outcome" => "success",
    "result" => [{
        "address" => [
            ("subsystem" => "messaging"),
            ("jms-bridge" => "*")
        ],
        "outcome" => "success",
        "result" => {
            "description" => "A JMS bridge instance.",
            "attributes" => {
                ...
        }
    }]
}
----

[[jms-bridge-statistics]]
=== Statistics of a JMS Bridge

Currently two statistics are available on a JMS bridge: the number of processed messages and the number of aborted/rolled back messages.
Those are available with the following command :

[source, ruby]
----
/subsystem=messaging/jms-bridge=myBridge:read-attribute(name=message-count)
{
    "outcome" => "success",
    "result" => 0L
}

/subsystem=messaging/jms-bridge=myBridge:read-attribute(name=aborted-message-count)
{
    "outcome" => "success",
    "result" => 0L
}
----

== Component Reference

The messaging-activemq subsystem is provided by the Artemis project. For
a detailed description of the available configuration properties, please
consult the project documentation.

****

* Artemis Homepage: http://activemq.apache.org/artemis/
* Artemis User Documentation:
http://activemq.apache.org/artemis/docs.html

****

=== Controlling internal broker usage of memory and disk space

You can configure the disk space usage of the journal by using the `global-max-disk-usage` attribute, thus blocking the paging and processing of new messages until some disk space is available.
This is done from the CLI:
[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=messaging-activemq/server=default:write-attribute(name=global-max-disk-usage, value=70)
{
    "outcome" => "success",
    "response-headers" => {
        "operation-requires-reload" => true,
        "process-state" => "reload-required"
    }
}
----
You can define at which frequency the disk usage is checked using the `disk-scan-period` attribute.

In the same way configure the maximal memory affected to processing messages by using the `global-max-memory-size` attribute, thus blocking the processing of new messages until some memory space is available.
This is done from the CLI:
[source,options="nowrap"]
----
[standalone@localhost:9990 /] /subsystem=messaging-activemq/server=default:write-attribute(name=global-max-memory-size, value=960000000)
{
    "outcome" => "success",
    "response-headers" => {
        "operation-requires-reload" => true,
        "process-state" => "reload-required"
    }
}
----
:leveloffset: +1

include::Messaging_Connect_a_pooled-connection-factory_to_a_Remote_Artemis_Server.adoc[]

include::Messaging_Backward_&_Forward_Compatibility.adoc[]

include::Mesaging_AIO_-_NIO_for_messaging_journal.adoc[]

include::Messaging_JDBC_Store_for_Messaging_Journal.adoc[]

include::Messaging_Discovery_Configuration.adoc[]

:leveloffset: -1
