diff --git a/src/reference/asciidoc/jms.adoc b/src/reference/asciidoc/jms.adoc index 65c2171cd1..6e6fe159e4 100644 --- a/src/reference/asciidoc/jms.adoc +++ b/src/reference/asciidoc/jms.adoc @@ -9,10 +9,10 @@ There is also an outbound Channel Adapter which uses the `JmsTemplate` to conver As you can see from above by using `JmsTemplate` and `MessageListener` container Spring Integration relies on Spring's JMS support. This is important to understand since most of the attributes exposed on these adapters will configure the underlying Spring's `JmsTemplate` and/or `MessageListener` container. -For more details about `JmsTemplate` and `MessageListener` container please refer to http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html[Spring JMS documentation]. +For more details about `JmsTemplate` and `MessageListener` container please refer to http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html[Spring JMS documentation]. Whereas the JMS Channel Adapters are intended for unidirectional Messaging (send-only or receive-only), Spring Integration also provides inbound and outbound JMS Gateways for request/reply operations. -The inbound gateway relies on one of Spring's MessageListener container implementations for Message-driven reception that is also capable of sending a return value to the `reply-to` Destination as provided by the received Message. +The inbound gateway relies on one of Spring's `MessageListener` container implementations for Message-driven reception that is also capable of sending a return value to the `reply-to` Destination as provided by the received Message. The outbound Gateway sends a JMS Message to a `request-destination` (or `request-destination-name` or `request-destination-expression`) and then receives a reply Message. The `reply-destination` reference (or `reply-destination-name` or `reply-destination-expression`) can be configured explicitly or else the outbound gateway will use a JMS http://docs.oracle.com/javaee/6/api/javax/jms/TemporaryQueue.html[TemporaryQueue]. @@ -33,18 +33,18 @@ The following example defines an inbound Channel Adapter with a `Destination` re ---- TIP: Notice from the configuration that the inbound-channel-adapter is a Polling Consumer. -That means that it invokes receive() when triggered. +That means that it invokes `receive()` when triggered. This should only be used in situations where polling is done relatively infrequently and timeliness is not important. For all other situations (a vast majority of JMS-based use-cases), the _message-driven-channel-adapter_ described below is a better option. -NOTE: All of the JMS adapters that require a reference to the ConnectionFactory will automatically look for a bean named "connectionFactory" by default. +NOTE: All of the JMS adapters that require a reference to the `ConnectionFactory` will automatically look for a bean named "connectionFactory" by default. That is why you don't see a "connection-factory" attribute in many of the examples. -However, if your JMS ConnectionFactory has a different bean name, then you will need to provide that attribute. +However, if your JMS `ConnectionFactory` has a different bean name, then you will need to provide that attribute. -If 'extract-payload' is set to true (which is the default), the received JMS Message will be passed through the MessageConverter. -When relying on the default SimpleMessageConverter, this means that the resulting Spring Integration Message will have the JMS Message's body as its payload. -A JMS TextMessage will produce a String-based payload, a JMS BytesMessage will produce a byte array payload, and a JMS ObjectMessage's Serializable instance will become the Spring Integration Message's payload. -If instead you prefer to have the raw JMS Message as the Spring Integration Message's payload, then set 'extract-payload' to false. +If 'extract-payload' is set to true (which is the default), the received JMS Message will be passed through the `MessageConverter`. +When relying on the default `SimpleMessageConverter`, this means that the resulting Spring Integration Message will have the JMS Message's body as its payload. +A JMS `TextMessage` will produce a String-based payload, a JMS `BytesMessage` will produce a byte array payload, and a JMS `ObjectMessage`'s Serializable instance will become the Spring Integration Message's payload. +If instead you prefer to have the raw JMS Message as the Spring Integration Message's payload, then set 'extract-payload' to `false`. [source,xml] ---- also accepts the 'error-channel' attribute. +Finally, the `` also accepts the 'error-channel' attribute. This provides the same basic functionality as described in <>. [source,xml] ---- @@ -108,7 +109,7 @@ This provides the same basic functionality as described in <>. When comparing this to the generic gateway configuration, or the JMS 'inbound-gateway' that will be discussed below, the key difference here is that we are in a one-way flow since this is a 'channel-adapter', not a gateway. Therefore, the flow downstream from the 'error-channel' should also be one-way. -For example, it could simply send to a logging handler, or it could be connected to a different JMS element. +For example, it could simply send to a logging handler, or it could be connected to a different JMS `` element. When consuming from topics, set the `pub-sub-domain` attribute to true; set `subscription-durable` to true for a durable subscription, `subscription-shared` for a shared subscription (requires a JMS 2.0 broker and @@ -227,7 +228,7 @@ This is because each request gets a new consumer with a new selector (selecting Given that these selectors are unique, they will remain in the cache unused after the current request completes. If you specify a reply destination, you are advised to NOT use cached consumers. -Alternatively, consider using a as described below. +Alternatively, consider using a `` as described below. ===== [source,xml] @@ -244,7 +245,7 @@ That means that the 'extract-request-payload' property value applies to the Spri ** _Spring Integration 2.2_ introduced an alternative technique for handling replies. -If you add a`` child element to the gateway, instead of creating a consumer for each reply, a `MessageListener` container is used to receive the replies and hand them over to the requesting thread. +If you add a `` child element to the gateway, instead of creating a consumer for each reply, a `MessageListener` container is used to receive the replies and hand them over to the requesting thread. This provides a number of performance benefits as well as alleviating the cached consumer memory utilization problem described in the caution above. When using a `` with an outbound gateway with no `reply-destination`, instead of creating a `TemporaryQueue` for each request, a single `TemporaryQueue` is used (the gateway will create an additional `TemporaryQueue`, as necessary, if the connection to the broker is lost and recovered). @@ -272,7 +273,7 @@ Note that, in this situation, a new consumer is used for each request, and consu In the above example, a reply listener with default attributes is used. The listener is very lightweight and it is anticipated that, in most cases, only a single consumer will be needed. However, attributes such as _concurrent-consumers_, _max-concurrent-consumers_ etc., can be added. -Refer to the schema for a complete list of supported attributes, together with thehttp://static.springsource.org/spring/docs/current/spring-framework-reference/html/jms.html[Spring JMS documentation] for their meanings. +Refer to the schema for a complete list of supported attributes, together with the http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html[Spring JMS documentation] for their meanings. *Idle Reply Listeners* @@ -287,6 +288,115 @@ for a short time after it finishes). See `idle-reply-listener-timeout` in <>. +==== Gateway Reply Correlation + +The following describes the mechanisms used for reply correlation (ensuring the originating gateway receives replies +to only its requests), depending on how the gateway is configured. +See the next section for complete description of the attributes discussed here. + +*1. No `reply-destination*` properties; no ``* + +A `TemporaryQueue` is created for each request, and deleted when the request is complete (successfully or otherwise). +`correlation-key` is irrelevant. + +*2. A `reply-destination*` property is provided; no ``; no `correlation-key`* + +The `JMSCorrelationID` equal to the outgoing message id is used as a message selector for the consumer: + + messageSelector = "JMSCorrelationID = '" + messageId + "'" + +The responding system is expected to return the inbound `JMSMessageID` in the reply `JMSCorrelationID` - this is a +common pattern and is implemented by the Spring Integration inbound gateway as well as Spring's +`MessageListenerAdapter` for message-driven POJOs. + +NOTE: When using this configuration, you should not use a topic for replies; the reply may be lost. + +*3. A `reply-destination*` property is provided; no ``; `correlation-key="JMSCorrelationID"`* + +The gateway generates a unique correlation id and inserts it in the `JMSCorrelationID` header. +The message selector is: + + messageSelector = "JMSCorrelationID = '" + uniqueId + "'" + +The responding system is expected to return the inbound `JMSCorrelationID` in the reply `JMSCorrelationID` - this is a +common pattern and is implemented by the Spring Integration inbound gateway as well as Spring's +`MessageListenerAdapter` for message-driven POJOs. + +*4. A `reply-destination*` property is provided; no ``; `correlation-key="myCorrelationHeader"`* + +The gateway generates a unique correlation id and inserts it in the `myCorrelationHeader` message property. +The `correlation-key` can be any user-defined value; the message selector is: + + messageSelector = "myCorrelationHeader = '" + uniqueId + "'" + +The responding system is expected to return the inbound `myCorrelationHeader` in the reply `myCorrelationHeader`. + +*5. A `reply-destination*` property is provided; no ``; `correlation-key="JMSCorrelationID*"`* + +(Note the `*` in the correlation key) + +The gateway uses the value in the `jms_correlationId` header (if present) from the request message, and inserts it in +the `JMSCorrelationID` header. +The message selector is: + + messageSelector = "JMSCorrelationID = '" + headers['jms_correlationId'] + "'" + +The user must ensure this value is unique. + +If the header does not exist, the gateway behaves as in `3.` above. + +The responding system is expected to return the inbound `JMSCorrelationID` in the reply `JMSCorrelationID` - this is a +common pattern and is implemented by the Spring Integration inbound gateway as well as Spring's +`MessageListenerAdapter` for message-driven POJOs. + +*6. No `reply-destination*` properties; with ``* + +A temporary queue is created and used for all replies from this gateway instance. +No correlation data is needed in the message but the outgoing `JMSMessageID` is used internally in the gateway to +direct the reply to the correct requesting thread. + +*7. A `reply-destination*` property is provided; with ``, no `correlation-key`* + +__NOT ALLOWED__ + +The `` configuration is ignored and the gateway behaves as in `2.` above. +A warning log message is written indicating this situation. + +*8. A `reply-destination*` property is provided; with ``, `correlation-key="JMSCorrelationID"`* + +The gateway has a unique correlation id and inserts it, together with an incrementing value in the `JMSCorrelationID` +header (`gatewayId + "_" + ++seq`). +The message selector is: + + messageSelector = "JMSCorrelationID LIKE '" + gatewayId%'" + +The responding system is expected to return the inbound `JMSCorrelationID` in the reply `JMSCorrelationID` - this is a +common pattern and is implemented by the Spring Integration inbound gateway as well as Spring's +`MessageListenerAdapter` for message-driven POJOs. +Since each gateway has a unique id, each instance only gets its own replies; the complete correlation data is used +to route the reply to the correct requesting thread. + +*9. A `reply-destination*` property is provided; with ``; `correlation-key="myCorrelationHeader"`* + +The gateway has a unique correlation id and inserts it, together with an incrementing value in the `myCorrelationHeader` +property (`gatewayId + "_" + ++seq`). +The `correlation-key` can be any user-defined value; and the message selector is: + + messageSelector = "myCorrelationHeader LIKE '" + gatewayId%'" + +The responding system is expected to return the inbound `myCorrelationHeader` in the reply `myCorrelationHeader`. +Since each gateway has a unique id, each instance only gets its own replies; the complete correlation data is used +to route the reply to the correct requesting thread. + +*10. A `reply-destination*` property is provided; with ``; `correlation-key="JMSCorrelationID*"`* + +(Note the `*` in the correlation key) + +__NOT ALLOWED__ + +User-supplied correlation ids are not permitted with a reply listener; the gateway will not initialize with this +configuration. + [[jms-og-attributes]] ==== Attribute Reference