From c082badcd6239976a34fcf1a7a8c33bf94257788 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Tue, 2 Sep 2025 11:24:25 -0400 Subject: [PATCH 1/3] GH-10083: Nullability for graph in core module * Add Nullability to core module's graph package. * `buildGraph` and `getGraph` methods in the `IntegrationGraphServer` because Nullify could not see the creation of the graph * `IntegrationGraphServer.receiptListRoutingHandler` required a change where the messageChannel could not be null in the `map` portion of expression. So it was extracted into a var and the var was checked for null. --- .../graph/CompositeMessageHandlerNode.java | 4 +- .../graph/DiscardingMessageHandlerNode.java | 10 ++-- .../integration/graph/EndpointNode.java | 8 ++-- ...rorCapableCompositeMessageHandlerNode.java | 10 ++-- ...orCapableDiscardingMessageHandlerNode.java | 10 ++-- .../graph/ErrorCapableEndpointNode.java | 8 ++-- .../graph/ErrorCapableMessageHandlerNode.java | 10 ++-- .../integration/graph/ErrorCapableNode.java | 3 ++ .../graph/ErrorCapableRoutingNode.java | 10 ++-- .../graph/IntegrationGraphRuntimeHints.java | 4 +- .../graph/IntegrationGraphServer.java | 46 +++++++++++-------- .../integration/graph/MessageChannelNode.java | 2 +- .../integration/graph/MessageGatewayNode.java | 4 +- .../integration/graph/MessageHandlerNode.java | 9 ++-- .../graph/MessageProducerNode.java | 4 +- .../integration/graph/MessageSourceNode.java | 5 +- .../graph/MicrometerNodeEnhancer.java | 25 ++++++---- .../graph/PollableChannelNode.java | 2 +- .../graph/RoutingMessageHandlerNode.java | 4 +- .../integration/graph/package-info.java | 1 + 20 files changed, 111 insertions(+), 68 deletions(-) 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..1889431f23c 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, @Nullable 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..937dcd8dfb6 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, @Nullable 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..db8a9727f43 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, + @Nullable 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..7d016a978c7 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) { + public ErrorCapableDiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, + @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..65e146c3cc4 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) { + public ErrorCapableMessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, + @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..52f96203c29 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, @Nullable 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..e0077dc340e 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 @@ -58,6 +58,7 @@ 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,22 +79,22 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat private final NodeFactory nodeFactory = new NodeFactory(this::enhance); - private MicrometerNodeEnhancer micrometerEnhancer; + private @Nullable MicrometerNodeEnhancer micrometerEnhancer; - private ApplicationContext applicationContext; + private @Nullable 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) } - protected ApplicationContext getApplicationContext() { + protected @Nullable ApplicationContext getApplicationContext() { return this.applicationContext; // NOSONAR (sync) } @@ -132,6 +133,7 @@ public void onApplicationEvent(ContextRefreshedEvent event) { * @return the graph. * @see #rebuild() */ + @SuppressWarnings("NullAway") // Dataflow analysis limitation public Graph getGraph() { if (this.graph == null) { this.lock.lock(); @@ -173,6 +175,9 @@ public Graph rebuild() { * @since 5.1 */ protected Map getBeansOfType(Class type) { + if (this.applicationContext == null) { + throw new IllegalStateException("ApplicationContext is not set"); + } return this.applicationContext.getBeansOfType(type, true, false); } @@ -185,7 +190,11 @@ private T enhance(T node) { } } + @SuppressWarnings("NullAway") // Dataflow analysis limitation private Graph buildGraph() { + if (this.applicationContext == null) { + throw new IllegalStateException("ApplicationContext is not set"); + } if (this.micrometerEnhancer == null && MicrometerMetricsCaptorConfiguration.METER_REGISTRY_PRESENT) { this.micrometerEnhancer = new MicrometerNodeEnhancer(this.applicationContext); } @@ -348,11 +357,9 @@ private void producerLink(Collection links, Map innerHandlers = handler.getHandlers() @@ -522,7 +528,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 +540,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,13 +556,17 @@ MessageHandlerNode routingHandler(String name, IntegrationConsumer consumer, Mes } MessageHandlerNode recipientListRoutingHandler(String name, IntegrationConsumer consumer, - MessageHandler handler, RecipientListRouterManagement router, String output, String errors, + MessageHandler handler, RecipientListRouterManagement router, @Nullable String output, @Nullable String errors, boolean polled) { List routes = router.getRecipients() .stream() - .map(recipient -> channelToBeanName(((Recipient) recipient).getChannel())) + .map(recipient -> { + var messageChannel = channelToBeanName(((Recipient) recipient).getChannel()); + Assert.state(messageChannel != null, "messageChannel must not be null for " + recipient); + return messageChannel; + }) .collect(Collectors.toList()); String inputChannel = channelToBeanName(consumer.getInputChannel()); 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..f903119f086 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 @@ -33,16 +33,16 @@ */ public class MessageHandlerNode extends EndpointNode implements SendTimersAware { - private final String input; + private final @Nullable 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, @Nullable String input, @Nullable String output) { super(nodeId, name, handler, output); this.input = input; } - public String getInput() { + public @Nullable String getInput() { return this.input; } @@ -57,4 +57,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..70cb2fe9309 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, @Nullable 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..8c1730f1c73 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, @Nullable 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..a0c88753338 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,7 +57,7 @@ public class MicrometerNodeEnhancer { private static final TimerStats ZERO_TIMER_STATS = new TimerStats(0L, 0.0, 0.0); - private final MeterRegistry registry; + private final @Nullable MeterRegistry registry; MicrometerNodeEnhancer(ApplicationContext applicationContext) { ObjectProvider meterRegistryProvider = applicationContext.getBeanProvider(MeterRegistry.class); @@ -100,14 +102,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 +120,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 +148,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 +161,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 +172,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..eae4973329d 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, @Nullable 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; From 3ed266fa25d11c1f6d7fce219d66c2ee5a41bc1f Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Wed, 3 Sep 2025 07:50:50 -0400 Subject: [PATCH 2/3] Remove unnecessary Nullable annotations * Set AppContext to not be nullable * Consumer's inbound channels are never null. Update to remove nullable * Update outbound channels so they are not nullable * Use local variable trick to work past Nullables inability to see a new above return value * Add contract to channelToBeanName in IntegrationGraphServer --- .../graph/CompositeMessageHandlerNode.java | 2 +- .../graph/DiscardingMessageHandlerNode.java | 2 +- ...rorCapableCompositeMessageHandlerNode.java | 2 +- ...orCapableDiscardingMessageHandlerNode.java | 2 +- .../graph/ErrorCapableMessageHandlerNode.java | 2 +- .../graph/ErrorCapableRoutingNode.java | 2 +- .../graph/IntegrationGraphServer.java | 24 +++++++++---------- .../integration/graph/MessageHandlerNode.java | 9 ++++--- .../graph/MessageProducerNode.java | 2 +- .../integration/graph/MessageSourceNode.java | 2 +- .../graph/MicrometerNodeEnhancer.java | 7 ++++-- .../graph/RoutingMessageHandlerNode.java | 2 +- 12 files changed, 29 insertions(+), 29 deletions(-) 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 1889431f23c..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 @@ -35,7 +35,7 @@ public class CompositeMessageHandlerNode extends MessageHandlerNode { private final List handlers = new ArrayList<>(); - public CompositeMessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, @Nullable 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 937dcd8dfb6..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 @@ -32,7 +32,7 @@ public class DiscardingMessageHandlerNode extends MessageHandlerNode { private final @Nullable String discards; - public DiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, + public DiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output, @Nullable String discards) { super(nodeId, name, handler, input, 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 db8a9727f43..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 @@ -36,7 +36,7 @@ public class ErrorCapableCompositeMessageHandlerNode extends CompositeMessageHan private final @Nullable String errors; public ErrorCapableCompositeMessageHandlerNode(int nodeId, String name, CompositeMessageHandler handler, - @Nullable String input, @Nullable String output, @Nullable String errors, List handlers) { + String input, @Nullable String output, @Nullable String errors, List handlers) { super(nodeId, name, handler, input, output, handlers); this.errors = 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 7d016a978c7..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 @@ -33,7 +33,7 @@ public class ErrorCapableDiscardingMessageHandlerNode extends DiscardingMessageH private final @Nullable String errors; - public ErrorCapableDiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, + public ErrorCapableDiscardingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output, @Nullable String discards, @Nullable String errors) { super(nodeId, name, handler, input, output, discards); 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 65e146c3cc4..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 @@ -31,7 +31,7 @@ public class ErrorCapableMessageHandlerNode extends MessageHandlerNode implement private final @Nullable String errors; - public ErrorCapableMessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, + public ErrorCapableMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output, @Nullable String errors) { super(nodeId, name, handler, input, output); 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 52f96203c29..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 @@ -35,7 +35,7 @@ public class ErrorCapableRoutingNode extends RoutingMessageHandlerNode implement private final @Nullable String errors; - public ErrorCapableRoutingNode(int nodeId, String name, MessageHandler handler, @Nullable String input, @Nullable String output, + 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); 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 e0077dc340e..9a5691f2fe2 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,6 +55,7 @@ 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; @@ -81,7 +82,8 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat private @Nullable MicrometerNodeEnhancer micrometerEnhancer; - private @Nullable ApplicationContext applicationContext; + @SuppressWarnings("NullAway.Init") + private ApplicationContext applicationContext; private volatile @Nullable Graph graph; @@ -133,20 +135,20 @@ public void onApplicationEvent(ContextRefreshedEvent event) { * @return the graph. * @see #rebuild() */ - @SuppressWarnings("NullAway") // Dataflow analysis limitation public Graph getGraph() { if (this.graph == null) { this.lock.lock(); try { if (this.graph == null) { - buildGraph(); + this.graph = buildGraph(); } } finally { this.lock.unlock(); } } - return this.graph; + var graph = this.graph; + return graph; } /** @@ -175,9 +177,6 @@ public Graph rebuild() { * @since 5.1 */ protected Map getBeansOfType(Class type) { - if (this.applicationContext == null) { - throw new IllegalStateException("ApplicationContext is not set"); - } return this.applicationContext.getBeansOfType(type, true, false); } @@ -190,11 +189,7 @@ private T enhance(T node) { } } - @SuppressWarnings("NullAway") // Dataflow analysis limitation private Graph buildGraph() { - if (this.applicationContext == null) { - throw new IllegalStateException("ApplicationContext is not set"); - } if (this.micrometerEnhancer == null && MicrometerMetricsCaptorConfiguration.METER_REGISTRY_PRESENT) { this.micrometerEnhancer = new MicrometerNodeEnhancer(this.applicationContext); } @@ -221,8 +216,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 graph = new Graph(descriptor, nodes, links); + this.graph = graph; + return graph; } private Map channels(Collection nodes) { @@ -416,6 +412,7 @@ MessageGatewayNode gatewayNode(String name, MessagingGatewaySupport gateway) { return new MessageGatewayNode(this.nodeId.incrementAndGet(), name, gateway, requestChannel, errorChannel); } + @Contract("null -> null; !null -> !null") private @Nullable String channelToBeanName(@Nullable MessageChannel messageChannel) { return messageChannel instanceof NamedComponent namedComponent ? namedComponent.getBeanName() @@ -425,6 +422,7 @@ MessageGatewayNode gatewayNode(String name, MessagingGatewaySupport gateway) { 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); } 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 f903119f086..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 @@ -33,21 +33,20 @@ */ public class MessageHandlerNode extends EndpointNode implements SendTimersAware { - private final @Nullable String input; + private final String input; private @Nullable Supplier sendTimers; - public MessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, @Nullable String output) { + public MessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output) { super(nodeId, name, handler, output); this.input = input; } - public @Nullable String getInput() { + public String getInput() { return this.input; } - @Nullable - public SendTimers getSendTimers() { + public @Nullable SendTimers getSendTimers() { return this.sendTimers != null ? this.sendTimers.get() : null; } 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 70cb2fe9309..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 @@ -30,7 +30,7 @@ */ public class MessageProducerNode extends ErrorCapableEndpointNode { - public MessageProducerNode(int nodeId, String name, MessageProducerSupport producer, @Nullable String output, @Nullable 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 8c1730f1c73..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 @@ -35,7 +35,7 @@ public class MessageSourceNode extends ErrorCapableEndpointNode implements Recei private @Nullable Supplier receiveCounters; - public MessageSourceNode(int nodeId, String name, MessageSource messageSource, @Nullable String output, @Nullable String errors) { + public MessageSourceNode(int nodeId, String name, MessageSource messageSource, String output, @Nullable String errors) { super(nodeId, name, messageSource, output, errors); } 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 a0c88753338..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 @@ -57,11 +57,14 @@ public class MicrometerNodeEnhancer { private static final TimerStats ZERO_TIMER_STATS = new TimerStats(0L, 0.0, 0.0); - private final @Nullable MeterRegistry registry; + @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; } /** 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 eae4973329d..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 @@ -34,7 +34,7 @@ public class RoutingMessageHandlerNode extends MessageHandlerNode { private final Collection routes; - public RoutingMessageHandlerNode(int nodeId, String name, MessageHandler handler, @Nullable String input, @Nullable String output, + public RoutingMessageHandlerNode(int nodeId, String name, MessageHandler handler, String input, @Nullable String output, Collection routes) { super(nodeId, name, handler, input, output); From ec20eb0cbbd7f5cc0593c781f1eb3b90e9c32257 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Wed, 3 Sep 2025 10:54:51 -0400 Subject: [PATCH 3/3] Update local variables to be used consistently --- .../graph/IntegrationGraphServer.java | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) 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 9a5691f2fe2..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 @@ -93,11 +93,11 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; // NOSONAR (sync) + this.applicationContext = applicationContext; } - protected @Nullable ApplicationContext getApplicationContext() { - return this.applicationContext; // NOSONAR (sync) + protected ApplicationContext getApplicationContext() { + return this.applicationContext; } /** @@ -107,7 +107,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws * @param applicationName the application name. */ public void setApplicationName(String applicationName) { - this.applicationName = applicationName; //NOSONAR (sync) + this.applicationName = applicationName; } /** @@ -136,19 +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) { - this.graph = buildGraph(); + localGraph = this.graph; + if (localGraph == null) { + localGraph = buildGraph(); } } finally { this.lock.unlock(); } } - var graph = this.graph; - return graph; + return localGraph; } /** @@ -216,9 +217,9 @@ private Graph buildGraph() { gateways(nodes, links, channelNodes); producers(nodes, links, channelNodes); consumers(nodes, links, channelNodes); - var graph = new Graph(descriptor, nodes, links); - this.graph = graph; - return graph; + var localGraph = new Graph(descriptor, nodes, links); + this.graph = localGraph; + return localGraph; } private Map channels(Collection nodes) { @@ -228,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; }) @@ -323,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; @@ -357,20 +358,20 @@ 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) { @@ -412,13 +413,6 @@ MessageGatewayNode gatewayNode(String name, MessagingGatewaySupport gateway) { return new MessageGatewayNode(this.nodeId.incrementAndGet(), name, gateway, requestChannel, errorChannel); } - @Contract("null -> null; !null -> !null") - private @Nullable String channelToBeanName(@Nullable 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()); @@ -554,18 +548,19 @@ MessageHandlerNode routingHandler(String name, IntegrationConsumer consumer, Mes } MessageHandlerNode recipientListRoutingHandler(String name, IntegrationConsumer consumer, - MessageHandler handler, RecipientListRouterManagement router, @Nullable String output, @Nullable String errors, - boolean polled) { + MessageHandler handler, RecipientListRouterManagement router, @Nullable String output, + @Nullable String errors, boolean polled) { List routes = router.getRecipients() .stream() .map(recipient -> { var messageChannel = channelToBeanName(((Recipient) recipient).getChannel()); - Assert.state(messageChannel != null, "messageChannel must not be null for " + recipient); + Assert.state(messageChannel != null, + "messageChannel must not be null for " + recipient); return messageChannel; }) - .collect(Collectors.toList()); + .toList(); String inputChannel = channelToBeanName(consumer.getInputChannel()); return polled @@ -579,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); + } + } }