@ -5,7 +5,7 @@ This describes how to receive messages with JMS in Spring.
@@ -5,7 +5,7 @@ This describes how to receive messages with JMS in Spring.
[[jms-receiving-sync]]
== Synchronous Reception
== Synchronous Receipt
While JMS is typically associated with asynchronous processing, you can
consume messages synchronously. The overloaded `receive(..)` methods provide this
@ -16,11 +16,11 @@ the receiver should wait before giving up waiting for a message.
@@ -16,11 +16,11 @@ the receiver should wait before giving up waiting for a message.
[[jms-receiving-async]]
== Asynchronous reception: Message-Driven POJOs
== Asynchronous Receipt: Message-Driven POJOs
NOTE: Spring also supports annotated-listener endpoints through the use of the `@JmsListener`
annotation and provides an open infrastructure to register endpoints programmatically.
This is, by far, the most convenient way to setup an asynchronous receiver.
annotation and provides open infrastructure to register endpoints programmatically.
This is, by far, the most convenient way to setup an asynchronous receiver.
See xref:integration/jms/annotated.adoc#jms-annotated-support[Enable Listener Endpoint Annotations] for more details.
In a fashion similar to a Message-Driven Bean (MDB) in the EJB world, the Message-Driven
You can activate local resource transactions through the `sessionTransacted` flag
on the listener container definition. Each message listener invocation then operates
within an active JMS transaction, with message reception rolled back in case of listener
within an active JMS transaction, with message receipt rolled back in case of listener
execution failure. Sending a response message (through `SessionAwareMessageListener`) is
part of the same local transaction, but any other resource operations (such as
database access) operate independently. This usually requires duplicate message
@ -173,7 +173,7 @@ To configure a message listener container for XA transaction participation, you
@@ -173,7 +173,7 @@ To configure a message listener container for XA transaction participation, you
to configure a `JtaTransactionManager` (which, by default, delegates to the Jakarta EE
server's transaction subsystem). Note that the underlying JMS `ConnectionFactory` needs to
be XA-capable and properly registered with your JTA transaction coordinator. (Check your
Jakarta EE server's configuration of JNDI resources.) This lets message reception as well
Jakarta EE server's configuration of JNDI resources.) This lets message receipt as well
as (for example) database access be part of the same transaction (with unified commit
semantics, at the expense of XA transaction log overhead).
@ -167,13 +167,15 @@ operations that do not refer to a specific destination.
@@ -167,13 +167,15 @@ operations that do not refer to a specific destination.
One of the most common uses of JMS messages in the EJB world is to drive message-driven
beans (MDBs). Spring offers a solution to create message-driven POJOs (MDPs) in a way
that does not tie a user to an EJB container. (See xref:integration/jms/receiving.adoc#jms-receiving-async[Asynchronous reception: Message-Driven POJOs] for detailed
coverage of Spring's MDP support.) Since Spring Framework 4.1, endpoint methods can be
annotated with `@JmsListener` -- see xref:integration/jms/annotated.adoc[Annotation-driven Listener Endpoints] for more details.
that does not tie a user to an EJB container. (See
for detailed coverage of Spring's MDP support.) Endpoint methods can be annotated with
`@JmsListener` -- see xref:integration/jms/annotated.adoc[Annotation-driven Listener Endpoints]
for more details.
A message listener container is used to receive messages from a JMS message queue and
drive the `MessageListener` that is injected into it. The listener container is
responsible for all threading of message reception and dispatches into the listener for
responsible for all threading of message receipt and dispatches into the listener for
processing. A message listener container is the intermediary between an MDP and a
messaging provider and takes care of registering to receive messages, participating in
transactions, resource acquisition and release, exception conversion, and so on. This
@ -227,7 +229,7 @@ the JMS provider, advanced functionality (such as participation in externally ma
@@ -227,7 +229,7 @@ the JMS provider, advanced functionality (such as participation in externally ma
transactions), and compatibility with Jakarta EE environments.
You can customize the cache level of the container. Note that, when no caching is enabled,
a new connection and a new session is created for each message reception. Combining this
a new connection and a new session is created for each message receipt. Combining this
with a non-durable subscription with high loads may lead to message loss. Make sure to
use a proper cache level in such a case.
@ -246,7 +248,7 @@ in the form of a business entity existence check or a protocol table check.
@@ -246,7 +248,7 @@ in the form of a business entity existence check or a protocol table check.
Any such arrangements are significantly more efficient than the alternative:
wrapping your entire processing with an XA transaction (through configuring your
`DefaultMessageListenerContainer` with an `JtaTransactionManager`) to cover the
reception of the JMS message as well as the execution of the business logic in your
receipt of the JMS message as well as the execution of the business logic in your
@ -37,7 +37,7 @@ As outlined xref:integration/observability.adoc[at the beginning of this section
@@ -37,7 +37,7 @@ As outlined xref:integration/observability.adoc[at the beginning of this section
|Processing time for an execution of a `@Scheduled` task
|===
NOTE: Observations are using Micrometer's official naming convention, but Metrics names will be automatically converted
NOTE: Observations use Micrometer's official naming convention, but Metrics names will be automatically converted
{micrometer-docs}/concepts/naming.html[to the format preferred by the monitoring system backend]
(Prometheus, Atlas, Graphite, InfluxDB...).
@ -97,7 +97,7 @@ This can be done by declaring a `SchedulingConfigurer` bean that sets the observ
@@ -97,7 +97,7 @@ This can be done by declaring a `SchedulingConfigurer` bean that sets the observ
include-code::./ObservationSchedulingConfigurer[]
It is using the `org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention` by default, backed by the `ScheduledTaskObservationContext`.
It uses the `org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention` by default, backed by the `ScheduledTaskObservationContext`.
You can configure a custom implementation on the `ObservationRegistry` directly.
During the execution of the scheduled method, the current observation is restored in the `ThreadLocal` context or the Reactor context (if the scheduled method returns a `Mono` or `Flux` type).
@ -107,7 +107,7 @@ By default, the following `KeyValues` are created:
@@ -107,7 +107,7 @@ By default, the following `KeyValues` are created:
[cols="a,a"]
|===
|Name | Description
|`code.function` _(required)_|Name of Java `Method` that is scheduled for execution.
|`code.function` _(required)_|Name of the Java `Method` that is scheduled for execution.
|`code.namespace` _(required)_|Canonical name of the class of the bean instance that holds the scheduled method, or `"ANONYMOUS"` for anonymous classes.
|`error` _(required)_|Class name of the exception thrown during the execution, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
@ -126,7 +126,7 @@ This instrumentation will create 2 types of observations:
@@ -126,7 +126,7 @@ This instrumentation will create 2 types of observations:
* `"jms.message.publish"` when a JMS message is sent to the broker, typically with `JmsTemplate`.
* `"jms.message.process"` when a JMS message is processed by the application, typically with a `MessageListener` or a `@JmsListener` annotated method.
NOTE: currently there is no instrumentation for `"jms.message.receive"` observations as there is little value in measuring the time spent waiting for the reception of a message.
NOTE: Currently there is no instrumentation for `"jms.message.receive"` observations as there is little value in measuring the time spent waiting for the receipt of a message.
Such an integration would typically instrument `MessageConsumer#receive` method calls. But once those return, the processing time is not measured and the trace scope cannot be propagated to the application.
By default, both observations share the same set of possible `KeyValues`:
@ -138,7 +138,7 @@ By default, both observations share the same set of possible `KeyValues`:
@@ -138,7 +138,7 @@ By default, both observations share the same set of possible `KeyValues`:
|`error` |Class name of the exception thrown during the messaging operation (or "none").
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|`messaging.destination.temporary` _(required)_|Whether the destination is a `TemporaryQueue` or `TemporaryTopic` (values: `"true"` or `"false"`).
|`messaging.operation` _(required)_|Name of JMS operation being performed (values: `"publish"` or `"process"`).
|`messaging.operation` _(required)_|Name of the JMS operation being performed (values: `"publish"` or `"process"`).
|===
.High cardinality Keys
@ -146,7 +146,7 @@ By default, both observations share the same set of possible `KeyValues`:
@@ -146,7 +146,7 @@ By default, both observations share the same set of possible `KeyValues`:
|===
|Name | Description
|`messaging.message.conversation_id` |The correlation ID of the JMS message.
|`messaging.destination.name` |The name of destination the current message was sent to.
|`messaging.destination.name` |The name of the destination the current message was sent to.
|`messaging.message.id` |Value used by the messaging system as an identifier for the message.
|===
@ -213,7 +213,7 @@ By default, the following `KeyValues` are created:
@@ -213,7 +213,7 @@ By default, the following `KeyValues` are created:
|Name | Description
|`error` _(required)_|Class name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`method` _(required)_|Name of the HTTP request method or `"none"` if not a well-known method.
|`outcome` _(required)_|Outcome of the HTTP server exchange.
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created.
|`uri` _(required)_|URI pattern for the matching handler if available, falling back to `REDIRECTION` for 3xx responses, `NOT_FOUND` for 404 responses, `root` for requests with no path info, and `UNKNOWN` for all other requests.
@ -235,10 +235,10 @@ This can be done on the `WebHttpHandlerBuilder`, as follows:
@@ -235,10 +235,10 @@ This can be done on the `WebHttpHandlerBuilder`, as follows:
include-code::./HttpHandlerConfiguration[]
It is using the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
It uses the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`.
This will only record an observation as an error if the `Exception` has not been handled by an application Controller.
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and <<web.adoc#webflux-ann-rest-exceptions,`ProblemDetail` support>> will not be recorded with the observation.
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and xref:web/webflux/ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation.
You can, at any point during request processing, set the error field on the `ObservationContext` yourself:
include-code::./UserController[]
@ -251,7 +251,7 @@ By default, the following `KeyValues` are created:
@@ -251,7 +251,7 @@ By default, the following `KeyValues` are created:
|Name | Description
|`error` _(required)_|Class name of the exception thrown during the exchange, or `"none"` if no exception happened.
|`exception` _(deprecated)_|Duplicates the `error` key and might be removed in the future.
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`method` _(required)_|Name of the HTTP request method or `"none"` if not a well-known method.
|`outcome` _(required)_|Outcome of the HTTP server exchange.
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created.
|`uri` _(required)_|URI pattern for the matching handler if available, falling back to `REDIRECTION` for 3xx responses, `NOT_FOUND` for 404 responses, `root` for requests with no path info, and `UNKNOWN` for all other requests.
@ -284,7 +284,7 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
@@ -284,7 +284,7 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
[cols="a,a"]
|===
|Name | Description
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`method` _(required)_|Name of the HTTP request method or `"none"` if not a well-known method.
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
@ -312,7 +312,7 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
@@ -312,7 +312,7 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
[cols="a,a"]
|===
|Name | Description
|`method` _(required)_|Name of HTTP request method or `"none"` if the request could not be created.
|`method` _(required)_|Name of the HTTP request method or `"none"` if the request could not be created.
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
@ -332,7 +332,7 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
@@ -332,7 +332,7 @@ Instrumentation uses the `org.springframework.http.client.observation.ClientRequ
[[observability.http-client.webclient]]
=== WebClient
Applications must configure an `ObservationRegistry` on the `WebClient` builder to enable the instrumentation; without that, observations are "no-ops".
Applications must configure an `ObservationRegistry` on the `WebClient.Builder` to enable the instrumentation; without that, observations are "no-ops".
Spring Boot will auto-configure `WebClient.Builder` beans with the observation registry already set.
Instrumentation uses the `org.springframework.web.reactive.function.client.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`.
@ -341,7 +341,7 @@ Instrumentation uses the `org.springframework.web.reactive.function.client.Clien
@@ -341,7 +341,7 @@ Instrumentation uses the `org.springframework.web.reactive.function.client.Clien
[cols="a,a"]
|===
|Name | Description
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method.
|`method` _(required)_|Name of the HTTP request method or `"none"` if not a well-known method.
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered.
|`client.name` _(required)_|Client name derived from the request URI host.
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received.
@ -105,7 +105,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
@@ -105,7 +105,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
@ -131,7 +131,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
@@ -131,7 +131,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
@ -474,7 +474,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
@@ -474,7 +474,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
@ -562,7 +562,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
@@ -562,7 +562,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe