Chapter 14. Messaging
14.1. HornetQ
14.1.1. HornetQ
14.1.2. About Java Messaging Service (JMS)
14.1.3. Supported Messaging Styles
- Message Queue pattern
- The Message Queue pattern involves sending a message to a queue. Once in the queue, the message is usually made persistent to guarantee delivery. Once the message has moved through the queue, the messaging system delivers it to a message consumer. The message consumer acknowledges the delivery of the message once it is processed.When used with point-to-point messaging, the Message Queue pattern allows multiple consumers for a queue, but each message can only be received by a single consumer.
- Publish-Subscribe pattern
- The Publish-Subscribe pattern allows multiple senders to send messages to a single entity on the server. This entity is often known as a "topic". Each topic can be attended by multiple consumers, known as "subscriptions".Each subscription receives a copy of every message sent to the topic. This differs from the Message Queue pattern, where each message is only consumed by a single consumer.Subscriptions that are durable retain copies of each message sent to the topic until the subscriber consumes them. These copies are retained even in the event of a server restart. Non-durable subscriptions last only as long as the connection that created them.
14.1.4. About Acceptors and Connectors
Acceptors and Connectors
Acceptor
- An acceptor defines which types of connections are accepted by the HornetQ server.
Connector
- A connector defines how to connect to a HornetQ server, and is used by the HornetQ client.
Invm and Netty
Invm
- Invm is short for Intra Virtual Machine. It can be used when both the client and the server are running in the same JVM.
Netty
- The name of a JBoss project. It must be used when the client and server are running in different JVMs.
standalone.xml
and domain.xml
. You can use either the Management Console or the Management CLI to define them.
Example 14.1. Example of the Default Acceptor and Connector Configuration
<connectors> <netty-connector name="netty" socket-binding="messaging"/> <netty-connector name="netty-throughput" socket-binding="messaging-throughput"> <param key="batch-delay" value="50"/> </netty-connector> <in-vm-connector name="in-vm" server-id="0"/> </connectors> <acceptors> <netty-acceptor name="netty" socket-binding="messaging"/> <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput"> <param key="batch-delay" value="50"/> <param key="direct-deliver" value="false"/> </netty-acceptor> <in-vm-acceptor name="in-vm" server-id="0"/> </acceptors>
14.1.5. About Bridges
14.1.6. Work with Large Messages
14.1.7. Configure High-availability (HA) Failover
Important
14.1.8. Embed HornetQ in Applications
Instantiate the configuration object
Instantiate the configuration object either from a configuration file, or by setting configuration parameters programmatically.Create the configuration object from a file
Use theFileConfigurationImpl
class to set a configuration object based on a file.import org.hornetq.core.config.Configuration; import org.hornetq.core.config.impl.FileConfiguration; ... Configuration config = new FileConfiguration(); config.setConfigurationUrl(<replaceable>file-url</replaceable>); config.start();
Create the configuration object programmatically
- Use the
ConfigurationImpl
class to create a configuration object.import org.hornetq.core.config.Configuration; import org.hornetq.core.config.impl.FileConfiguration; ... Configuration config = new ConfigurationImpl();
- Set any configuration parameters programmatically, such as acceptors. For example:
HashSet<TransportConfiguration> transports = new HashSet<TransportConfiguration>(); transports.add(new TransportConfiguration(NettyAcceptorFactory.class.getName())); transports.add(new TransportConfiguration(InVMAcceptorFactory.class.getName())); config.setAcceptorConfigurations(transports);
Instantiate and start the server
Use theorg.hornetq.api.core.server.HornetQ
static methods to create and start a server based on the configuration object.import org.hornetq.api.core.server.HornetQ; import org.hornetq.core.server.HornetQServer; ... HornetQServer server = HornetQ.newHornetQServer(config); server.start();
An embedded HornetQ instance is instantiated for internal messaging. To connect clients to the embedded HornetQ, create factories as normal.
14.1.9. Configure the JMS Server
EAP_HOME/domain/configuration/domain.xml
file for domain servers, or in the EAP_HOME/standalone/configuration/standalone.xml
file for standalone servers.
<subsystem xmlns="urn:jboss:domain:messaging:1.2">
element contains all JMS configuration. Add any JMS ConnectionFactory
, Queue
, or Topic
instances required for the JNDI.
Enable the JMS subsystem in the JBoss Enterprise Application Platform.
In the<extensions>
element, verify that the following line is present and is not commented out:<extension module="org.jboss.as.messaging"/>
Add the basic JMS subsystem.
If the Messaging subsystem is not present in your configuration file, add it.- Look for the
<profile>
which corresponds to the profile you use, and locate its<subsystems>
tag. - Add a new line just beneath the
<subsystems>
tag. Paste the following into it:<subsystem xmlns="urn:jboss:domain:messaging:1.2"> </subsystem>
All further configuration will be added to the empty line above.
Add basic configuration for JMS.
<journal-file-size>102400</journal-file-size> <journal-min-files>2</journal-min-files> <journal-type>NIO</journal-type> <!-- disable messaging persistence --> <persistence-enabled>false</persistence-enabled>
Customize the values above to meet your needs.Add connection factory instances to HornetQ
The client uses a JMSConnectionFactory
object to make connections to the server. To add a JMS connection factory object to HornetQ, include a single<jms-connection-factories>
tag and<connection-factory>
element for each connection factory as follows:<subsystem xmlns="urn:jboss:domain:messaging:1.2"> ... <jms-connection-factories> <connection-factory name="myConnectionFactory"> <connectors> <connector-ref connector-name="netty"/> </connectors> <entries> <entry name="/ConnectionFactory"/> </entries> </connection-factory> </jms-connection-factories> ... </subsystem>
Configure the
netty
connectorThis JMS connection factory uses anetty
connector. This is a reference to a connector object deployed in the server configuration file. The connector object defines the transport and parameters used to actually connect to the server.To configure thenetty
connector, include the following settings:<subsystem xmlns="urn:jboss:domain:messaging:1.2"> ... <connectors> <netty-connector name="netty" socket-binding="messaging"/> <netty-connector name="netty-throughput" socket-binding="messaging-throughput"> <param key="batch-delay" value="50"/> </netty-connector> <in-vm-connector name="in-vm" server-id="0"/> </connectors> ... </subsystem>
The connector references themessaging
andmessaging-throughput
socket bindings. Themessaging
socket binding uses port 5445, and themessaging-throughput
socket binding uses port 5455. Ensure the following socket bindings are present in the<socket-binding-groups>
element:<socket-binding-groups> ... <socket-binding-group ... > <socket-binding name="messaging" port="5445"/> <socket-binding name="messaging-throughput" port="5455"/> ... </socket-binding-group> ... </socket-binding-groups>
Add queue instances to HornetQ
The client uses a JMSQueue
object to stage sent messages for delivery to the server. To add a JMS queue object to HornetQ, include a<jms-queue>
element as follows:<subsystem xmlns="urn:jboss:domain:messaging:1.2"> ... <jms-destinations> <jms-queue name="myQueue"> <entry name="/queue/myQueue"/> </jms-queue> </jms-destinations> ...
Optional: Add topic instances to HornetQ
The client uses a JMSTopic
object to manage messages for multiple subscribers. To add a JMS topic object, include a<topic>
element as follows:<subsystem xmlns="urn:jboss:domain:messaging:1.2"> ... <jms-topic name="myTopic"> <entry name="/topic/myTopic"/> </jms-topic> ...
Perform additional configuration
If you need additional settings, review the DTD inEAP_HOME/docs/schema/jboss-messaging_1_2.xsd
.
14.1.10. About Java Naming and Directory Interface (JNDI)
14.1.11. Configure JNDI for HornetQ
Prerequisites
Procedure 14.1. Task
JNDIServer
bean for HornetQ when the JBoss Enterprise Application Server is running as a standalone server.
Set the JNDI properties on the client side
The JNDI properties tell the JNDI client where to locate the JNDI server. The properties can be specified in a file namedjndi.properties
on the client classpath, or declared directly when creating the initial JNDI context.Set the JNDI properties to the following settings:java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.provider.url=jnp://hostname:1099 java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
- hostname is the hostname or IP address of the JNDI server.
Configure the JNDI server ports
Navigate to the Socket Binding Groups panel in the Management Console
Select the General Configuration → Socket Binding Groups option from the menu on the left of the console.The Socket Binding Groups panel for the selected server appears.Edit the JNDI Socket Binding
Select jndi from the Socket Binding Declarations table, then select the Edit button in the Socket Binding section below.Configure the following settings: and Multicast Port settings. Select the Save button when done.- Port:
1099
- Multicast Port:
1098
The JNDI server is now configured for HornetQ.
14.1.12. Configure JMS Address Settings
<address-settings>
configuration element.
Address wildcards can be used to match multiple similar addresses with a single statement, similar to how many systems use the asterisk ( *) character to match multiple files or strings with a single search. The following characters have special significance in a wildcard statement.
Table 14.1. JMS Wildcard Syntax
Character | Description |
---|---|
. (a single period) | Denotes the space between words in a wildcard expression. |
# (a pound or hash symbol) | Matches any sequence of zero or more words. |
* (an asterisk) | Matches a single word. |
Table 14.2. JMS Wildcard Examples
Example | Description |
---|---|
news.europe.# |
Matches
news.europe , news.europe.sport , news.europe.politic , but not news.usa or europe .
|
news. |
Matches
news.europe but not news.europe.sport .
|
news.*.sport |
Matches
news.europe.sport and news.usa.sport , but not news.europe.politics .
|
Example 14.2. Default Address Setting Configuration
<address-settings> <!--default for catch all--> <address-setting match="#"> <dead-letter-address>jms.queue.DLQ</dead-letter-address> <expiry-address>jms.queue.ExpiryQueue</expiry-address> <redelivery-delay>0</redelivery-delay> <max-size-bytes>10485760</max-size-bytes> <address-full-policy>BLOCK</address-full-policy> <message-counter-history-day-limit>10</message-counter-history-day-limit> </address-setting> </address-settings>
Table 14.3. Description of JMS Address Settings
Element | Description | Default Value | Type |
---|---|---|---|
address-full-policy
|
Determines what happens when an address where max-size-bytes is specified becomes full.
|
PAGE
|
STRING
|
dead-letter-address
|
If a dead letter address is specified, messages are moved to the dead letter address if
max-delivery-attempts delivery attempts have failed. Otherwise, these undelivered messages are discarded. Wildcards are allowed.
|
jms.queue.DLQ
|
STRING
|
expiry-address
|
If the expiry address is present, expired messages are sent to the address or addresses matched by it, instead of being discarded. Wildcards are allowed.
|
jms.queue.ExpiryQueue
|
STRING
|
last-value-queue
|
Defines whether a queue only uses last values or not.
|
false
|
BOOLEAN
|
max-delivery-attempts
|
The maximum number of times to attempt to re-deliver a message before it is sent to
dead-letter-address or discarded.
|
10
|
INT
|
max-delivery-bytes
|
The maximum bytes size.
|
10485760L
|
LONG
|
message-counter-history-day-limit
|
Day limit for the message counter history.
|
10
|
INT
|
page-max-cache-size
|
The number of page files to keep in memory to optimize IO during paging navigation.
|
5
|
INT
|
page-size-bytes
|
The paging size.
|
5
|
INT
|
redelivery-delay
|
Time to delay between re-delivery attempts of messages, expressed in milliseconds. If set to
0 , re-delivery attempts occur indefinitely.
|
0L
|
LONG
|
redistribution-delay
|
Defines how long to wait when the last consumer is closed on a queue before redistributing any messages.
|
-1L
|
LONG
|
send-to-dla-on-no-route
|
A parameter for an address that sets the condition of a message not ruoted to any queues to instead be sent the to the dead letter address (DLA) indicated for that address.
|
false
|
BOOLEAN
|
Configure Address Setting and Pattern Attributes
Choose either the Management CLI or the Management Console to configure your pattern attributes as required.Configure the Address Settings Using the Management CLI
Use the Management CLI to configure address settings.Add a New Pattern
Use theadd
operation to create a new address setting if required. You can run this command from the root of the Management CLI session, which in the following examples creates a new pattern titled patternname, with amax-delivery-attempts
attribute declared as 5. The examples for both Standalone Server and a Managed Domain editing on thefull
profile are shown.[domain@localhost:9999 /] /profile=full/subsystem=messaging/hornetq-server=default/address-setting=patternname/:add(max-delivery-attempts=5)
[standalone@localhost:9999 /] /subsystem=messaging/hornetq-server=default/address-setting=patternname/:add(max-delivery-attempts=5)
Edit Pattern Attributes
Use thewrite
operation to write a new value to an attribute. You can use tab completion to help complete the command string as you type, as well as to expose the available attributes. The following example updates themax-delivery-attempts
value to 10[domain@localhost:9999 /] /profile=full/subsystem=messaging/hornetq-server=default/address-setting=patternname/:write-attribute(name=max-delivery-attempts,value=10)
[standalone@localhost:9999 /] /subsystem=messaging/hornetq-server=default/address-setting=patternname/:write-attribute(name=max-delivery-attempts,value=10)
Confirm Pattern Attributes
Confirm the values are changed by running theread-resource
operation with theinclude-runtime=true
parameter to expose all current values active in the server model.[domain@localhost:9999 /] /profile=full/subsystem=messaging/hornetq-server=default/address-setting=patternname/:read-resource
[standalone@localhost:9999 /] /subsystem=messaging/hornetq-server=default/address-setting=patternname/:read-resource
Configure the Address Settings Using the Management Console
Use the Management Console to configure address settings.Log into the Management Console.
Log into the Management Console of your Managed Domain or Standalone Server.If you use a Managed Domain, choose the correct profile.
Select the Profiles tab at the top right, and then select the correct profile from the Profile menu at the top left of the next screen. Only thefull
andfull-ha
profiles have themessaging
subsystem enabled.Select the Messaging item from the navigation menu.
Expand the Messaging menu item from the navigation menu, and click Destinations.View the JMS Provider.
A list of JMS Providers is shown. In the default configuration, only one provider, calleddefault
, is shown. Click the View link to view the detailed settings for this provider.View the Address Settings.
Click the Addressing tab. Either add a new pattern by clicking the Add button, or edit an existing one by clicking its name and clicking the Edit button.Configure the options.
If you are adding a new pattern, the Pattern field refers to thematch
parameter of theaddress-setting
element. You can also edit the Dead Letter Address, Expiry Address, Redelivery Delay, and Max Delivery Attempts. Other options need to be configured using the Management CLI.
14.1.13. Reference for HornetQ Configuration Attributes
read-resource
operation.
Example 14.3. Example
[standalone@localhost:9999 /] /subsystem=messaging/hornetq-server=default:read-resource
Table 14.4. TableTitle
Attribute | Example Value | Type |
---|---|---|
allow-failback | true | BOOLEAN |
async-connection-execution-enabled | true | BOOLEAN |
backup | false | BOOLEAN |
cluster-password | somethingsecure | STRING |
cluster-user | HORNETQ.CLUSTER.ADMIN.USER | STRING |
clustered | false | BOOLEAN |
connection-ttl-override | -1 | LONG |
create-bindings-dir | true | BOOLEAN |
create-journal-dir | true | BOOLEAN |
failback-delay | 5000 | LONG |
failover-on-shutdown | false | BOOLEAN |
id-cache-size | 2000 | INT |
jmx-domain | org.hornetq | STRING |
jmx-management-enabled | false | BOOLEAN |
journal-buffer-size | 100 | LONG |
journal-buffer-timeout | 100 | LONG |
journal-compact-min-files | 10 | INT |
journal-compact-percentage | 30 | INT |
journal-file-size | 102400 | LONG |
journal-max-io | 1 | INT |
journal-min-files | 2 | INT |
journal-sync-non-transactional | true | BOOLEAN |
journal-sync-transactional | true | BOOLEAN |
journal-type | ASYNCIO | STRING |
live-connector-ref | reference | STRING |
log-journal-write-rate | false | BOOLEAN |
management-address | jms.queue.hornetq.management | STRING |
management-notification-address | hornetq.notifications | STRING |
memory-measure-interval | -1 | LONG |
memory-warning-threshold | 25 | INT |
message-counter-enabled | false | BOOLEAN |
message-counter-max-day-history | 10 | INT |
message-counter-sample-period | 10000 | LONG |
message-expiry-scan-period | 30000 | LONG |
message-expiry-thread-priority | 3 | INT |
page-max-concurrent-io | 5 | INT |
perf-blast-pages | -1 | INT |
persist-delivery-count-before-delivery | false | BOOLEAN |
persist-id-cache | true | BOOLEAN |
persistence-enabled | true | BOOLEAN |
remoting-interceptors | undefined | LIST |
run-sync-speed-test | false | BOOLEAN |
scheduled-thread-pool-max-size | 5 | INT |
security-domain | other | STRING |
security-enabled | true | BOOLEAN |
security-invalidation-interval | 10000 | LONG |
server-dump-interval | -1 | LONG |
shared-store | true | BOOLEAN |
started | true | BOOLEAN |
thread-pool-max-size | 30 | INT |
transaction-timeout | 300000 | LONG |
transaction-timeout-scan-period | 1000 | LONG |
version | 2.2.16.Final (HQ_2_2_16_FINAL, 122) | STRING |
wild-card-routing-enabled | true | BOOLEAN |
14.1.14. Configure Messaging with HornetQ
standalone.xml
or domain.xml
configuration files. It is useful however to familiarise yourself with the messaging components of the default configuration files, where documentation examples using management tools give configuration file snippets for reference.
14.1.15. Configure Delayed Redelivery
Delayed redelivery is defined in the <redelivery-delay>
element, which is a child element of the <address-setting>
configuration element in the Java Messaging Service (JMS) subsystem configuration.
<!-- delay redelivery of messages for 5s --> <address-setting match="jms.queue.exampleQueue"> <redelivery-delay>5000</redelivery-delay> </address-setting>
<redelivery-delay>
is set to 0
, there is no redelivery delay. Address wildcards can be used on the <address-setting-match>
element to configure the redelivery delay for addresses which match the wildcard.
14.1.16. Configure Dead Letter Addresses
A dead letter address is defined in the <address-setting>
element of the Java Messaging Service (JMS) subsystem configuration.
<!-- undelivered messages in exampleQueue will be sent to the dead letter address deadLetterQueue after 3 unsuccessful delivery attempts --> <address-setting match="jms.queue.exampleQueue"> <dead-letter-address>jms.queue.deadLetterQueue</dead-letter-address> <max-delivery-attempts>3</max-delivery-attempts> </address-setting>
<dead-letter-address>
is not specified, messages are removed after trying to deliver <max-delivery-attempts>
times. By default, messages delivery is attempted 10 times. Setting <max-delivery-attempts>
to -1
allows infinite redelivery attempts. For example, a dead letter can be set globally for a set of matching addresses and you can set <max-delivery-attempts>
to -1
for a specific address setting to allow infinite redelivery attempts only for this address. Address wildcards can also be used to configure dead letter settings for a set of addresses.
14.1.17. Configure Message Expiry Addresses
Message expiry addresses are defined in the address-setting configuration of the Java Messaging Service (JMS). For example:
<!-- expired messages in exampleQueue will be sent to the expiry address expiryQueue --> <address-setting match="jms.queue.exampleQueue"> <expiry-address>jms.queue.expiryQueue</expiry-address> </address-setting>
Address wildcards can be used to match multiple similar addresses with a single statement, similar to how many systems use the asterisk (*) character to match multiple files or strings with a single search. The following characters have special significance in a wildcard statement.
Table 14.5. JMS Wildcard Syntax
Character | Description |
---|---|
. (a single period) | Denotes the space between words in a wildcard expression. |
# (a pound or hash symbol) | Matches any sequence of zero or more words. |
* (an asterisk) | Matches a single word. |
Table 14.6. JMS Wildcard Examples
Example | Description |
---|---|
news.europe.# |
Matches
news.europe , news.europe.sport , news.europe.politic , but not news.usa or europe .
|
news. |
Matches
news.europe but not news.europe.sport .
|
news.*.sport |
Matches
news.europe.sport and news.usa.sport , but not news.europe.politics .
|
14.1.18. Set Message Expiry
Using HornetQ Core API, the expiration time can be set directly on the message. For example:
// message will expire in 5000ms from now message.setExpiration(System.currentTimeMillis() + 5000);
MessageProducer
JMS MessageProducer
includes a TimeToLive
parameter which controls message expiry for the messages it sends::
// messages sent by this producer will be retained for 5s (5000ms) before expiration producer.setTimeToLive(5000);
- _HQ_ORIG_ADDRESS
- _HQ_ACTUAL_EXPIRY