From 94fe1f4c6369cb186e620550e7f9d3d05eb92a1d Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Mon, 14 Aug 2023 16:27:45 +0200 Subject: [PATCH] Guard for Micrometer Core usage in JMS instrumentation This commit ensures that the Observability instrumentation for `@JmsListener` does not assume that micrometer-core is on the classpath and guards against direct usage. Closes gh-30335 --- .../AbstractMessageListenerContainer.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java b/spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java index 6c7dbd1f0ece..a65391e1647d 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java @@ -37,6 +37,7 @@ import org.springframework.jms.support.QosSettings; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; import org.springframework.util.ErrorHandler; /** @@ -149,7 +150,8 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListeningContainer implements MessageListenerContainer { - private static final JmsProcessObservationConvention DEFAULT_CONVENTION = new DefaultJmsProcessObservationConvention(); + private static final boolean micrometerCorePresent = ClassUtils.isPresent( + "io.micrometer.core.instrument.binder.jms.JmsInstrumentation", AbstractMessageListenerContainer.class.getClassLoader()); @Nullable private volatile Object destination; @@ -703,8 +705,7 @@ protected void doExecuteListener(Session session, Message message) throws JMSExc } try { - Observation observation = JmsObservationDocumentation.JMS_MESSAGE_PROCESS - .observation(null, DEFAULT_CONVENTION, () -> new JmsProcessObservationContext(message), this.observationRegistry); + Observation observation = createObservation(message); observation.observeChecked(() -> invokeListener(session, message)); } catch (JMSException | RuntimeException | Error ex) { @@ -714,6 +715,15 @@ protected void doExecuteListener(Session session, Message message) throws JMSExc commitIfNecessary(session, message); } + private Observation createObservation(Message message) { + if (micrometerCorePresent) { + return ObservationFactory.create(this.observationRegistry, message); + } + else { + return Observation.NOOP; + } + } + /** * Invoke the specified listener: either as standard JMS MessageListener * or (preferably) as Spring SessionAwareMessageListener. @@ -758,8 +768,7 @@ protected void doInvokeListener(SessionAwareMessageListener listener, Session se Connection conToClose = null; Session sessionToClose = null; - Observation observation = JmsObservationDocumentation.JMS_MESSAGE_PROCESS - .observation(null, DEFAULT_CONVENTION, () -> new JmsProcessObservationContext(message), this.observationRegistry); + Observation observation = createObservation(message); try { Session sessionToUse = session; if (!isExposeListenerSession()) { @@ -982,4 +991,14 @@ protected void invokeErrorHandler(Throwable ex) { private static class MessageRejectedWhileStoppingException extends RuntimeException { } + private static abstract class ObservationFactory { + + private static final JmsProcessObservationConvention DEFAULT_CONVENTION = new DefaultJmsProcessObservationConvention(); + + static Observation create(@Nullable ObservationRegistry registry, Message message) { + return JmsObservationDocumentation.JMS_MESSAGE_PROCESS + .observation(null, DEFAULT_CONVENTION, () -> new JmsProcessObservationContext(message), registry); + } + } + }