Skip to content

Sending messages to JMS

The JMS Connector can send Reactive Messaging Messages as JMS Message.

Example

Let’s imagine you have a jakarta.jms.ConnectionFactory bean exposed and connected to your JMS server. Don’t forget that it’s required to use the JMS connector.

Configure your application to write the messages from the prices channel into a JMS Message as follows:

mp.messaging.outgoing.prices.connector=smallrye-jms

Note

You don’t need to set the destination. By default, it uses the channel name (prices). You can configure the destination attribute to override it.

Note

By default the connector uses a queue. You can configure it to use a topic by setting destination-type=topic.

Then, your application must send Message<Double> to the prices channel. It can use double payloads as in the following snippet:

package jms.outbound;

import java.time.Duration;
import java.util.Random;

import jakarta.enterprise.context.ApplicationScoped;

import org.eclipse.microprofile.reactive.messaging.Outgoing;

import io.smallrye.mutiny.Multi;

@ApplicationScoped
public class JmsPriceProducer {

    private Random random = new Random();

    @Outgoing("prices")
    public Multi<Double> generate() {
        // Build an infinite stream of random prices
        // It emits a price every second
        return Multi.createFrom().ticks().every(Duration.ofSeconds(1))
                .map(x -> random.nextDouble());
    }

}

Or, you can send Message<Double>:

package jms.outbound;

import java.time.Duration;
import java.util.Random;

import jakarta.enterprise.context.ApplicationScoped;

import org.eclipse.microprofile.reactive.messaging.Message;
import org.eclipse.microprofile.reactive.messaging.Outgoing;

import io.smallrye.mutiny.Multi;

@ApplicationScoped
public class JmsPriceMessageProducer {

    private Random random = new Random();

    @Outgoing("prices")
    public Multi<Message<Double>> generate() {
        // Build an infinite stream of random prices
        // It emits a price every second
        return Multi.createFrom().ticks().every(Duration.ofSeconds(1))
                .map(x -> Message.of(random.nextDouble()));
    }

}

Serialization

The connector serializes the incoming message payload into the body of the outgoing JMS Message.

If the payload is a String or a primitive type, the payload is encoded as String and the JMSType is set to the target class. The _classname property is also set. The JMS Message is a TextMessage.

If the payload is a byte[], it’s passed as byte[] in a JMS BytesMessage.

Otherwise, the payload is encoded using included JSON serializer (JSON-B and Jackson provided OOB, for more details see Serde). The JMSType is set to the target class. The _classname property is also set. The JMS Message is a TextMessage.

For example, the following code serialize the produced Person using JSON-B.

1
2
3
4
5
6
@Incoming("...")
@Outgoing("my-channel")
public Person sendToJms(...) {
  // ...
  return new Person("bob", 42);
}

It requires that the Person class can be serialized to JSON. The classname is passed in the JMSType property and _classname property.

Outbound Metadata

When sending Messages, you can add an instance of OutgoingJmsMessageMetadata to influence how the message is going to be written to JMS.

1
2
3
4
5
6
7
OutgoingJmsMessageMetadata metadata = OutgoingJmsMessageMetadata.builder()
        .withProperties(JmsProperties.builder().with("some-property", "some-value").build())
        .build();

// Create a new message from the `incoming` message
// Add `metadata` to the metadata from the `incoming` message.
return incoming.addMetadata(metadata);

The metadata allow adding properties but also override the destination.

Acknowledgement

Once the JMS message is sent to the JMS server, the message is acknowledged. Sending a JMS message is a blocking operation. So, sending is done on a worker thread.

Configuration Reference

Attribute (alias) Description Type Mandatory Default
client-id The client id String false
connection-factory-name The name of the JMS connection factory (jakarta.jms.ConnectionFactory) to be used. If not set, it uses any exposed JMS connection factory String false
correlation-id The JMS Message correlation id string false
delivery-delay The delivery delay long false
delivery-mode The delivery mode. Either persistent or non_persistent string false
destination The name of the JMS destination. If not set the name of the channel is used String false
destination-type The type of destination. It can be either queue or topic string false queue
disable-message-id Omit the message id in the outbound JMS message boolean false
disable-message-timestamp Omit the message timestamp in the outbound JMS message boolean false
merge Whether the connector should allow multiple upstreams boolean false false
password The password to connect to to the JMS server String false
priority The JMS Message priority int false
reply-to The reply to destination if any string false
reply-to-destination-type The type of destination for the response. It can be either queue or topic string false queue
retry Whether to retry on terminal stream errors. boolean false true
retry.initial-delay The initial delay for the retry. string false PT1S
retry.jitter How much the delay jitters as a multiplier between 0 and 1. The formula is current delay * jitter. For example, with a current delay of 2H, a jitter of 0.5 will result in an actual delay somewhere between 1H and 3H. double false 0.5
retry.max-delay The maximum delay string false PT10S
retry.max-retries Maximum number of retries for terminal stream errors. int false 3
session-mode The session mode. Accepted values are AUTO_ACKNOWLEDGE, SESSION_TRANSACTED, CLIENT_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE String false AUTO_ACKNOWLEDGE
ttl The JMS Message time-to-live long false
username The username to connect to to the JMS server String false