diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/CompositeMessageHandlerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/CompositeMessageHandlerNode.java index 161716e3709..96e20838b63 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/CompositeMessageHandlerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/CompositeMessageHandlerNode.java @@ -19,6 +19,8 @@ import java.util.ArrayList; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.MessageHandler; /** @@ -33,7 +35,7 @@ public class CompositeMessageHandlerNode extends MessageHandlerNode { private final List handlers = new ArrayList<>(); - public CompositeMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, String output, + public CompositeMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output, List handlers) { super(nodeId, name, handler, input, output); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/DiscardingMessageHandlerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/DiscardingMessageHandlerNode.java index 0dbac6afc56..3b6e722a26d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/DiscardingMessageHandlerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/DiscardingMessageHandlerNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.MessageHandler; /** @@ -28,16 +30,16 @@ */ public class DiscardingMessageHandlerNode extends MessageHandlerNode { - private final String discards; + private final @Nullable String discards; - public DiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, String output, - String discards) { + public DiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, + @Nullable String output, @Nullable String discards) { super(nodeId, name, handler, input, output); this.discards = discards; } - public String getDiscards() { + public @Nullable String getDiscards() { return this.discards; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/EndpointNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/EndpointNode.java index 470a5d6b146..fd7f448c1b6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/EndpointNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/EndpointNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + /** * Base class for all endpoints. * @@ -26,14 +28,14 @@ */ public abstract class EndpointNode extends IntegrationNode { - private final String output; + private final @Nullable String output; - protected EndpointNode(int nodeId, String name, Object nodeObject, String output) { + protected EndpointNode(int nodeId, String name, Object nodeObject, @Nullable String output) { super(nodeId, name, nodeObject); this.output = output; } - public String getOutput() { + public @Nullable String getOutput() { return this.output; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableCompositeMessageHandlerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableCompositeMessageHandlerNode.java index a6bd14d41fe..3a84893fba8 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableCompositeMessageHandlerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableCompositeMessageHandlerNode.java @@ -18,6 +18,8 @@ import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.handler.CompositeMessageHandler; /** @@ -31,17 +33,17 @@ */ public class ErrorCapableCompositeMessageHandlerNode extends CompositeMessageHandlerNode implements ErrorCapableNode { - private final String errors; + private final @Nullable String errors; - public ErrorCapableCompositeMessageHandlerNode(int nodeId, String name, CompositeMessageHandler handler, String input, - String output, String errors, List handlers) { + public ErrorCapableCompositeMessageHandlerNode(int nodeId, String name, CompositeMessageHandler handler, + String input, @Nullable String output, @Nullable String errors, List handlers) { super(nodeId, name, handler, input, output, handlers); this.errors = errors; } @Override - public String getErrors() { + public @Nullable String getErrors() { return this.errors; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableDiscardingMessageHandlerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableDiscardingMessageHandlerNode.java index f7b8325d67f..6047896bbd5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableDiscardingMessageHandlerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableDiscardingMessageHandlerNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.MessageHandler; /** @@ -29,17 +31,17 @@ */ public class ErrorCapableDiscardingMessageHandlerNode extends DiscardingMessageHandlerNode implements ErrorCapableNode { - private final String errors; + private final @Nullable String errors; public ErrorCapableDiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, - String output, String discards, String errors) { + @Nullable String output, @Nullable String discards, @Nullable String errors) { super(nodeId, name, handler, input, output, discards); this.errors = errors; } @Override - public String getErrors() { + public @Nullable String getErrors() { return this.errors; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableEndpointNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableEndpointNode.java index 8dde25b218f..d7aad79c6a8 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableEndpointNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableEndpointNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + /** * Represents nodes that can natively handle errors. * @@ -26,15 +28,15 @@ */ public class ErrorCapableEndpointNode extends EndpointNode implements ErrorCapableNode { - private final String errors; + private final @Nullable String errors; - protected ErrorCapableEndpointNode(int nodeId, String name, Object nodeObject, String output, String errors) { + protected ErrorCapableEndpointNode(int nodeId, String name, Object nodeObject, @Nullable String output, @Nullable String errors) { super(nodeId, name, nodeObject, output); this.errors = errors; } @Override - public String getErrors() { + public @Nullable String getErrors() { return this.errors; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableMessageHandlerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableMessageHandlerNode.java index 9e91f916f19..2618469df1e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableMessageHandlerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableMessageHandlerNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.MessageHandler; /** @@ -27,17 +29,17 @@ */ public class ErrorCapableMessageHandlerNode extends MessageHandlerNode implements ErrorCapableNode { - private final String errors; + private final @Nullable String errors; public ErrorCapableMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, - String output, String errors) { + @Nullable String output, @Nullable String errors) { super(nodeId, name, handler, input, output); this.errors = errors; } @Override - public String getErrors() { + public @Nullable String getErrors() { return this.errors; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableNode.java index d68529cf11b..64d648d7e51 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + /** * Nodes implementing this interface are capable of emitting errors. * @@ -26,6 +28,7 @@ */ public interface ErrorCapableNode { + @Nullable String getErrors(); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableRoutingNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableRoutingNode.java index 693d4c3bbb1..fc781476181 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableRoutingNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/ErrorCapableRoutingNode.java @@ -18,6 +18,8 @@ import java.util.Collection; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.MessageHandler; /** @@ -31,17 +33,17 @@ */ public class ErrorCapableRoutingNode extends RoutingMessageHandlerNode implements ErrorCapableNode { - private final String errors; + private final @Nullable String errors; - public ErrorCapableRoutingNode(int nodeId, String name, MessageHandler handler, String input, String output, - String errors, Collection routes) { + public ErrorCapableRoutingNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output, + @Nullable String errors, Collection routes) { super(nodeId, name, handler, input, output, routes); this.errors = errors; } @Override - public String getErrors() { + public @Nullable String getErrors() { return this.errors; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java index 51011789e83..69462a17050 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphRuntimeHints.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + import org.springframework.aot.hint.BindingReflectionHintsRegistrar; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; @@ -31,7 +33,7 @@ class IntegrationGraphRuntimeHints implements RuntimeHintsRegistrar { @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { new BindingReflectionHintsRegistrar() .registerReflectionHints(hints.reflection(), Graph.class, diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java index 0b7c349daa2..d38e8ab5495 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java @@ -55,9 +55,11 @@ import org.springframework.integration.support.management.MappingMessageRouterManagement; import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptorConfiguration; import org.springframework.integration.support.utils.IntegrationUtils; +import org.springframework.lang.Contract; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.PollableChannel; +import org.springframework.util.Assert; /** * Builds the runtime object model graph. @@ -78,23 +80,24 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat private final NodeFactory nodeFactory = new NodeFactory(this::enhance); - private MicrometerNodeEnhancer micrometerEnhancer; + private @Nullable MicrometerNodeEnhancer micrometerEnhancer; + @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; - private volatile Graph graph; + private volatile @Nullable Graph graph; - private String applicationName; + private @Nullable String applicationName; - private Function> additionalPropertiesCallback; + private @Nullable Function> additionalPropertiesCallback; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; // NOSONAR (sync) + this.applicationContext = applicationContext; } protected ApplicationContext getApplicationContext() { - return this.applicationContext; // NOSONAR (sync) + return this.applicationContext; } /** @@ -104,7 +107,7 @@ protected ApplicationContext getApplicationContext() { * @param applicationName the application name. */ public void setApplicationName(String applicationName) { - this.applicationName = applicationName; //NOSONAR (sync) + this.applicationName = applicationName; } /** @@ -133,18 +136,20 @@ public void onApplicationEvent(ContextRefreshedEvent event) { * @see #rebuild() */ public Graph getGraph() { - if (this.graph == null) { + var localGraph = this.graph; + if (localGraph == null) { this.lock.lock(); try { - if (this.graph == null) { - buildGraph(); + localGraph = this.graph; + if (localGraph == null) { + localGraph = buildGraph(); } } finally { this.lock.unlock(); } } - return this.graph; + return localGraph; } /** @@ -212,8 +217,9 @@ private Graph buildGraph() { gateways(nodes, links, channelNodes); producers(nodes, links, channelNodes); consumers(nodes, links, channelNodes); - this.graph = new Graph(descriptor, nodes, links); - return this.graph; + var localGraph = new Graph(descriptor, nodes, links); + this.graph = localGraph; + return localGraph; } private Map channels(Collection nodes) { @@ -223,8 +229,8 @@ private Map channels(Collection nod .map(e -> { MessageChannel messageChannel = e.getValue(); MessageChannelNode messageChannelNode = this.nodeFactory.channelNode(e.getKey(), messageChannel); - if (messageChannel instanceof NamedComponent) { - messageChannelNode.addProperties(getAdditionalPropertiesIfAny((NamedComponent) messageChannel)); + if (messageChannel instanceof NamedComponent namedComponent) { + messageChannelNode.addProperties(getAdditionalPropertiesIfAny(namedComponent)); } return messageChannelNode; }) @@ -318,8 +324,8 @@ private void consumers(Collection nodes, Collection l .map(e -> { IntegrationConsumer consumer = e.getValue(); MessageHandlerNode handlerNode = - consumer instanceof PollingConsumer - ? this.nodeFactory.polledHandlerNode(e.getKey(), (PollingConsumer) consumer) + consumer instanceof PollingConsumer pollingConsumer + ? this.nodeFactory.polledHandlerNode(e.getKey(), pollingConsumer) : this.nodeFactory.handlerNode(e.getKey(), consumer); handlerNode.addProperties(getAdditionalPropertiesIfAny(consumer)); return handlerNode; @@ -348,26 +354,24 @@ private void producerLink(Collection links, Map routes = ((RoutingMessageHandlerNode) endpointNode).getRoutes(); + if (endpointNode instanceof RoutingMessageHandlerNode routingMessageHandlerNode) { + Collection routes = routingMessageHandlerNode.getRoutes(); for (String route : routes) { channelNode = channelNodes.get(route); if (channelNode != null) { @@ -409,16 +413,10 @@ MessageGatewayNode gatewayNode(String name, MessagingGatewaySupport gateway) { return new MessageGatewayNode(this.nodeId.incrementAndGet(), name, gateway, requestChannel, errorChannel); } - @Nullable - private String channelToBeanName(MessageChannel messageChannel) { - return messageChannel instanceof NamedComponent namedComponent - ? namedComponent.getBeanName() - : Objects.toString(messageChannel, null); - } - MessageProducerNode producerNode(String name, MessageProducerSupport producer) { String errorChannel = channelToBeanName(producer.getErrorChannel()); String outputChannel = channelToBeanName(producer.getOutputChannel()); + Assert.state(outputChannel != null, "'outputChannel' must not be null"); return new MessageProducerNode(this.nodeId.incrementAndGet(), name, producer, outputChannel, errorChannel); } @@ -500,7 +498,7 @@ else if (handler instanceof RecipientListRouterManagement recipientListRouterMan } MessageHandlerNode compositeHandler(String name, IntegrationConsumer consumer, - CompositeMessageHandler handler, String output, String errors, boolean polled) { + CompositeMessageHandler handler, @Nullable String output, @Nullable String errors, boolean polled) { List innerHandlers = handler.getHandlers() @@ -522,7 +520,7 @@ MessageHandlerNode compositeHandler(String name, IntegrationConsumer consumer, } MessageHandlerNode discardingHandler(String name, IntegrationConsumer consumer, - DiscardingMessageHandler handler, String output, String errors, boolean polled) { + DiscardingMessageHandler handler, @Nullable String output, @Nullable String errors, boolean polled) { String discards = channelToBeanName(handler.getDiscardChannel()); String inputChannel = channelToBeanName(consumer.getInputChannel()); @@ -534,7 +532,7 @@ MessageHandlerNode discardingHandler(String name, IntegrationConsumer consumer, } MessageHandlerNode routingHandler(String name, IntegrationConsumer consumer, MessageHandler handler, - MappingMessageRouterManagement router, String output, String errors, boolean polled) { + MappingMessageRouterManagement router, @Nullable String output, @Nullable String errors, boolean polled) { Collection routes = Stream.concat(router.getChannelMappings().values().stream(), @@ -550,14 +548,19 @@ MessageHandlerNode routingHandler(String name, IntegrationConsumer consumer, Mes } MessageHandlerNode recipientListRoutingHandler(String name, IntegrationConsumer consumer, - MessageHandler handler, RecipientListRouterManagement router, String output, String errors, - boolean polled) { + MessageHandler handler, RecipientListRouterManagement router, @Nullable String output, + @Nullable String errors, boolean polled) { List routes = router.getRecipients() .stream() - .map(recipient -> channelToBeanName(((Recipient) recipient).getChannel())) - .collect(Collectors.toList()); + .map(recipient -> { + var messageChannel = channelToBeanName(((Recipient) recipient).getChannel()); + Assert.state(messageChannel != null, + "messageChannel must not be null for " + recipient); + return messageChannel; + }) + .toList(); String inputChannel = channelToBeanName(consumer.getInputChannel()); return polled @@ -571,6 +574,13 @@ void reset() { this.nodeId.set(0); } + @Contract("null -> null; !null -> !null") + private static @Nullable String channelToBeanName(@Nullable MessageChannel messageChannel) { + return messageChannel instanceof NamedComponent namedComponent + ? namedComponent.getBeanName() + : Objects.toString(messageChannel, null); + } + } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageChannelNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageChannelNode.java index dc04a9a6f18..5df5cc94ddc 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageChannelNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageChannelNode.java @@ -33,7 +33,7 @@ */ public class MessageChannelNode extends IntegrationNode implements SendTimersAware { - private Supplier sendTimers; + private @Nullable Supplier sendTimers; public MessageChannelNode(int nodeId, String name, MessageChannel channel) { super(nodeId, name, channel); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageGatewayNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageGatewayNode.java index c29c9ee2bb9..969e1549b86 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageGatewayNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageGatewayNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.gateway.MessagingGatewaySupport; /** @@ -28,7 +30,7 @@ */ public class MessageGatewayNode extends ErrorCapableEndpointNode { - public MessageGatewayNode(int nodeId, String name, MessagingGatewaySupport gateway, String output, String errors) { + public MessageGatewayNode(int nodeId, String name, MessagingGatewaySupport gateway, @Nullable String output, @Nullable String errors) { super(nodeId, name, gateway, output, errors); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageHandlerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageHandlerNode.java index fc05a6650cc..221db18023b 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageHandlerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageHandlerNode.java @@ -35,9 +35,9 @@ public class MessageHandlerNode extends EndpointNode implements SendTimersAware private final String input; - private Supplier sendTimers; + private @Nullable Supplier sendTimers; - public MessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, String output) { + public MessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output) { super(nodeId, name, handler, output); this.input = input; } @@ -46,8 +46,7 @@ public String getInput() { return this.input; } - @Nullable - public SendTimers getSendTimers() { + public @Nullable SendTimers getSendTimers() { return this.sendTimers != null ? this.sendTimers.get() : null; } @@ -57,4 +56,3 @@ public void sendTimers(Supplier timers) { } } - diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageProducerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageProducerNode.java index ee9f017e40d..81c75a49aa4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageProducerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageProducerNode.java @@ -16,6 +16,8 @@ package org.springframework.integration.graph; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.endpoint.MessageProducerSupport; /** @@ -28,7 +30,7 @@ */ public class MessageProducerNode extends ErrorCapableEndpointNode { - public MessageProducerNode(int nodeId, String name, MessageProducerSupport producer, String output, String errors) { + public MessageProducerNode(int nodeId, String name, MessageProducerSupport producer, String output, @Nullable String errors) { super(nodeId, name, producer, output, errors); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageSourceNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageSourceNode.java index d897ffb4341..8e239f6ff91 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageSourceNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/MessageSourceNode.java @@ -33,9 +33,9 @@ */ public class MessageSourceNode extends ErrorCapableEndpointNode implements ReceiveCountersAware { - private Supplier receiveCounters; + private @Nullable Supplier receiveCounters; - public MessageSourceNode(int nodeId, String name, MessageSource messageSource, String output, String errors) { + public MessageSourceNode(int nodeId, String name, MessageSource messageSource, String output, @Nullable String errors) { super(nodeId, name, messageSource, output, errors); } @@ -50,4 +50,3 @@ public void receiveCounters(Supplier counters) { } } - diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/MicrometerNodeEnhancer.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/MicrometerNodeEnhancer.java index 5084f1b0400..aaa71cf7dd1 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/MicrometerNodeEnhancer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/MicrometerNodeEnhancer.java @@ -22,6 +22,7 @@ import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.search.RequiredSearch; import io.micrometer.core.instrument.search.Search; import io.micrometer.observation.ObservationConvention; import org.jspecify.annotations.Nullable; @@ -33,6 +34,7 @@ import org.springframework.integration.support.management.observation.DefaultMessageRequestReplyReceiverObservationConvention; import org.springframework.integration.support.management.observation.DefaultMessageSenderObservationConvention; import org.springframework.integration.support.management.observation.IntegrationObservation; +import org.springframework.util.Assert; /** * Add micrometer metrics to the node. @@ -55,11 +57,14 @@ public class MicrometerNodeEnhancer { private static final TimerStats ZERO_TIMER_STATS = new TimerStats(0L, 0.0, 0.0); + @SuppressWarnings("NullAway.Init") private final MeterRegistry registry; MicrometerNodeEnhancer(ApplicationContext applicationContext) { ObjectProvider meterRegistryProvider = applicationContext.getBeanProvider(MeterRegistry.class); - this.registry = meterRegistryProvider.getIfUnique(); + var registry = meterRegistryProvider.getIfUnique(); + Assert.state(registry != null, "MeterRegistry must not be null"); + this.registry = registry; } /** @@ -100,14 +105,13 @@ private SendTimers retrieveTimers(T node, String typ return new SendTimers(buildTimerStats(successTimer), buildTimerStats(failureTimer)); } - @Nullable - private Timer obtainTimer(T node, String type, boolean success) { + private @Nullable Timer obtainTimer(T node, String type, boolean success) { try { if (node.isObserved()) { return observationTimer(node, type, success); } else { - return this.registry.get(IntegrationManagement.SEND_TIMER_NAME) + return getRegistry(IntegrationManagement.SEND_TIMER_NAME) .tag(TAG_TYPE, type) .tag(TAG_NAME, node.getName()) .tag(TAG_RESULT, success ? "success" : "failure") @@ -119,8 +123,12 @@ private Timer obtainTimer(T node, String type, boole } } - @Nullable - private Timer observationTimer(T node, String type, boolean success) { + private RequiredSearch getRegistry(String name) { + Assert.state(this.registry != null, "registry must not be null"); + return this.registry.get(name); + } + + private @Nullable Timer observationTimer(T node, String type, boolean success) { Search timerSearch = switch (type) { case "channel" -> buildTimerSearch(DefaultMessageSenderObservationConvention.INSTANCE, @@ -143,7 +151,9 @@ private Timer observationTimer(T node, String type, } private Search buildTimerSearch(ObservationConvention observationConvention, KeyName tagKey, String tagValue) { - return this.registry.find(observationConvention.getName()).tag(tagKey.asString(), tagValue); // NOSONAR + Assert.state(observationConvention.getName() != null, "observationConvention.getName() must have a name"); + Assert.state(this.registry != null, "registry must not be null"); + return this.registry.find(observationConvention.getName()).tag(tagKey.asString(), tagValue); } private void enhanceWithCounts(T node, String type) { @@ -154,7 +164,7 @@ private ReceiveCounters retrieveCounters(T node, Str Counter successes = null; String name = node.getName(); try { - successes = this.registry.get(IntegrationManagement.RECEIVE_COUNTER_NAME) + successes = getRegistry(IntegrationManagement.RECEIVE_COUNTER_NAME) .tag(TAG_TYPE, type) .tag(TAG_NAME, name) .tag(TAG_RESULT, "success") @@ -165,7 +175,7 @@ private ReceiveCounters retrieveCounters(T node, Str } Counter failures = null; try { - failures = this.registry.get(IntegrationManagement.RECEIVE_COUNTER_NAME) + failures = getRegistry(IntegrationManagement.RECEIVE_COUNTER_NAME) .tag(TAG_TYPE, type) .tag(TAG_NAME, name) .tag(TAG_RESULT, "failure") diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/PollableChannelNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/PollableChannelNode.java index 3873dfbc2ec..16a036513f0 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/PollableChannelNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/PollableChannelNode.java @@ -33,7 +33,7 @@ */ public class PollableChannelNode extends MessageChannelNode implements ReceiveCountersAware { - private Supplier receiveCounters; + private @Nullable Supplier receiveCounters; public PollableChannelNode(int nodeId, String name, MessageChannel channel) { super(nodeId, name, channel); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/RoutingMessageHandlerNode.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/RoutingMessageHandlerNode.java index d5ad83f68b0..a824b95f693 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/RoutingMessageHandlerNode.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/RoutingMessageHandlerNode.java @@ -18,6 +18,8 @@ import java.util.Collection; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.MessageHandler; /** @@ -32,7 +34,7 @@ public class RoutingMessageHandlerNode extends MessageHandlerNode { private final Collection routes; - public RoutingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, String output, + public RoutingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output, Collection routes) { super(nodeId, name, handler, input, output); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/package-info.java index 4c10d364555..20d97d12e8f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes related to the runtime object graph. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.graph;