From 9b2648f59b2f3c547aa61d3ec9c6b63d91c19ddf Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Tue, 10 Jun 2025 14:40:28 -0400 Subject: [PATCH 1/8] Update SI Core to add Nullability to module This is a first pass at the module to make sure it is being converted properly. Related to https://github.com/spring-projects/spring-integration/issues/10083 --- .../context/ExpressionCapable.java | 6 +++++- .../context/IntegrationContextUtils.java | 8 +++++++ .../context/IntegrationObjectSupport.java | 21 ++++++++++++++++++- .../context/IntegrationProperties.java | 5 ++++- .../integration/context/package-info.java | 1 + 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java b/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java index cedeb5bdafb..b9498f96984 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.integration.context; + +import org.jspecify.annotations.Nullable; + import org.springframework.expression.Expression; /** @@ -32,6 +35,7 @@ public interface ExpressionCapable { * Return the primary SpEL expression if this component is expression-based. * @return the expression as a String. */ + @Nullable Expression getExpression(); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java index dd605557cf9..c84f9203a58 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java @@ -16,6 +16,8 @@ package org.springframework.integration.context; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; @@ -120,6 +122,7 @@ public abstract class IntegrationContextUtils { * @param beanFactory BeanFactory for lookup, must not be null. * @return The {@link MetadataStore} bean whose name is "metadataStore". */ + @Nullable public static MetadataStore getMetadataStore(BeanFactory beanFactory) { return getBeanOfType(beanFactory, METADATA_STORE_BEAN_NAME, MetadataStore.class); } @@ -128,6 +131,7 @@ public static MetadataStore getMetadataStore(BeanFactory beanFactory) { * @param beanFactory BeanFactory for lookup, must not be null. * @return The {@link MessageChannel} bean whose name is "errorChannel". */ + @Nullable public static MessageChannel getErrorChannel(BeanFactory beanFactory) { return getBeanOfType(beanFactory, ERROR_CHANNEL_BEAN_NAME, MessageChannel.class); } @@ -136,6 +140,7 @@ public static MessageChannel getErrorChannel(BeanFactory beanFactory) { * @param beanFactory BeanFactory for lookup, must not be null. * @return The {@link TaskScheduler} bean whose name is "taskScheduler" if available. */ + @Nullable public static TaskScheduler getTaskScheduler(BeanFactory beanFactory) { return getBeanOfType(beanFactory, TASK_SCHEDULER_BEAN_NAME, TaskScheduler.class); } @@ -156,6 +161,7 @@ public static TaskScheduler getRequiredTaskScheduler(BeanFactory beanFactory) { * @return the instance of {@link StandardEvaluationContext} bean whose name is * {@value #INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME}. */ + @Nullable public static StandardEvaluationContext getEvaluationContext(BeanFactory beanFactory) { return getBeanOfType(beanFactory, INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, StandardEvaluationContext.class); } @@ -166,11 +172,13 @@ public static StandardEvaluationContext getEvaluationContext(BeanFactory beanFac * {@value #INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME}. * @since 4.3.15 */ + @Nullable public static SimpleEvaluationContext getSimpleEvaluationContext(BeanFactory beanFactory) { return getBeanOfType(beanFactory, INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME, SimpleEvaluationContext.class); } + @Nullable private static T getBeanOfType(BeanFactory beanFactory, String beanName, Class type) { Assert.notNull(beanFactory, "BeanFactory must not be null"); if (!beanFactory.containsBean(beanName)) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java index de14144d7d7..0f1fbf3db60 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java @@ -72,38 +72,50 @@ public abstract class IntegrationObjectSupport implements ComponentSourceAware, protected final LogAccessor logger = new LogAccessor(getClass()); // NOSONAR protected + @SuppressWarnings("NullAway.Init") private DestinationResolver channelResolver; + @SuppressWarnings("NullAway.Init") private String beanName; + @Nullable private String componentName; + @SuppressWarnings("NullAway.Init") private BeanFactory beanFactory; + @Nullable private TaskScheduler taskScheduler; private IntegrationProperties integrationProperties = new IntegrationProperties(); + @Nullable private ConversionService conversionService; + @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; + @SuppressWarnings("NullAway.Init") private MessageBuilderFactory messageBuilderFactory; + @Nullable private Expression expression; + @Nullable private Object beanSource; + @Nullable private String beanDescription; private boolean initialized; @Override - public final void setBeanName(@Nullable String beanName) { + public final void setBeanName(String beanName) { this.beanName = beanName; } @Override + @Nullable public String getBeanName() { return this.beanName; } @@ -113,6 +125,7 @@ public String getBeanName() { * If {@link #componentName} was not set this method will default to the 'beanName' of this component; */ @Override + @Nullable public String getComponentName() { return StringUtils.hasText(this.componentName) ? this.componentName : this.beanName; } @@ -128,6 +141,7 @@ public void setComponentName(String componentName) { /** * Subclasses may implement this method to provide component type information. */ + @Nullable @Override public String getComponentType() { return null; @@ -195,6 +209,7 @@ public void setChannelResolver(DestinationResolver channelResolv } @Override + @Nullable public Expression getExpression() { return this.expression; } @@ -208,6 +223,7 @@ public final void setPrimaryExpression(Expression expression) { this.expression = expression; } + @SuppressWarnings("NullAway.Init") @Override public final void afterPropertiesSet() { this.integrationProperties = IntegrationContextUtils.getIntegrationProperties(this.beanFactory); @@ -264,6 +280,7 @@ public void setTaskScheduler(TaskScheduler taskScheduler) { this.taskScheduler = taskScheduler; } + @Nullable protected TaskScheduler getTaskScheduler() { if (this.taskScheduler == null && this.beanFactory != null) { this.taskScheduler = IntegrationContextUtils.getTaskScheduler(this.beanFactory); @@ -278,6 +295,7 @@ protected DestinationResolver getChannelResolver() { return this.channelResolver; } + @Nullable public ConversionService getConversionService() { if (this.conversionService == null && this.beanFactory != null) { this.conversionService = IntegrationUtils.getConversionService(this.beanFactory); @@ -299,6 +317,7 @@ public void setConversionService(ConversionService conversionService) { * {@link ApplicationContext} is available. * @return The id, or null if there is no application context. */ + @Nullable public String getApplicationContextId() { return this.applicationContext == null ? null : this.applicationContext.getId(); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationProperties.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationProperties.java index d31bd8c9303..3d005ad2076 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationProperties.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2024 the original author or authors. + * Copyright 2014-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,8 @@ import java.util.Arrays; import java.util.Properties; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.JavaUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -139,6 +141,7 @@ public final class IntegrationProperties { private long endpointsDefaultTimeout = IntegrationContextUtils.DEFAULT_TIMEOUT; + @Nullable private volatile Properties properties; static { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/context/package-info.java index 1acc7924df0..e72e965c195 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes relating to application context configuration. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.context; From ed5f14f8c1c36f0019a6523cc7faab955363fcc8 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Tue, 10 Jun 2025 15:20:24 -0400 Subject: [PATCH 2/8] Add nullability to org.springframework.messaging.core package --- .../integration/core/ErrorMessagePublisher.java | 6 +++++- .../springframework/integration/core/MessagingTemplate.java | 6 ++++-- .../org/springframework/integration/core/package-info.java | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/core/ErrorMessagePublisher.java b/spring-integration-core/src/main/java/org/springframework/integration/core/ErrorMessagePublisher.java index fa6c4770b63..27faee4246a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/core/ErrorMessagePublisher.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/core/ErrorMessagePublisher.java @@ -54,10 +54,13 @@ public class ErrorMessagePublisher implements BeanFactoryAware { protected final MessagingTemplate messagingTemplate = new MessagingTemplate(); // NOSONAR final + @SuppressWarnings("NullAway.Init") private DestinationResolver channelResolver; + @Nullable private MessageChannel channel; + @Nullable private String channelName; private ErrorMessageStrategy errorMessageStrategy = new DefaultErrorMessageStrategy(); @@ -79,6 +82,7 @@ public ErrorMessageStrategy getErrorMessageStrategy() { return this.errorMessageStrategy; } + @Nullable public MessageChannel getChannel() { populateChannel(); return this.channel; @@ -146,7 +150,7 @@ public void publish(Message inputMessage, MessagingException exception) { * @param failedMessage the message. * @param throwable the throwable. */ - public void publish(@Nullable Message inputMessage, Message failedMessage, Throwable throwable) { + public void publish(@Nullable Message inputMessage, @Nullable Message failedMessage, Throwable throwable) { publish(throwable, ErrorMessageUtils.getAttributeAccessor(inputMessage, failedMessage)); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java b/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java index 95552bb7285..2557e8bbd6e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java @@ -44,6 +44,7 @@ public class MessagingTemplate extends GenericMessagingTemplate { private final Lock lock = new ReentrantLock(); + @SuppressWarnings("NullAway.Init") private BeanFactory beanFactory; private volatile boolean throwExceptionOnLateReplySet; @@ -84,7 +85,7 @@ public void setThrowExceptionOnLateReply(boolean throwExceptionOnLateReply) { * backward compatibility. * @param channel the channel to set. */ - public void setDefaultChannel(MessageChannel channel) { + public void setDefaultChannel(@Nullable MessageChannel channel) { super.setDefaultDestination(channel); } @@ -109,6 +110,7 @@ public Message sendAndReceive(MessageChannel destination, Message requestM return super.sendAndReceive(destination, requestMessage); } + @Nullable public Object receiveAndConvert(MessageChannel destination, long timeout) { Message message = doReceive(destination, timeout); if (message != null) { @@ -118,7 +120,7 @@ public Object receiveAndConvert(MessageChannel destination, long timeout) { return null; } } - + @Nullable public Message receive(MessageChannel destination, long timeout) { return doReceive(destination, timeout); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/core/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/core/package-info.java index b6f850c4881..b1ecdac03f3 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/core/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/core/package-info.java @@ -1,4 +1,5 @@ /** * Provides core classes. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.core; From 14e6be7cdd1f3b9428b1d01dbd9bdcf598adea57 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Wed, 11 Jun 2025 08:38:57 -0400 Subject: [PATCH 3/8] Add nullability to org.springframework.aggregator & org.springframework.acks packages Note in this commit that there cases where methods are called where the parameters passed in may contain a null. In those cases the attribute that contains the potential null is tested with an `Assert.notNull`. This may not be the best approach, let's discuss. Also note that in FluxAggregatorMessageHandler line 112 `@NullUnmarked` is used on the the applyWindowOptions method. This is because the consumer.apply on line 121 can not be null according to JSpecify. But we can't make that assumption for how the user implemented the function. There maybe a better way of handling this besides marking the method as `NullUnmarked`. Let's discuss. Similarly in FluxAggregatorMessageHandler the way in which sequenceSizeHeader is utilized it had to be `@NullUnmarked`. Let's discuss Make sure all annotations are applied consistently --- .../integration/acks/package-info.java | 2 +- ...tractAggregatingMessageGroupProcessor.java | 5 ++- .../AbstractCorrelatingMessageHandler.java | 37 ++++++++++++++----- .../aggregator/AggregatingMessageHandler.java | 6 ++- .../aggregator/BarrierMessageHandler.java | 7 +++- .../aggregator/CorrelatingMessageBarrier.java | 11 +++++- .../aggregator/CorrelationStrategy.java | 5 ++- .../DelegatingMessageGroupProcessor.java | 3 +- ...essionEvaluatingMessageGroupProcessor.java | 5 ++- ...ressionEvaluatingMessageListProcessor.java | 6 ++- .../FluxAggregatorMessageHandler.java | 19 ++++++++-- .../HeaderAttributeCorrelationStrategy.java | 5 ++- .../aggregator/MessageGroupProcessor.java | 5 ++- .../aggregator/MessageListProcessor.java | 5 ++- .../MethodInvokingCorrelationStrategy.java | 5 ++- .../MethodInvokingMessageGroupProcessor.java | 5 ++- .../MethodInvokingReleaseStrategy.java | 4 +- .../ResequencingMessageGroupProcessor.java | 5 ++- .../ResequencingMessageHandler.java | 8 ++-- .../integration/aggregator/package-info.java | 1 + .../context/ExpressionCapable.java | 1 - .../context/IntegrationObjectSupport.java | 8 ++-- .../integration/core/MessagingTemplate.java | 1 + 23 files changed, 121 insertions(+), 38 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/acks/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/acks/package-info.java index f341052a884..c263244d02d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/acks/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/acks/package-info.java @@ -1,5 +1,5 @@ /** * Provides classes related to message acknowledgment. */ -@org.springframework.lang.NonNullApi +@org.jspecify.annotations.NullMarked package org.springframework.integration.acks; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java index 2e3ad25b6f0..943e61544ba 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -56,6 +57,7 @@ public abstract class AbstractAggregatingMessageGroupProcessor implements Messag private boolean messageBuilderFactorySet; + @SuppressWarnings("NullAway.Init") private BeanFactory beanFactory; @Override @@ -117,6 +119,7 @@ protected Map aggregateHeaders(MessageGroup group) { return getHeadersFunction().apply(group); } + @Nullable protected abstract Object aggregatePayloads(MessageGroup group, Map defaultHeaders); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java index 7a7cae7320d..038be5657dc 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java @@ -65,6 +65,7 @@ import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; @@ -125,8 +126,10 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageP private boolean releaseStrategySet; + @SuppressWarnings("NullAway.Init") private MessageChannel discardChannel; + @Nullable private String discardChannelName; private boolean sendPartialResultOnExpiry; @@ -143,18 +146,23 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageP private boolean releasePartialSequences; + @Nullable private Expression groupTimeoutExpression; + @Nullable private List forceReleaseAdviceChain; private long expireTimeout; + @Nullable private Duration expireDuration; private MessageGroupProcessor forceReleaseProcessor = new ForceReleaseMessageGroupProcessor(); + @SuppressWarnings("NullAway.Init") private EvaluationContext evaluationContext; + @Nullable private ApplicationEventPublisher applicationEventPublisher; private boolean expireGroupsUponTimeout = true; @@ -165,10 +173,11 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageP private volatile boolean running; + @Nullable private BiFunction, String, String> groupConditionSupplier; public AbstractCorrelatingMessageHandler(MessageGroupProcessor processor, MessageGroupStore store, - CorrelationStrategy correlationStrategy, ReleaseStrategy releaseStrategy) { + @Nullable CorrelationStrategy correlationStrategy, @Nullable ReleaseStrategy releaseStrategy) { Assert.notNull(processor, "'processor' must not be null"); Assert.notNull(store, "'store' must not be null"); @@ -504,6 +513,7 @@ public MessageChannel getDiscardChannel() { return this.discardChannel; } + @Nullable protected String getDiscardChannelName() { return this.discardChannelName; } @@ -532,6 +542,7 @@ protected boolean isReleasePartialSequences() { return this.releasePartialSequences; } + @Nullable protected Expression getGroupTimeoutExpression() { return this.groupTimeoutExpression; } @@ -641,8 +652,10 @@ protected boolean isExpireGroupsUponCompletion() { } private void removeEmptyGroupAfterTimeout(UUID groupId, long timeout) { + TaskScheduler taskScheduler = getTaskScheduler(); + Assert.notNull(taskScheduler, "'taskScheduler' must not be null"); ScheduledFuture scheduledFuture = - getTaskScheduler() + taskScheduler .schedule(() -> { Lock lock = this.lockRegistry.obtain(groupId.toString()); @@ -699,8 +712,10 @@ else if ((Long) groupTimeout > 0) { Object groupId = messageGroup.getGroupId(); long timestamp = messageGroup.getTimestamp(); long lastModified = messageGroup.getLastModified(); + TaskScheduler taskScheduler = getTaskScheduler(); + Assert.notNull(taskScheduler, "'taskScheduler' must not be null"); ScheduledFuture scheduledFuture = - getTaskScheduler() + taskScheduler .schedule(() -> { try { processForceRelease(groupId, timestamp, lastModified); @@ -753,7 +768,7 @@ private void discardMessage(Message message) { * @param group The group. * @param completedMessages The completed messages. */ - protected abstract void afterRelease(MessageGroup group, Collection> completedMessages); + protected abstract void afterRelease(MessageGroup group, @Nullable Collection> completedMessages); /** * Subclasses may override if special action is needed because the group was released or discarded @@ -912,14 +927,12 @@ protected void expireGroup(Object correlationKey, MessageGroup group, Lock lock) } protected void completeGroup(Object correlationKey, MessageGroup group, Lock lock) { - Message first = null; - if (group != null) { - first = group.getOne(); - } + Message first = group.getOne(); completeGroup(first, correlationKey, group, lock); } @SuppressWarnings("unchecked") + @Nullable protected Collection> completeGroup(Message message, Object correlationKey, MessageGroup group, Lock lock) { @@ -929,6 +942,7 @@ protected Collection> completeGroup(Message message, Object correl this.logger.debug(() -> "Completing group with correlationKey [" + correlationKey + "]"); result = this.outputProcessor.processMessageGroup(group); + Assert.notNull(result, "the group returned a null result"); if (isResultCollectionOfMessages(result)) { partialSequence = (Collection>) result; } @@ -988,6 +1002,7 @@ private static boolean isResultCollectionOfMessages(Object result) { return false; } + @Nullable protected Object obtainGroupTimeout(MessageGroup group) { if (this.groupTimeoutExpression != null) { Object timeout = this.groupTimeoutExpression.getValue(this.evaluationContext, group); @@ -1024,7 +1039,9 @@ public void start() { if (this.expireTimeout > 0) { purgeOrphanedGroups(); if (this.expireDuration != null) { - getTaskScheduler() + TaskScheduler taskScheduler = getTaskScheduler(); + Assert.notNull(taskScheduler, "'taskScheduler' must not be null"); + taskScheduler .scheduleWithFixedDelay(this::purgeOrphanedGroups, this.expireDuration); } } @@ -1062,6 +1079,7 @@ public void purgeOrphanedGroups() { protected static class SequenceAwareMessageGroup extends SimpleMessageGroup { + @Nullable private final SimpleMessageGroup sourceGroup; public SequenceAwareMessageGroup(MessageGroup messageGroup) { @@ -1124,6 +1142,7 @@ private class ForceReleaseMessageGroupProcessor implements MessageGroupProcessor } @Override + @Nullable public Object processMessageGroup(MessageGroup group) { forceComplete(group); return null; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AggregatingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AggregatingMessageHandler.java index fdeeb7eb819..ad8b69ffee5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AggregatingMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AggregatingMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import java.util.Collection; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.IntegrationPatternType; import org.springframework.integration.store.MessageGroup; import org.springframework.integration.store.MessageGroupStore; @@ -95,7 +97,7 @@ protected boolean shouldSplitOutput(Iterable reply) { * @param completedMessages The completed messages. Ignored in this implementation. */ @Override - protected void afterRelease(MessageGroup messageGroup, Collection> completedMessages) { + protected void afterRelease(MessageGroup messageGroup, @Nullable Collection> completedMessages) { Object groupId = messageGroup.getGroupId(); MessageGroupStore messageStore = getMessageStore(); messageStore.completeGroup(groupId); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/BarrierMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/BarrierMessageHandler.java index 5d1d28e0ba5..1d479f75f83 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/BarrierMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/BarrierMessageHandler.java @@ -68,8 +68,10 @@ public class BarrierMessageHandler extends AbstractReplyProducingMessageHandler private final MessageGroupProcessor messageGroupProcessor; + @Nullable private String discardChannelName; + @Nullable private MessageChannel discardChannel; /** @@ -159,7 +161,7 @@ public BarrierMessageHandler(long requestTimeout, long triggerTimeout, Correlati * @since 5.4 */ public BarrierMessageHandler(long requestTimeout, long triggerTimeout, MessageGroupProcessor outputProcessor, - CorrelationStrategy correlationStrategy) { + @Nullable CorrelationStrategy correlationStrategy) { Assert.notNull(outputProcessor, "'messageGroupProcessor' cannot be null"); this.messageGroupProcessor = outputProcessor; @@ -218,6 +220,7 @@ public IntegrationPatternType getIntegrationPatternType() { } @Override + @Nullable protected Object handleRequestMessage(Message requestMessage) { Object key = this.correlationStrategy.getCorrelationKey(requestMessage); if (key == null) { @@ -247,6 +250,7 @@ protected Object handleRequestMessage(Message requestMessage) { return null; } + @Nullable private Object processRelease(Object key, Message requestMessage, Message releaseMessage) { this.suspensions.remove(key); if (releaseMessage.getPayload() instanceof Throwable) { @@ -266,6 +270,7 @@ private Object processRelease(Object key, Message requestMessage, Message * @param releaseMessage the release message. * @return the result. */ + @Nullable protected Object buildResult(Object key, Message requestMessage, Message releaseMessage) { SimpleMessageGroup group = new SimpleMessageGroup(key); group.add(requestMessage); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelatingMessageBarrier.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelatingMessageBarrier.java index 5c074928c3e..c3da415afcc 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelatingMessageBarrier.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelatingMessageBarrier.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.jspecify.annotations.Nullable; + import org.springframework.core.log.LogMessage; import org.springframework.integration.core.MessageSource; import org.springframework.integration.handler.AbstractMessageHandler; @@ -27,6 +29,7 @@ import org.springframework.integration.store.MessageGroupStore; import org.springframework.integration.store.SimpleMessageStore; import org.springframework.messaging.Message; +import org.springframework.util.Assert; /** * This Endpoint serves as a barrier for messages that should not be processed yet. The decision when a message can be @@ -58,8 +61,10 @@ public class CorrelatingMessageBarrier extends AbstractMessageHandler implements private final MessageGroupStore store; + @Nullable private CorrelationStrategy correlationStrategy; + @Nullable private ReleaseStrategy releaseStrategy; public CorrelatingMessageBarrier() { @@ -88,7 +93,9 @@ public void setReleaseStrategy(ReleaseStrategy releaseStrategy) { @Override protected void handleMessageInternal(Message message) { + Assert.notNull(this.correlationStrategy, "'correlationStrategy' must not be null"); Object correlationKey = this.correlationStrategy.getCorrelationKey(message); + Assert.notNull(correlationKey, "The correlation key is required"); Object lock = getLock(correlationKey); synchronized (lock) { this.store.addMessagesToGroup(correlationKey, message); @@ -103,12 +110,14 @@ private Object getLock(Object correlationKey) { @SuppressWarnings("unchecked") @Override + @Nullable public Message receive() { for (Object key : this.correlationLocks.keySet()) { Object lock = getLock(key); synchronized (lock) { MessageGroup group = this.store.getMessageGroup(key); //group might be removed by another thread + Assert.notNull(this.releaseStrategy, "'releaseStrategy' must not be null"); if (group != null && this.releaseStrategy.canRelease(group)) { Message nextMessage = null; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelationStrategy.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelationStrategy.java index f08e87abeca..5bd6e3fcbab 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelationStrategy.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/CorrelationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.integration.aggregator; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.Message; /** @@ -35,6 +37,7 @@ public interface CorrelationStrategy { * @param message The message. * @return The correlation key. */ + @Nullable Object getCorrelationKey(Message message); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java index d6ed43cf8ca..7df1a29d14d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/DelegatingMessageGroupProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,6 +61,7 @@ public class DelegatingMessageGroupProcessor implements MessageGroupProcessor, B private volatile boolean messageBuilderFactorySet; + @SuppressWarnings("NullAway.Init") private BeanFactory beanFactory; public DelegatingMessageGroupProcessor(MessageGroupProcessor delegate, diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java index e4f27b46538..1066ceb8c4c 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.BeanFactory; import org.springframework.core.convert.ConversionService; import org.springframework.integration.store.MessageGroup; @@ -58,6 +60,7 @@ public void setExpectedType(Class expectedType) { * {@link org.springframework.integration.core.MessagingTemplate} to send downstream. */ @Override + @Nullable protected Object aggregatePayloads(MessageGroup group, Map headers) { return this.processor.process(group.getMessages()); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java index 7ef5c73976f..525e927a0fe 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import java.util.Collection; +import org.jspecify.annotations.Nullable; + import org.springframework.expression.Expression; import org.springframework.expression.ParseException; import org.springframework.integration.util.AbstractExpressionEvaluator; @@ -37,6 +39,7 @@ public class ExpressionEvaluatingMessageListProcessor extends AbstractExpression private final Expression expression; + @Nullable private volatile Class expectedType = null; /** @@ -101,6 +104,7 @@ public void setExpectedType(Class expectedType) { * evaluation result Object will be returned. */ @Override + @Nullable public Object process(Collection> messages) { return this.evaluateExpression(this.expression, messages, this.expectedType); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java index 275e36ba07d..0d5efa24cc6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 the original author or authors. + * Copyright 2019-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,8 @@ import java.util.function.Function; import java.util.function.Predicate; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.FluxSink; @@ -62,18 +64,24 @@ public class FluxAggregatorMessageHandler extends AbstractMessageProducingHandle private CorrelationStrategy correlationStrategy = new HeaderAttributeCorrelationStrategy(IntegrationMessageHeaderAccessor.CORRELATION_ID); + @Nullable private Predicate> boundaryTrigger; - private Function, Integer> windowSizeFunction = FluxAggregatorMessageHandler::sequenceSizeHeader; + @Nullable + public Function, Integer> windowSizeFunction = FluxAggregatorMessageHandler::sequenceSizeHeader; + @Nullable private Function>, Flux>>> windowConfigurer; + @Nullable private Duration windowTimespan; private Function>, Mono>> combineFunction = this::messageForWindowFlux; + @SuppressWarnings("NullAway.Init") private FluxSink> sink; + @Nullable private volatile Disposable subscription; /** @@ -90,7 +98,9 @@ public FluxAggregatorMessageHandler() { } private Object groupBy(Message message) { - return this.correlationStrategy.getCorrelationKey(message); + Object result = this.correlationStrategy.getCorrelationKey(message); + Assert.notNull(result, "Correlation key cannot be null"); + return result; } private Flux> releaseBy(Flux> groupFlux) { @@ -99,6 +109,7 @@ private Flux> releaseBy(Flux> groupFlux) { .flatMap((windowFlux) -> windowFlux.transform(this.combineFunction)); } + @NullUnmarked private Flux>> applyWindowOptions(Flux> groupFlux) { if (this.boundaryTrigger != null) { return groupFlux.windowUntil(this.boundaryTrigger); @@ -106,6 +117,7 @@ private Flux>> applyWindowOptions(Flux> groupFlux) { return groupFlux .switchOnFirst((signal, group) -> { if (signal.hasValue()) { + Assert.notNull(this.windowSizeFunction, "'windowSizeFunction' must not be null"); Integer maxSize = this.windowSizeFunction.apply(signal.get()); if (maxSize != null) { if (this.windowTimespan != null) { @@ -277,6 +289,7 @@ private Mono> messageForWindowFlux(Flux> messageFlux) { .build()); } + @NullUnmarked private static Integer sequenceSizeHeader(Message message) { return message.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, Integer.class); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/HeaderAttributeCorrelationStrategy.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/HeaderAttributeCorrelationStrategy.java index 777c23bbac3..928a5a2ec6d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/HeaderAttributeCorrelationStrategy.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/HeaderAttributeCorrelationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.integration.aggregator; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.Message; import org.springframework.util.Assert; @@ -35,6 +37,7 @@ public HeaderAttributeCorrelationStrategy(String attributeName) { this.attributeName = attributeName; } + @Nullable public Object getCorrelationKey(Message message) { return message.getHeaders().get(this.attributeName); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageGroupProcessor.java index 83b28fce2ee..7ba26209fc9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageGroupProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.integration.aggregator; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.store.MessageGroup; /** @@ -37,6 +39,7 @@ public interface MessageGroupProcessor { * @param group The message group. * @return The result of processing the group. */ + @Nullable Object processMessageGroup(MessageGroup group); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java index a147da20cfa..801b770699e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import java.util.Collection; +import org.jspecify.annotations.Nullable; + import org.springframework.messaging.Message; /** @@ -27,6 +29,7 @@ @FunctionalInterface public interface MessageListProcessor { + @Nullable Object process(Collection> messages); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingCorrelationStrategy.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingCorrelationStrategy.java index c78e056a028..1a40b7b43a7 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingCorrelationStrategy.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingCorrelationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import java.lang.reflect.Method; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; @@ -57,6 +59,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { } @Override + @Nullable public Object getCorrelationKey(Message message) { return this.processor.processMessage(message); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java index 773601ca58a..931fd7c9e46 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ import java.util.Collection; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.beans.factory.BeanFactory; import org.springframework.core.convert.ConversionService; import org.springframework.integration.annotation.Aggregator; @@ -85,6 +87,7 @@ public void setBeanFactory(BeanFactory beanFactory) { } @Override + @Nullable protected final Object aggregatePayloads(MessageGroup group, Map headers) { final Collection> messagesUpForProcessing = group.getMessages(); return this.processor.process(messagesUpForProcessing, headers); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingReleaseStrategy.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingReleaseStrategy.java index b52864bd31d..952f72d90e3 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingReleaseStrategy.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingReleaseStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ public void setBeanFactory(BeanFactory beanFactory) { @Override public boolean canRelease(MessageGroup messages) { - return this.adapter.process(messages.getMessages(), null); + return Boolean.TRUE.equals(this.adapter.process(messages.getMessages(), null)); } @Override diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageGroupProcessor.java index 154351860f8..f6aaaa17304 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageGroupProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,8 @@ import java.util.Comparator; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.StaticMessageHeaderAccessor; import org.springframework.integration.store.MessageGroup; import org.springframework.messaging.Message; @@ -40,6 +42,7 @@ public class ResequencingMessageGroupProcessor implements MessageGroupProcessor private final Comparator> comparator = new MessageSequenceComparator(); + @Nullable public Object processMessageGroup(MessageGroup group) { Collection> messages = group.getMessages(); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageHandler.java index 6d986702863..587a597c970 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ResequencingMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import java.util.Collection; +import org.jspecify.annotations.Nullable; + import org.springframework.integration.IntegrationPatternType; import org.springframework.integration.store.MessageGroup; import org.springframework.integration.store.MessageGroupStore; @@ -78,7 +80,7 @@ protected boolean shouldCopyRequestHeaders() { } @Override - protected void afterRelease(MessageGroup messageGroup, Collection> completedMessages) { + protected void afterRelease(MessageGroup messageGroup, @Nullable Collection> completedMessages) { afterRelease(messageGroup, completedMessages, false); } @@ -90,7 +92,7 @@ protected void afterRelease(MessageGroup messageGroup, Collection> co * @param timeout True if the release/discard was due to a timeout. */ @Override - protected void afterRelease(MessageGroup messageGroup, Collection> completedMessages, boolean timeout) { + protected void afterRelease(MessageGroup messageGroup, @Nullable Collection> completedMessages, boolean timeout) { int size = messageGroup.size(); int sequenceSize = messageGroup.getSequenceSize(); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/package-info.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/package-info.java index 2ac1aa53803..7deb51b0ff1 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/package-info.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/package-info.java @@ -1,4 +1,5 @@ /** * Provides classes related to message aggregation. */ +@org.jspecify.annotations.NullMarked package org.springframework.integration.aggregator; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java b/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java index b9498f96984..c80f8240a04 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/ExpressionCapable.java @@ -16,7 +16,6 @@ package org.springframework.integration.context; - import org.jspecify.annotations.Nullable; import org.springframework.expression.Expression; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java index 0f1fbf3db60..151c4873af5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java @@ -141,8 +141,8 @@ public void setComponentName(String componentName) { /** * Subclasses may implement this method to provide component type information. */ - @Nullable @Override + @Nullable public String getComponentType() { return null; } @@ -152,8 +152,8 @@ public void setComponentSource(Object source) { this.beanSource = source; } - @Nullable @Override + @Nullable public Object getComponentSource() { return this.beanSource; } @@ -163,8 +163,8 @@ public void setComponentDescription(String description) { this.beanDescription = description; } - @Nullable @Override + @Nullable public String getComponentDescription() { return this.beanDescription; } @@ -223,8 +223,8 @@ public final void setPrimaryExpression(Expression expression) { this.expression = expression; } - @SuppressWarnings("NullAway.Init") @Override + @SuppressWarnings("NullAway.Init") public final void afterPropertiesSet() { this.integrationProperties = IntegrationContextUtils.getIntegrationProperties(this.beanFactory); if (this.messageBuilderFactory == null) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java b/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java index 2557e8bbd6e..1d2da3fb15a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/core/MessagingTemplate.java @@ -120,6 +120,7 @@ public Object receiveAndConvert(MessageChannel destination, long timeout) { return null; } } + @Nullable public Message receive(MessageChannel destination, long timeout) { return doReceive(destination, timeout); From de899a0812e9c84e15de52cd2e64c9b79d3ea8a2 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Wed, 11 Jun 2025 16:54:10 -0400 Subject: [PATCH 4/8] Apply code changes from code review --- .../AbstractAggregatingMessageGroupProcessor.java | 2 -- .../AbstractCorrelatingMessageHandler.java | 13 +++---------- .../ExpressionEvaluatingMessageGroupProcessor.java | 8 ++++---- .../ExpressionEvaluatingMessageListProcessor.java | 5 +++-- .../aggregator/FluxAggregatorMessageHandler.java | 10 +++++----- .../aggregator/MessageListProcessor.java | 1 - .../MethodInvokingMessageGroupProcessor.java | 8 ++++---- .../context/IntegrationContextUtils.java | 5 +++-- .../context/IntegrationObjectSupport.java | 2 +- 9 files changed, 23 insertions(+), 31 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java index 943e61544ba..645acfe3c42 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractAggregatingMessageGroupProcessor.java @@ -21,7 +21,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.jspecify.annotations.Nullable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -119,7 +118,6 @@ protected Map aggregateHeaders(MessageGroup group) { return getHeadersFunction().apply(group); } - @Nullable protected abstract Object aggregatePayloads(MessageGroup group, Map defaultHeaders); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java index 038be5657dc..1b361faf143 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java @@ -65,7 +65,6 @@ import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; @@ -652,10 +651,8 @@ protected boolean isExpireGroupsUponCompletion() { } private void removeEmptyGroupAfterTimeout(UUID groupId, long timeout) { - TaskScheduler taskScheduler = getTaskScheduler(); - Assert.notNull(taskScheduler, "'taskScheduler' must not be null"); ScheduledFuture scheduledFuture = - taskScheduler + getTaskScheduler() .schedule(() -> { Lock lock = this.lockRegistry.obtain(groupId.toString()); @@ -712,10 +709,8 @@ else if ((Long) groupTimeout > 0) { Object groupId = messageGroup.getGroupId(); long timestamp = messageGroup.getTimestamp(); long lastModified = messageGroup.getLastModified(); - TaskScheduler taskScheduler = getTaskScheduler(); - Assert.notNull(taskScheduler, "'taskScheduler' must not be null"); ScheduledFuture scheduledFuture = - taskScheduler + getTaskScheduler() .schedule(() -> { try { processForceRelease(groupId, timestamp, lastModified); @@ -1039,9 +1034,7 @@ public void start() { if (this.expireTimeout > 0) { purgeOrphanedGroups(); if (this.expireDuration != null) { - TaskScheduler taskScheduler = getTaskScheduler(); - Assert.notNull(taskScheduler, "'taskScheduler' must not be null"); - taskScheduler + getTaskScheduler() .scheduleWithFixedDelay(this::purgeOrphanedGroups, this.expireDuration); } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java index 1066ceb8c4c..83956d86c3a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java @@ -18,11 +18,10 @@ import java.util.Map; -import org.jspecify.annotations.Nullable; - import org.springframework.beans.factory.BeanFactory; import org.springframework.core.convert.ConversionService; import org.springframework.integration.store.MessageGroup; +import org.springframework.util.Assert; /** * A {@link MessageGroupProcessor} implementation that evaluates a SpEL expression. The SpEL context root is the list of @@ -60,9 +59,10 @@ public void setExpectedType(Class expectedType) { * {@link org.springframework.integration.core.MessagingTemplate} to send downstream. */ @Override - @Nullable protected Object aggregatePayloads(MessageGroup group, Map headers) { - return this.processor.process(group.getMessages()); + Object object = this.processor.process(group.getMessages()); + Assert.notNull(object, "Result from processor must not be null"); + return object; } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java index 525e927a0fe..85db32f537d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java @@ -104,9 +104,10 @@ public void setExpectedType(Class expectedType) { * evaluation result Object will be returned. */ @Override - @Nullable public Object process(Collection> messages) { - return this.evaluateExpression(this.expression, messages, this.expectedType); + Object object = this.evaluateExpression(this.expression, messages, this.expectedType); + Assert.state(object != null, "Failed to evaluate expression: " + this.expression); + return object; } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java index 0d5efa24cc6..2ef6b823189 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java @@ -17,6 +17,7 @@ package org.springframework.integration.aggregator; import java.time.Duration; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.function.Predicate; @@ -67,8 +68,7 @@ public class FluxAggregatorMessageHandler extends AbstractMessageProducingHandle @Nullable private Predicate> boundaryTrigger; - @Nullable - public Function, Integer> windowSizeFunction = FluxAggregatorMessageHandler::sequenceSizeHeader; + private Function, @Nullable Integer> windowSizeFunction = FluxAggregatorMessageHandler::sequenceSizeHeader; @Nullable private Function>, Flux>>> windowConfigurer; @@ -203,7 +203,7 @@ public void setWindowSize(int windowSize) { * @see Flux#window(int) * @see Flux#windowTimeout(int, Duration) */ - public void setWindowSizeFunction(Function, Integer> windowSizeFunction) { + public void setWindowSizeFunction(Function, @Nullable Integer> windowSizeFunction) { Assert.notNull(windowSizeFunction, "'windowSizeFunction' must not be null"); this.windowSizeFunction = windowSizeFunction; } @@ -289,9 +289,9 @@ private Mono> messageForWindowFlux(Flux> messageFlux) { .build()); } - @NullUnmarked + private static Integer sequenceSizeHeader(Message message) { - return message.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, Integer.class); + return Objects.requireNonNull(message.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, Integer.class)); } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java index 801b770699e..4aa6641a44e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java @@ -29,7 +29,6 @@ @FunctionalInterface public interface MessageListProcessor { - @Nullable Object process(Collection> messages); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java index 931fd7c9e46..4fd0ab27967 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java @@ -20,14 +20,13 @@ import java.util.Collection; import java.util.Map; -import org.jspecify.annotations.Nullable; - import org.springframework.beans.factory.BeanFactory; import org.springframework.core.convert.ConversionService; import org.springframework.integration.annotation.Aggregator; import org.springframework.integration.store.MessageGroup; import org.springframework.integration.support.management.ManageableLifecycle; import org.springframework.messaging.Message; +import org.springframework.util.Assert; /** * MessageGroupProcessor that serves as an adapter for the invocation of a POJO method. @@ -87,10 +86,11 @@ public void setBeanFactory(BeanFactory beanFactory) { } @Override - @Nullable protected final Object aggregatePayloads(MessageGroup group, Map headers) { final Collection> messagesUpForProcessing = group.getMessages(); - return this.processor.process(messagesUpForProcessing, headers); + Object object = this.processor.process(messagesUpForProcessing, headers); + Assert.notNull(object, "Result from processor must not be null"); + return object; } @Override diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java index c84f9203a58..f6c11183691 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java @@ -140,9 +140,10 @@ public static MessageChannel getErrorChannel(BeanFactory beanFactory) { * @param beanFactory BeanFactory for lookup, must not be null. * @return The {@link TaskScheduler} bean whose name is "taskScheduler" if available. */ - @Nullable public static TaskScheduler getTaskScheduler(BeanFactory beanFactory) { - return getBeanOfType(beanFactory, TASK_SCHEDULER_BEAN_NAME, TaskScheduler.class); + TaskScheduler taskScheduler = getBeanOfType(beanFactory, TASK_SCHEDULER_BEAN_NAME, TaskScheduler.class); + Assert.state(taskScheduler != null, "No such bean '" + TASK_SCHEDULER_BEAN_NAME + "'"); + return taskScheduler; } /** diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java index 151c4873af5..281af0ab08b 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java @@ -280,11 +280,11 @@ public void setTaskScheduler(TaskScheduler taskScheduler) { this.taskScheduler = taskScheduler; } - @Nullable protected TaskScheduler getTaskScheduler() { if (this.taskScheduler == null && this.beanFactory != null) { this.taskScheduler = IntegrationContextUtils.getTaskScheduler(this.beanFactory); } + Assert.notNull(this.taskScheduler, "'taskScheduler' must not be null"); return this.taskScheduler; } From 335bde697a1b15fd78148047af7bf35eaeb34278 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 11 Jun 2025 20:44:23 -0400 Subject: [PATCH 5/8] Fix nullability in the `FluxAggregatorMessageHandler` * This PR is not ready for merge. There are failing tests, but wanted to capture where it is at. * Also still having issue with the .apply() in FluxAggregatorMessageHandler * Make `windowSizeFunction` as `Function, @Nullable Integer>` because `sequenceSizeHeader()` may return `null` from message headers * Extract local `subscriptionToDispose` in the `stop()` to satisfy null check context * Use `Objects.requireNonNull(signal.get())` to satisfy `Function.apply()` contract. The `if (signal.hasValue()) {` does the trick for us, but currently that is not visible for that `signal.get()` * Remove `@NullUnmarked` since we have just mitigated all the null problems Updated tests so that they work with nullability changes Update the tests so that they will pass with nullify changes --- .../FluxAggregatorMessageHandler.java | 14 ++--- .../aggregator/MessageListProcessor.java | 2 - .../FluxAggregatorMessageHandlerTests.java | 18 +++++- .../registry/HeaderChannelRegistryTests.java | 14 ++++- .../reactivestreams/ReactiveStreamsTests.java | 16 ++++++ .../gateway/AsyncGatewayTests.java | 43 +++++++++----- .../gateway/GatewayInterfaceTests.java | 2 + .../gateway/GatewayProxyFactoryBeanTests.java | 48 ++++++++++------ .../GatewayProxyMessageMappingTests.java | 8 ++- .../handler/AsyncHandlerTests.java | 18 +++++- .../MethodInvokingMessageProcessorTests.java | 17 +++++- .../ip/dsl/ConnectionFactoryTests.java | 17 +++++- .../ip/dsl/IpIntegrationTests.java | 5 +- .../tcp/TcpReceivingChannelAdapterTests.java | 54 ++++++++++++------ .../ip/tcp/TcpSendingMessageHandlerTests.java | 17 +++++- .../CachingClientConnectionFactoryTests.java | 14 ++++- .../connection/ConnectionFactoryTests.java | 33 ++++++++--- .../FailoverClientConnectionFactoryTests.java | 56 +++++++++++++------ .../ip/tcp/connection/SocketSupportTests.java | 15 ++++- .../TcpNetConnectionSupportTests.java | 15 +++++ .../tcp/connection/TcpNetConnectionTests.java | 14 +++++ .../connection/TcpNioConnectionReadTests.java | 20 ++++++- .../tcp/connection/TcpNioConnectionTests.java | 20 ++++++- .../ip/tcp/connection/TcpSenderTests.java | 19 ++++++- .../tcp/serializer/DeserializationTests.java | 25 ++++++++- .../mail/ImapMailReceiverTests.java | 32 +++++++---- .../mail/ImapMailSearchTermsTests.java | 20 +++++-- .../SyslogReceivingChannelAdapterTests.java | 33 +++++++++-- 28 files changed, 483 insertions(+), 126 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java index 2ef6b823189..dac5e2ddb7b 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java @@ -17,7 +17,6 @@ package org.springframework.integration.aggregator; import java.time.Duration; -import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.function.Predicate; @@ -203,7 +202,7 @@ public void setWindowSize(int windowSize) { * @see Flux#window(int) * @see Flux#windowTimeout(int, Duration) */ - public void setWindowSizeFunction(Function, @Nullable Integer> windowSizeFunction) { + public void setWindowSizeFunction(Function, @Nullable Integer> windowSizeFunction) { Assert.notNull(windowSizeFunction, "'windowSizeFunction' must not be null"); this.windowSizeFunction = windowSizeFunction; } @@ -255,8 +254,9 @@ public void start() { @Override public void stop() { - if (this.subscribed.compareAndSet(true, false) && this.subscription != null) { - this.subscription.dispose(); + Disposable subscriptionToDispose = this.subscription; + if (this.subscribed.compareAndSet(true, false) && subscriptionToDispose != null) { + subscriptionToDispose.dispose(); } } @@ -289,9 +289,7 @@ private Mono> messageForWindowFlux(Flux> messageFlux) { .build()); } - - private static Integer sequenceSizeHeader(Message message) { - return Objects.requireNonNull(message.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, Integer.class)); + private static @Nullable Integer sequenceSizeHeader(Message message) { + return message.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, Integer.class); } - } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java index 4aa6641a44e..49271e48f27 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MessageListProcessor.java @@ -18,8 +18,6 @@ import java.util.Collection; -import org.jspecify.annotations.Nullable; - import org.springframework.messaging.Message; /** diff --git a/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java index 6ddbb415807..02083f69ddc 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 the original author or authors. + * Copyright 2019-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,13 +29,19 @@ import reactor.core.publisher.Flux; import reactor.test.StepVerifier; +import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Artem Bilan @@ -159,6 +165,7 @@ void testCustomCombineFunction() { void testWindowTimespan() { QueueChannel resultChannel = new QueueChannel(); FluxAggregatorMessageHandler fluxAggregatorMessageHandler = new FluxAggregatorMessageHandler(); + fluxAggregatorMessageHandler.setBeanFactory(getBeanFactory()); fluxAggregatorMessageHandler.setOutputChannel(resultChannel); fluxAggregatorMessageHandler.setWindowTimespan(Duration.ofMillis(100)); fluxAggregatorMessageHandler.start(); @@ -213,6 +220,15 @@ void testWindowTimespan() { executorService.shutdown(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @Test void testBoundaryTrigger() { QueueChannel resultChannel = new QueueChannel(); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java b/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java index 502bbd79dde..1c2b5386a69 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 the original author or authors. + * Copyright 2013-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -238,6 +240,7 @@ public void testBFCRNoRegistry() { @Test public void testRemoveOnGet() { DefaultHeaderChannelRegistry registry = new DefaultHeaderChannelRegistry(); + registry.setBeanFactory(getBeanFactory()); MessageChannel channel = new DirectChannel(); String foo = (String) registry.channelToChannelName(channel); Map map = TestUtils.getPropertyValue(registry, "channels", Map.class); @@ -249,6 +252,15 @@ public void testRemoveOnGet() { assertThat(map.size()).isEqualTo(0); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + public static class Foo extends AbstractReplyProducingMessageHandler { @Override diff --git a/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java b/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java index 54a2cdf9477..f25354f5421 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java @@ -36,6 +36,7 @@ import reactor.core.scheduler.Schedulers; import reactor.test.StepVerifier; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ConfigurableApplicationContext; @@ -57,10 +58,15 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Artem Bilan @@ -130,6 +136,7 @@ void testReactiveFlow() throws Exception { @Test void testPollableReactiveFlow() throws Exception { assertThat(this.reactiveTransformer).isInstanceOf(ReactiveStreamsConsumer.class); + this.reactiveTransformer.setBeanFactory(getBeanFactory()); this.inputChannel.send(new GenericMessage<>("1,2,3,4,5")); CountDownLatch latch = new CountDownLatch(6); @@ -165,6 +172,15 @@ void testPollableReactiveFlow() throws Exception { exec.shutdownNow(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @Test void testFromPublisher() { Flux> messageFlux = diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java index ba168382492..6fa45ba6de5 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,11 +42,15 @@ import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.messaging.support.GenericMessage; import org.springframework.messaging.support.MessageBuilder; +import org.springframework.scheduling.TaskScheduler; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Mark Fisher @@ -65,7 +69,7 @@ public void futureWithMessageReturned() throws Exception { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future> f = service.returnMessage("foo"); @@ -88,7 +92,7 @@ protected boolean doSend(Message message, long timeout) { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(channel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future> f = service.returnMessage("foo"); @@ -106,7 +110,7 @@ public void listenableFutureWithMessageReturned() throws Exception { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); CompletableFuture> f = service.returnMessageListenable("foo"); @@ -132,7 +136,7 @@ public void customFutureReturned() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); CustomFuture f = service.returnCustomFuture("foo"); @@ -149,7 +153,7 @@ public void nonAsyncFutureReturned() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.setAsyncExecutor(null); // Not async - user flow returns Future @@ -181,7 +185,7 @@ public void futureWithPayloadReturned() throws Exception { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future f = service.returnString("foo"); @@ -197,7 +201,7 @@ public void futureWithWildcardReturned() throws Exception { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future f = service.returnSomething("foo"); @@ -211,7 +215,7 @@ public void futureVoid() throws Exception { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(new NullChannel()); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future f = service.asyncSendAndForget("test1"); @@ -251,7 +255,7 @@ public void futureVoidReply() throws Exception { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.setAsyncExecutor(null); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); @@ -267,7 +271,7 @@ public void monoWithMessageReturned() { startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.setBeanName("testGateway"); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); @@ -282,7 +286,7 @@ public void monoWithPayloadReturned() { startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.setBeanName("testGateway"); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); @@ -297,7 +301,7 @@ public void monoWithWildcardReturned() { startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.setBeanName("testGateway"); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); @@ -313,7 +317,7 @@ public void monoWithConsumer() { startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.setBeanName("testGateway"); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); @@ -329,7 +333,7 @@ public void monoVoid() throws InterruptedException { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); proxyFactory.setDefaultRequestChannel(new NullChannel()); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Mono mono = service.monoVoid("test1"); @@ -372,6 +376,15 @@ private static void startResponder(final PollableChannel requestChannel) { }).start(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + private interface TestEchoService { Future returnString(String s); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java index a4f360bbc16..5249e62f478 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTests.java @@ -89,6 +89,7 @@ import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.messaging.support.MessageHeaderAccessor; +import org.springframework.scheduling.TaskScheduler; import org.springframework.stereotype.Component; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; @@ -340,6 +341,7 @@ public void testWithServiceEquals() { bf.registerSingleton("requestChannelBar", channel); bf.registerSingleton("requestChannelBaz", channel); bf.registerSingleton("requestChannelFoo", channel); + bf.registerSingleton("taskScheduler", mock(TaskScheduler.class)); fb.setBeanFactory(bf); fb.afterPropertiesSet(); assertThat(fb.getObject()).isNotSameAs(bar); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java index 70f6253252c..d55192f51eb 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,15 +59,19 @@ import org.springframework.messaging.PollableChannel; import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; /** * @author Mark Fisher @@ -85,7 +89,7 @@ public void testRequestReplyWithAnonymousChannel() { startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.setBeanName("testGateway"); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); @@ -113,7 +117,7 @@ public byte[] convert(String source) { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.registerSingleton(IntegrationUtils.INTEGRATION_CONVERSION_SERVICE_BEAN_NAME, cs); - + bf.registerSingleton("taskScheduler", mock(TaskScheduler.class)); proxyFactory.setBeanFactory(bf); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); @@ -121,7 +125,7 @@ public byte[] convert(String source) { TestService service = proxyFactory.getObject(); byte[] result = service.requestReplyInBytes("foo"); assertThat(result.length).isEqualTo(6); - Mockito.verify(stringToByteConverter, Mockito.times(1)).convert(Mockito.any(String.class)); + Mockito.verify(stringToByteConverter, Mockito.times(1)).convert(any(String.class)); } @Test @@ -130,7 +134,7 @@ public void testOneWay() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); service.oneWay("test"); @@ -142,7 +146,7 @@ public void testOneWay() { @Test public void testOneWayIgnoreReply() { DirectChannel requestChannel = new DirectChannel(); - BeanFactory beanFactory = mock(BeanFactory.class); + BeanFactory beanFactory = getBeanFactory(); QueueChannel nullChannel = new QueueChannel(); willReturn(nullChannel) .given(beanFactory) @@ -173,7 +177,7 @@ public void testSolicitResponse() { proxyFactory.setDefaultRequestChannel(new DirectChannel()); proxyFactory.setDefaultReplyChannel(replyChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); String result = service.solicitResponse(); @@ -188,7 +192,7 @@ public void testReceiveMessage() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultReplyChannel(replyChannel); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); Message message = service.getMessage(); @@ -210,7 +214,7 @@ public void testReactiveReplyChannel() { proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setDefaultReplyChannel(replyChannel); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); @@ -229,7 +233,7 @@ public void testRequestReplyWithTypeConversion() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); Integer result = service.requestReplyWithIntegers(123); @@ -300,7 +304,7 @@ public void testMessageAsMethodArgument() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); String result = service.requestReplyWithMessageParameter(new GenericMessage<>("foo")); @@ -314,7 +318,7 @@ public void testNoArgMethodWithPayloadAnnotation() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); String result = service.requestReplyWithPayloadAnnotation(); @@ -338,7 +342,7 @@ public void testMessageAsReturnValue() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultRequestChannel(requestChannel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestService service = proxyFactory.getObject(); Message result = service.requestReplyWithMessageReturnValue("foo"); @@ -356,7 +360,7 @@ public void testProxiedToStringMethod() { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestService.class); proxyFactory.setDefaultRequestChannel(new DirectChannel()); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); Object proxy = proxyFactory.getObject(); String expected = "gateway proxy for"; @@ -380,7 +384,7 @@ public void handleMessage(Message message) { consumer.start(); proxyFactory.setDefaultRequestChannel(channel); proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(mock(BeanFactory.class)); + proxyFactory.setBeanFactory(getBeanFactory()); proxyFactory.afterPropertiesSet(); TestExceptionThrowingInterface proxy = proxyFactory.getObject(); assertThatExceptionOfType(TestException.class) @@ -398,7 +402,7 @@ private static void startResponder(final PollableChannel requestChannel) { @Test public void testProgrammaticWiring() { GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>(TestEchoService.class); - gpfb.setBeanFactory(mock(BeanFactory.class)); + gpfb.setBeanFactory(getBeanFactory()); QueueChannel drc = new QueueChannel(); gpfb.setDefaultRequestChannel(drc); gpfb.setDefaultReplyTimeout(0L); @@ -414,6 +418,15 @@ public void testProgrammaticWiring() { assertThat(bar).isEqualTo("bar"); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @Test public void testIdHeaderOverrideHeaderExpression() { GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>(); @@ -495,7 +508,7 @@ public void autowiredGateway() { @Test public void testOverriddenMethod() { GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>(InheritChild.class); - gpfb.setBeanFactory(mock(BeanFactory.class)); + gpfb.setBeanFactory(getBeanFactory()); gpfb.afterPropertiesSet(); Map gateways = gpfb.getGateways(); assertThat(gateways.size()).isEqualTo(2); @@ -508,6 +521,7 @@ public void testAliasForSupport() throws NoSuchMethodException { beanFactory.registerSingleton("requestChannel", requestChannel); GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>( CompositedGatewayService.class); + beanFactory.registerSingleton("taskScheduler", mock(TaskScheduler.class)); gpfb.setBeanFactory(beanFactory); gpfb.afterPropertiesSet(); Map gateways = gpfb.getGateways(); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java index 47cfb7debcd..11a48f2ec25 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyMessageMappingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,9 +32,11 @@ import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.Headers; import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.mock; /** * @author Mark Fisher @@ -58,6 +60,8 @@ public void initializeGateway() { context.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, new RootBeanDefinition(IntegrationEvaluationContextFactoryBean.class)); context.refresh(); + context.getBeanFactory().registerSingleton("taskScheduler", mock(TaskScheduler.class)); + factoryBean.setBeanFactory(context); factoryBean.afterPropertiesSet(); this.gateway = factoryBean.getObject(); @@ -144,6 +148,7 @@ public void payloadAnnotationAtMethodLevelUsingBeanResolver() { context.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class)); context.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, new RootBeanDefinition(IntegrationEvaluationContextFactoryBean.class)); + context.getBeanFactory().registerSingleton("taskScheduler", mock(TaskScheduler.class)); context.refresh(); TestGateway gateway = context.getBean("testGateway", TestGateway.class); gateway.payloadAnnotationAtMethodLevelUsingBeanResolver("foo"); @@ -171,6 +176,7 @@ public void payloadAnnotationWithExpressionUsingBeanResolver() { context.registerBeanDefinition("testBean", new RootBeanDefinition(TestBean.class)); context.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, new RootBeanDefinition(IntegrationEvaluationContextFactoryBean.class)); + context.getBeanFactory().registerSingleton("taskScheduler", mock(TaskScheduler.class)); context.refresh(); TestGateway gateway = context.getBean("testGateway", TestGateway.class); gateway.payloadAnnotationWithExpressionUsingBeanResolver("foo"); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java index c2393ec4c2b..9d592125124 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 the original author or authors. + * Copyright 2016-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,12 +41,15 @@ import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.support.GenericMessage; import org.springframework.messaging.support.MessageBuilder; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -218,7 +221,7 @@ public void testMessagingExceptionNoErrorChannel() throws Exception { public void testGateway() { this.whichTest = 0; GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>(Foo.class); - gpfb.setBeanFactory(mock(BeanFactory.class)); + gpfb.setBeanFactory(getBeanFactory()); DirectChannel input = new DirectChannel(); gpfb.setDefaultRequestChannel(input); gpfb.setDefaultReplyTimeout(10000L); @@ -233,11 +236,20 @@ public void testGateway() { assertThat(result).isEqualTo("reply"); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @Test public void testGatewayWithException() { this.whichTest = 0; GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>(Foo.class); - gpfb.setBeanFactory(mock(BeanFactory.class)); + gpfb.setBeanFactory(getBeanFactory()); DirectChannel input = new DirectChannel(); gpfb.setDefaultRequestChannel(input); gpfb.setDefaultReplyTimeout(10000L); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java index ef365013d17..5dd2a5b5a2e 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,6 +79,7 @@ import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.util.StopWatch; import static org.assertj.core.api.Assertions.assertThat; @@ -87,9 +88,12 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.fail; import static org.mockito.AdditionalAnswers.returnsFirstArg; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Mark Fisher @@ -605,7 +609,7 @@ public void testOverloadedNonVoidReturningMethodsWithExactMatchForType() { @Test public void gatewayTest() throws Exception { GatewayProxyFactoryBean gwFactoryBean = new GatewayProxyFactoryBean<>(); - gwFactoryBean.setBeanFactory(mock(BeanFactory.class)); + gwFactoryBean.setBeanFactory(getBeanFactory()); gwFactoryBean.afterPropertiesSet(); Object target = gwFactoryBean.getObject(); // just instantiate a helper with a simple target; we're going to invoke getTargetClass with reflection @@ -617,6 +621,15 @@ public void gatewayTest() throws Exception { assertThat(result).isSameAs(RequestReplyExchanger.class); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @Test public void testInt3199GenericTypeResolvingAndObjectMethod() { diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java index bd03f34dd7f..de71a257307 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 the original author or authors. + * Copyright 2016-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory; import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory; @@ -38,9 +39,13 @@ import org.springframework.integration.transformer.ObjectToStringTransformer; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -57,6 +62,7 @@ public void test() throws Exception { ApplicationEventPublisher publisher = e -> { }; AbstractServerConnectionFactory server = Tcp.netServer(0).backlog(2).soTimeout(5000).getObject(); + server.setBeanFactory(getBeanFactory()); final AtomicReference> received = new AtomicReference<>(); final CountDownLatch latch = new CountDownLatch(1); server.registerListener(m -> { @@ -79,6 +85,15 @@ public void test() throws Exception { server.stop(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @Test public void shouldReturnNioFlavor() { AbstractServerConnectionFactory server = Tcp.nioServer(0).getObject(); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java index a243d6b4684..a5b0aff0f2a 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 the original author or authors. + * Copyright 2016-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,11 +68,13 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; /** * @author Gary Russell @@ -134,6 +136,7 @@ void testTcpAdapters() { AbstractServerConnectionFactory server = Tcp.netServer(0).backlog(2).soTimeout(5000).id("server").getObject(); assertThat(server.getComponentName()).isEqualTo("server"); server.setApplicationEventPublisher(publisher); + server.setTaskScheduler(mock(TaskScheduler.class)); server.afterPropertiesSet(); TcpReceivingChannelAdapter inbound = Tcp.inboundAdapter(server).getObject(); QueueChannel received = new QueueChannel(); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java index 785237a5bc3..110328862e6 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,10 +55,14 @@ import org.springframework.integration.ip.util.TestingUtilities; import org.springframework.messaging.Message; import org.springframework.messaging.SubscribableChannel; +import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -68,7 +72,7 @@ public class TcpReceivingChannelAdapterTests extends AbstractTcpChannelAdapterTe @Test public void testNet() throws Exception { - AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -155,7 +159,7 @@ public void testNetClientMode() throws Exception { @Test public void testNio() throws Exception { - TcpNioServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -186,7 +190,7 @@ public void testNio() throws Exception { @Test public void testNetShared() throws Exception { - AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -220,7 +224,7 @@ public void testNetShared() throws Exception { @Test public void testNioShared() throws Exception { - TcpNioServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -254,7 +258,7 @@ public void testNioShared() throws Exception { @Test public void testNetSingleNoOutbound() throws Exception { - AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -286,7 +290,7 @@ public void testNetSingleNoOutbound() throws Exception { @Test public void testNioSingleNoOutbound() throws Exception { - TcpNioServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -328,7 +332,7 @@ private void readFully(InputStream is, byte[] buff) throws IOException { @Test public void testNetSingleShared() throws Exception { - AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -365,7 +369,7 @@ public void testNetSingleShared() throws Exception { @Test public void testNioSingleShared() throws Exception { - TcpNioServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -402,7 +406,7 @@ public void testNioSingleShared() throws Exception { @Test public void testNioSingleSharedMany() throws Exception { - TcpNioServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); @@ -442,15 +446,30 @@ public void testNioSingleSharedMany() throws Exception { @Test public void testNetInterceptors() throws Exception { - AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); interceptorsGuts(scf); scf.stop(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + + private AbstractServerConnectionFactory getDefaultServerConnectionFactory() { + AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + scf.setBeanFactory(getBeanFactory()); + return scf; + } + @Test public void testNetSingleNoOutboundInterceptors() throws Exception { - AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); singleNoOutboundInterceptorsGuts(scf); scf.stop(); @@ -458,7 +477,7 @@ public void testNetSingleNoOutboundInterceptors() throws Exception { @Test public void testNetSingleSharedInterceptors() throws Exception { - AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); singleSharedInterceptorsGuts(scf); scf.stop(); @@ -466,7 +485,7 @@ public void testNetSingleSharedInterceptors() throws Exception { @Test public void testNioInterceptors() throws Exception { - AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); interceptorsGuts(scf); scf.stop(); @@ -474,7 +493,7 @@ public void testNioInterceptors() throws Exception { @Test public void testNioSingleNoOutboundInterceptors() throws Exception { - AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); singleNoOutboundInterceptorsGuts(scf); scf.stop(); @@ -482,7 +501,7 @@ public void testNioSingleNoOutboundInterceptors() throws Exception { @Test public void testNioSingleSharedInterceptors() throws Exception { - AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); noopPublisher(scf); singleSharedInterceptorsGuts(scf); scf.stop(); @@ -623,8 +642,11 @@ public void testException() throws Exception { ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); scf.setDeserializer(serializer); + scf.setTaskScheduler(mock(TaskScheduler.class)); + TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter(); adapter.setConnectionFactory(scf); + adapter.setTaskScheduler(mock(TaskScheduler.class)); scf.start(); TestingUtilities.waitListening(scf, null); int port = scf.getPort(); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java index 8c6bb858c60..c7f48107e1f 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,12 +73,16 @@ import org.springframework.messaging.MessagingException; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -1203,6 +1207,7 @@ public void testConnectionException() throws Exception { public void testInterceptedConnection() throws Exception { final CountDownLatch latch = new CountDownLatch(1); AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + scf.setBeanFactory(getBeanFactory()); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); scf.setDeserializer(serializer); @@ -1236,6 +1241,7 @@ public void testInterceptedConnection() throws Exception { public void testInterceptedCleanup() throws Exception { final CountDownLatch latch = new CountDownLatch(1); AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); + scf.setBeanFactory(getBeanFactory()); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); scf.setDeserializer(serializer); @@ -1261,4 +1267,13 @@ public void testInterceptedCleanup() throws Exception { scf.stop(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java index 190fcf92d32..f82b36f922f 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,6 +68,7 @@ import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @@ -77,6 +78,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -698,6 +700,7 @@ public void testRealConnection() throws Exception { @Test //INT-3722 public void testGatewayRelease() { TcpNetServerConnectionFactory in = new TcpNetServerConnectionFactory(0); + in.setBeanFactory(getBeanFactory()); in.setApplicationEventPublisher(mock(ApplicationEventPublisher.class)); final TcpSendingMessageHandler handler = new TcpSendingMessageHandler(); handler.setConnectionFactory(in); @@ -821,4 +824,13 @@ private static AbstractClientConnectionFactory createFactoryWithMockConnection(T return factory; } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java index c298fcf994d..f343282602d 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,6 +66,7 @@ import static org.awaitility.Awaitility.await; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -84,7 +85,7 @@ public class ConnectionFactoryTests { @Test void netOpenEventOnReadThread() throws InterruptedException, IOException { - TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); + TcpNetServerConnectionFactory server = getTcpNetServerConnectionFactory(0); AtomicReference readThread = new AtomicReference<>(); AtomicReference openEventThread = new AtomicReference<>(); CountDownLatch latch1 = new CountDownLatch(1); @@ -162,7 +163,7 @@ public void testObtainConnectionIds(AbstractServerConnectionFactory serverFactor ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); scheduler.afterPropertiesSet(); - BeanFactory bf = mock(BeanFactory.class); + BeanFactory bf = getBeanFactory(); when(bf.containsBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)).thenReturn(true); when(bf.getBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, TaskScheduler.class)).thenReturn(scheduler); serverFactory.setBeanFactory(bf); @@ -273,22 +274,22 @@ private void testEarlyClose(final AbstractServerConnectionFactory factory, Strin @Test void healthCheckSuccessNet() throws InterruptedException { - healthCheckSuccess(new TcpNetServerConnectionFactory(0), false); + healthCheckSuccess(getTcpNetServerConnectionFactory(0), false); } @Test void healthCheckSuccessNio() throws InterruptedException { - healthCheckSuccess(new TcpNioServerConnectionFactory(0), false); + healthCheckSuccess(getTcpNetServerConnectionFactory(0), false); } @Test void healthCheckFailureNet() throws InterruptedException { - healthCheckSuccess(new TcpNetServerConnectionFactory(0), true); + healthCheckSuccess(getTcpNetServerConnectionFactory(0), true); } @Test void healthCheckFailureNio() throws InterruptedException { - healthCheckSuccess(new TcpNioServerConnectionFactory(0), true); + healthCheckSuccess(getTcpNetServerConnectionFactory(0), true); } private void healthCheckSuccess(AbstractServerConnectionFactory server, boolean fail) throws InterruptedException { @@ -298,7 +299,7 @@ private void healthCheckSuccess(AbstractServerConnectionFactory server, boolean serverUp.countDown(); } }); - server.setBeanFactory(mock(BeanFactory.class)); + server.setBeanFactory(getBeanFactory()); AtomicReference connection = new AtomicReference<>(); server.registerSender(conn -> { connection.set(conn); @@ -367,6 +368,21 @@ private void healthCheckSuccess(AbstractServerConnectionFactory server, boolean server.stop(); } + private TcpNetServerConnectionFactory getTcpNetServerConnectionFactory(int port) { + TcpNetServerConnectionFactory result = new TcpNetServerConnectionFactory(port); + result.setBeanFactory(getBeanFactory()); + return result; + } + + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @SuppressWarnings("serial") private class FooEvent extends TcpConnectionOpenEvent { @@ -375,5 +391,4 @@ private class FooEvent extends TcpConnectionOpenEvent { } } - } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java index 2733937d29d..4a40125ac08 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java @@ -54,11 +54,13 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; @@ -328,39 +330,39 @@ public TcpConnectionSupport makeMockConnection() { @Test public void testRealNet() throws Exception { - AbstractServerConnectionFactory server1 = new TcpNetServerConnectionFactory(0); - AbstractServerConnectionFactory server2 = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory server1 = getTcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory server2 = getTcpNetServerConnectionFactory(0); Holder holder = setupAndStartServers(server1, server2); - AbstractClientConnectionFactory client1 = new TcpNetClientConnectionFactory("localhost", server1.getPort()); - AbstractClientConnectionFactory client2 = new TcpNetClientConnectionFactory("localhost", server2.getPort()); + AbstractClientConnectionFactory client1 = getTcpNetServerConnectionFactory("localhost", server1.getPort()); + AbstractClientConnectionFactory client2 = getTcpNetServerConnectionFactory("localhost", server2.getPort()); testRealGuts(client1, client2, holder); } @Test public void testRealNio() throws Exception { - AbstractServerConnectionFactory server1 = new TcpNioServerConnectionFactory(0); - AbstractServerConnectionFactory server2 = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory server1 = getTcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory server2 = getTcpNetServerConnectionFactory(0); Holder holder = setupAndStartServers(server1, server2); - AbstractClientConnectionFactory client1 = new TcpNioClientConnectionFactory("localhost", server1.getPort()); - AbstractClientConnectionFactory client2 = new TcpNioClientConnectionFactory("localhost", server2.getPort()); + AbstractClientConnectionFactory client1 = getTcpNetServerConnectionFactory("localhost", server1.getPort()); + AbstractClientConnectionFactory client2 = getTcpNetServerConnectionFactory("localhost", server2.getPort()); testRealGuts(client1, client2, holder); } @Test public void testRealNetSingleUse() throws Exception { - AbstractServerConnectionFactory server1 = new TcpNetServerConnectionFactory(0); - AbstractServerConnectionFactory server2 = new TcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory server1 = getTcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory server2 = getTcpNetServerConnectionFactory(0); Holder holder = setupAndStartServers(server1, server2); - AbstractClientConnectionFactory client1 = new TcpNetClientConnectionFactory("localhost", server1.getPort()); - AbstractClientConnectionFactory client2 = new TcpNetClientConnectionFactory("localhost", server2.getPort()); + AbstractClientConnectionFactory client1 = getTcpNetServerConnectionFactory("localhost", server1.getPort()); + AbstractClientConnectionFactory client2 = getTcpNetServerConnectionFactory("localhost", server2.getPort()); client1.setSingleUse(true); client2.setSingleUse(true); testRealGuts(client1, client2, holder); @@ -369,13 +371,13 @@ public void testRealNetSingleUse() throws Exception { @Test public void testRealNioSingleUse() throws Exception { - AbstractServerConnectionFactory server1 = new TcpNioServerConnectionFactory(0); - AbstractServerConnectionFactory server2 = new TcpNioServerConnectionFactory(0); + AbstractServerConnectionFactory server1 = getTcpNetServerConnectionFactory(0); + AbstractServerConnectionFactory server2 = getTcpNetServerConnectionFactory(0); Holder holder = setupAndStartServers(server1, server2); - AbstractClientConnectionFactory client1 = new TcpNioClientConnectionFactory("localhost", server1.getPort()); - AbstractClientConnectionFactory client2 = new TcpNioClientConnectionFactory("localhost", server2.getPort()); + AbstractClientConnectionFactory client1 = getTcpNetServerConnectionFactory("localhost", server1.getPort()); + AbstractClientConnectionFactory client2 = getTcpNetServerConnectionFactory("localhost", server2.getPort()); client1.setSingleUse(true); client2.setSingleUse(true); testRealGuts(client1, client2, holder); @@ -698,5 +700,27 @@ private static AbstractClientConnectionFactory createFactoryWithMockConnection(T return factory; } + private TcpNetServerConnectionFactory getTcpNetServerConnectionFactory(int port) { + TcpNetServerConnectionFactory result = new TcpNetServerConnectionFactory(port); + result.setBeanFactory(getBeanFactory()); + + return result; + } + + private TcpNetClientConnectionFactory getTcpNetServerConnectionFactory(String host, int port) { + TcpNetClientConnectionFactory result = new TcpNetClientConnectionFactory(host, port); + result.setBeanFactory(getBeanFactory()); + + return result; + } + + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java index 8a7c8da7748..b571f462139 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer; import org.springframework.integration.ip.util.TestingUtilities; import org.springframework.integration.test.util.TestUtils; @@ -48,6 +49,7 @@ import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -470,6 +472,7 @@ public void postProcessServerSocket(ServerSocket serverSocket) { public void testNioClientAndServerSSL() throws Exception { System.setProperty("javax.net.debug", "all"); // SSL activity in the console TcpNioServerConnectionFactory server = new TcpNioServerConnectionFactory(0); + server.setBeanFactory(getBeanFactory()); server.setSslHandshakeTimeout(43); DefaultTcpSSLContextSupport sslContextSupport = new DefaultTcpSSLContextSupport("test.ks", "test.truststore.ks", "secret", "secret"); @@ -576,6 +579,7 @@ protected void postProcessSSLEngine(SSLEngine sslEngine) { public void testNioClientAndServerSSLDifferentContextsLargeDataWithReply() throws Exception { System.setProperty("javax.net.debug", "all"); // SSL activity in the console TcpNioServerConnectionFactory server = new TcpNioServerConnectionFactory(0); + server.setBeanFactory(getBeanFactory()); TcpSSLContextSupport serverSslContextSupport = new DefaultTcpSSLContextSupport("server.ks", "server.truststore.ks", "secret", "secret"); DefaultTcpNioSSLConnectionSupport serverTcpNioConnectionSupport = @@ -645,6 +649,15 @@ public void testNioClientAndServerSSLDifferentContextsLargeDataWithReply() throw server.stop(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + private static class Replier implements TcpSender { private TcpConnection connection; diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java index b5b39b4445b..17152c2df9c 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java @@ -26,10 +26,16 @@ import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.messaging.Message; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -41,6 +47,7 @@ public class TcpNetConnectionSupportTests { @Test public void testBadCode() throws Exception { TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); + server.setBeanFactory(getBeanFactory()); AtomicReference> message = new AtomicReference<>(); CountDownLatch latch1 = new CountDownLatch(1); server.registerListener(m -> { @@ -81,4 +88,12 @@ public TcpNetConnection createNewConnection(Socket socket, boolean isServer, boo server.stop(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java index 0ca13eed336..61ff6f8784e 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java @@ -36,6 +36,7 @@ import org.mockito.Mockito; import org.springframework.beans.DirectFieldAccessor; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.integration.ip.tcp.connection.TcpNioConnection.ChannelInputStream; import org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer; @@ -46,9 +47,12 @@ import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; import org.springframework.messaging.support.ErrorMessage; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -153,6 +157,7 @@ public void transferHeaders() throws Exception { @Test public void socketClosedNextRead() throws InterruptedException, IOException { TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); + server.setBeanFactory(getBeanFactory()); AtomicInteger port = new AtomicInteger(); CountDownLatch latch = new CountDownLatch(1); ApplicationEventPublisher publisher = ev -> { @@ -174,4 +179,13 @@ public void socketClosedNextRead() throws InterruptedException, IOException { server.stop(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java index 2489780414c..e22f26f0e4a 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.ip.tcp.serializer.AbstractByteArraySerializer; import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer; import org.springframework.integration.ip.tcp.serializer.ByteArrayLengthHeaderSerializer; @@ -38,9 +39,14 @@ import org.springframework.integration.ip.util.TestingUtilities; import org.springframework.messaging.Message; import org.springframework.messaging.support.ErrorMessage; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.with; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -62,6 +68,7 @@ private AbstractServerConnectionFactory getConnectionFactory( AbstractByteArraySerializer serializer, TcpListener listener, TcpSender sender) { TcpNioServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + scf.setBeanFactory(getBeanFactory()); scf.setUsingDirectBuffers(true); scf.setApplicationEventPublisher(e -> { }); @@ -119,7 +126,6 @@ public void testFragmented() throws Exception { semaphore.release(); return false; }); - int howMany = 2; scf.setBacklog(howMany + 5); // Fire up the sender. @@ -144,7 +150,6 @@ public void testReadStxEtx() throws Exception { semaphore.release(); return false; }); - // Fire up the sender. CountDownLatch done = SocketTestUtils.testSendStxEtx(scf.getPort(), latch); @@ -534,4 +539,13 @@ private void whileOpen(Semaphore semaphore, List added) .until(() -> !added.get(0).isOpen()); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java index 3f7f3b002f0..cf6d660aaa5 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,6 +59,7 @@ import org.mockito.stubbing.Answer; import org.springframework.beans.DirectFieldAccessor; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; @@ -76,6 +77,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.ErrorMessage; +import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.ReflectionUtils; import org.springframework.util.StopWatch; @@ -88,6 +90,7 @@ import static org.awaitility.Awaitility.with; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willReturn; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -545,7 +548,7 @@ public Integer answer(InvocationOnMock invocation) { public void testAssemblerUsesSecondaryExecutor() throws Exception { TcpNioServerConnectionFactory factory = new TcpNioServerConnectionFactory(0); factory.setApplicationEventPublisher(nullPublisher); - + factory.setBeanFactory(getBeanFactory()); CompositeExecutor compositeExec = compositeExecutor(); factory.setSoTimeout(1000); @@ -595,6 +598,7 @@ private void cleanupCompositeExecutor(CompositeExecutor compositeExec) throws Ex public void testAllMessagesDelivered() throws Exception { final int numberOfSockets = 10; TcpNioServerConnectionFactory factory = new TcpNioServerConnectionFactory(0); + factory.setBeanFactory(getBeanFactory()); factory.setApplicationEventPublisher(nullPublisher); CompositeExecutor compositeExec = compositeExecutor(); @@ -661,6 +665,15 @@ public void testAllMessagesDelivered() throws Exception { cleanupCompositeExecutor(compositeExec); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + private CompositeExecutor compositeExecutor() { ThreadPoolTaskExecutor ioExec = new ThreadPoolTaskExecutor(); ioExec.setCorePoolSize(2); @@ -682,6 +695,7 @@ private CompositeExecutor compositeExecutor() { @Test public void int3453RaceTest() throws Exception { TcpNioServerConnectionFactory factory = new TcpNioServerConnectionFactory(0); + factory.setBeanFactory(getBeanFactory()); final CountDownLatch connectionLatch = new CountDownLatch(1); factory.setApplicationEventPublisher(new ApplicationEventPublisher() { @@ -769,6 +783,7 @@ public void publishEvent(Object event) { @Test public void testNoDelayOnClose() throws Exception { TcpNioServerConnectionFactory cf = new TcpNioServerConnectionFactory(0); + cf.setBeanFactory(getBeanFactory()); final CountDownLatch reading = new CountDownLatch(1); final StopWatch watch = new StopWatch(); cf.setDeserializer(is -> { @@ -808,6 +823,7 @@ private void testMulti(boolean multiAccept) throws InterruptedException, IOExcep CountDownLatch latch = new CountDownLatch(21); List sockets = new ArrayList<>(); TcpNioServerConnectionFactory server = new TcpNioServerConnectionFactory(0); + server.setBeanFactory(getBeanFactory()); try { List events = Collections.synchronizedList(new ArrayList<>()); List> messages = Collections.synchronizedList(new ArrayList<>()); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java index 76300c4bd07..d143f966421 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2024 the original author or authors. + * Copyright 2022-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,14 @@ import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.scheduling.TaskScheduler; + import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -43,6 +50,7 @@ public class TcpSenderTests { void senderCalledForDeadConnectionClientNet() throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); + server.setBeanFactory(getBeanFactory()); server.registerListener(msg -> false); server.afterPropertiesSet(); server.setApplicationEventPublisher(event -> { @@ -61,6 +69,7 @@ void senderCalledForDeadConnectionClientNet() throws InterruptedException { void senderCalledForDeadConnectionClientNio() throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); + server.setBeanFactory(getBeanFactory()); server.registerListener(msg -> false); server.afterPropertiesSet(); server.setApplicationEventPublisher(event -> { @@ -161,4 +170,12 @@ public synchronized void removeDeadConnection(TcpConnection connection) { assertThat(passedConnectionsToSenderViaAddNewConnection.get(1)).isSameAs(interceptorsPerInstance.get(6)); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java index 551b1e965e8..cbb244597cc 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,12 +44,16 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.GenericMessage; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatException; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIOException; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -308,9 +312,24 @@ public void testTimeoutWithRawDeserializer() { testTimeoutWhileDecoding(new ByteArrayRawSerializer(), "reply"); } + private TcpNioServerConnectionFactory getTcpNioServerConnectionFactory(int port) { + TcpNioServerConnectionFactory result = new TcpNioServerConnectionFactory(port); + result.setBeanFactory(getBeanFactory()); + return result; + } + + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + private void testTimeoutWhileDecoding(AbstractByteArraySerializer deserializer, String reply) { ByteArrayRawSerializer serializer = new ByteArrayRawSerializer(); - TcpNioServerConnectionFactory serverNio = new TcpNioServerConnectionFactory(0); + TcpNioServerConnectionFactory serverNio = getTcpNioServerConnectionFactory(0); serverNio.setApplicationEventPublisher(event -> { }); ByteArrayLengthHeaderSerializer lengthHeaderSerializer = new ByteArrayLengthHeaderSerializer(1); @@ -364,7 +383,7 @@ private void testTimeoutWhileDecoding(AbstractByteArraySerializer deserializer, @Test public void testTimeoutWithRawDeserializerEofIsTerminator() { ByteArrayRawSerializer serializer = new ByteArrayRawSerializer(); - TcpNioServerConnectionFactory serverNio = new TcpNioServerConnectionFactory(0); + TcpNioServerConnectionFactory serverNio = getTcpNioServerConnectionFactory(0); ByteArrayLengthHeaderSerializer lengthHeaderSerializer = new ByteArrayLengthHeaderSerializer(1); serverNio.setDeserializer(lengthHeaderSerializer); serverNio.setSerializer(serializer); diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java index 76f5a90a662..d33aa847beb 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java @@ -93,6 +93,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willAnswer; import static org.mockito.BDDMockito.willDoNothing; @@ -311,7 +312,7 @@ private AbstractMailReceiver receiveAndMarkAsReadDontDeleteGuts(AbstractMailRece ((ImapMailReceiver) receiver).setShouldMarkMessagesAsRead(true); receiver = spy(receiver); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); folderField.setAccessible(true); @@ -419,7 +420,7 @@ public void receiveMarkAsReadAndDelete() throws Exception { ((ImapMailReceiver) receiver).setShouldMarkMessagesAsRead(true); receiver.setShouldDeleteMessages(true); receiver = spy(receiver); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -457,7 +458,7 @@ public void receiveAndDontMarkAsRead() throws Exception { AbstractMailReceiver receiver = new ImapMailReceiver(); ((ImapMailReceiver) receiver).setShouldMarkMessagesAsRead(false); receiver = spy(receiver); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -487,7 +488,7 @@ public void receiveAndDontMarkAsReadButDelete() throws Exception { receiver.setShouldDeleteMessages(true); ((ImapMailReceiver) receiver).setShouldMarkMessagesAsRead(false); receiver = spy(receiver); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -525,7 +526,7 @@ public void receiveAndDontMarkAsReadButDelete() throws Exception { public void receiveAndIgnoreMarkAsReadDontDelete() throws Exception { AbstractMailReceiver receiver = new ImapMailReceiver(); receiver = spy(receiver); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -563,7 +564,7 @@ public void testMessageHistory() throws Exception { AbstractMailReceiver receiver = new ImapMailReceiver(); receiver = spy(receiver); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter); @@ -619,7 +620,7 @@ protected Object handleRequestMessage(org.springframework.messaging.Message r adapter.setReconnectDelay(10); AbstractMailReceiver receiver = new ImapMailReceiver(); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -810,7 +811,7 @@ public void testImapLifecycleForRaceCondition() throws Exception { DirectFieldAccessor df = new DirectFieldAccessor(receiver); df.setPropertyValue("store", store); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); new Thread(() -> { @@ -890,7 +891,7 @@ private Folder testAttachmentsGuts(final ImapMailReceiver receiver) throws Messa given(folder.getPermanentFlags()).willReturn(new Flags(Flags.Flag.USER)); DirectFieldAccessor df = new DirectFieldAccessor(receiver); df.setPropertyValue("store", store); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); return folder; @@ -946,7 +947,7 @@ public Message[] receive() throws MessagingException { @Test public void testIdleReconnects() throws Exception { ImapMailReceiver receiver = spy(new ImapMailReceiver("imap:foo")); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); IMAPFolder folder = mock(IMAPFolder.class); given(folder.getPermanentFlags()).willReturn(new Flags(Flags.Flag.USER)); @@ -982,7 +983,7 @@ public void testIdleReconnects() throws Exception { private void setUpScheduler(ImapMailReceiver mailReceiver, ThreadPoolTaskScheduler taskScheduler) { taskScheduler.setPoolSize(5); taskScheduler.initialize(); - BeanFactory bf = mock(BeanFactory.class); + BeanFactory bf = getBeanFactory(); given(bf.containsBean("taskScheduler")).willReturn(true); given(bf.getBean("taskScheduler", TaskScheduler.class)).willReturn(taskScheduler); mailReceiver.setBeanFactory(bf); @@ -1013,6 +1014,15 @@ public void receiveAndMarkAsReadDontDeleteWithThrowingWhenCopying() throws Excep verify(receiver, times(0)).deleteMessages(Mockito.any()); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + private static class ImapSearchLoggingHandler extends Handler { private final List searches = new ArrayList<>(); diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java index 376f80aff2e..15d21521ec6 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,9 +30,12 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanFactory; +import org.springframework.scheduling.TaskScheduler; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -62,7 +65,7 @@ public void validateSearchTermsWhenShouldMarkAsReadNoExistingFlagsCustom() throw public void validateSearchTermsWhenShouldMarkAsReadNoExistingFlagsGuts(String userFlag, ImapMailReceiver receiver) throws NoSuchFieldException, IllegalAccessException, InvocationTargetException { receiver.setShouldMarkMessagesAsRead(true); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); folderField.setAccessible(true); @@ -85,7 +88,7 @@ public void validateSearchTermsWhenShouldMarkAsReadNoExistingFlagsGuts(String us public void validateSearchTermsWhenShouldMarkAsReadWithExistingFlags() throws Exception { ImapMailReceiver receiver = new ImapMailReceiver(); receiver.setShouldMarkMessagesAsRead(true); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -115,7 +118,7 @@ public void validateSearchTermsWhenShouldMarkAsReadWithExistingFlags() throws Ex public void validateSearchTermsWhenShouldNotMarkAsReadNoExistingFlags() throws Exception { ImapMailReceiver receiver = new ImapMailReceiver(); receiver.setShouldMarkMessagesAsRead(false); - receiver.setBeanFactory(mock(BeanFactory.class)); + receiver.setBeanFactory(getBeanFactory()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -131,4 +134,13 @@ public void validateSearchTermsWhenShouldNotMarkAsReadNoExistingFlags() throws E assertThat(searchTerms instanceof NotTerm).isTrue(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + } diff --git a/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java b/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java index 0c92034e3b3..81e717f6313 100644 --- a/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java +++ b/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,14 +46,17 @@ import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; import org.springframework.messaging.PollableChannel; +import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -72,13 +75,14 @@ public void testUdp() throws Exception { PollableChannel outputChannel = new QueueChannel(); factory.setPort(0); factory.setOutputChannel(outputChannel); - factory.setBeanFactory(mock(BeanFactory.class)); + factory.setBeanFactory(getBeanFactory()); factory.afterPropertiesSet(); factory.start(); UnicastReceivingChannelAdapter server = TestUtils.getPropertyValue(factory, "syslogAdapter.udpAdapter", UnicastReceivingChannelAdapter.class); TestingUtilities.waitListening(server, null); UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject(); + adapter.setBeanFactory(getBeanFactory()); byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE".getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", server.getPort())); @@ -106,7 +110,7 @@ public void testTcp() throws Exception { return null; }).when(publisher).publishEvent(any(ApplicationEvent.class)); factory.setApplicationEventPublisher(publisher); - factory.setBeanFactory(mock(BeanFactory.class)); + factory.setBeanFactory(getBeanFactory()); factory.afterPropertiesSet(); factory.start(); AbstractServerConnectionFactory server = TestUtils.getPropertyValue(factory, "syslogAdapter.connectionFactory", @@ -137,6 +141,15 @@ public void testTcp() throws Exception { assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + @Test public void testAsMapFalse() throws Exception { SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean( @@ -144,15 +157,18 @@ public void testAsMapFalse() throws Exception { factory.setPort(0); PollableChannel outputChannel = new QueueChannel(); factory.setOutputChannel(outputChannel); - factory.setBeanFactory(mock(BeanFactory.class)); + factory.setBeanFactory(getBeanFactory()); factory.afterPropertiesSet(); factory.start(); UnicastReceivingChannelAdapter server = TestUtils.getPropertyValue(factory, "syslogAdapter.udpAdapter", UnicastReceivingChannelAdapter.class); + server.setBeanFactory(getBeanFactory()); TestingUtilities.waitListening(server, null); UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject(); + adapter.setBeanFactory(getBeanFactory()); DefaultMessageConverter defaultMessageConverter = new DefaultMessageConverter(); defaultMessageConverter.setAsMap(false); + defaultMessageConverter.setBeanFactory(getBeanFactory()); adapter.setConverter(defaultMessageConverter); byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE".getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", @@ -173,6 +189,7 @@ public void testAsMapFalse() throws Exception { public void testTcpRFC5424() throws Exception { SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean( SyslogReceivingChannelAdapterFactoryBean.Protocol.tcp); + factory.setBeanFactory(getBeanFactory()); PollableChannel outputChannel = new QueueChannel(); factory.setOutputChannel(outputChannel); ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class); @@ -181,8 +198,9 @@ public void testTcpRFC5424() throws Exception { latch.countDown(); return null; }).when(publisher).publishEvent(any(ApplicationEvent.class)); - factory.setBeanFactory(mock(BeanFactory.class)); + factory.setBeanFactory(getBeanFactory()); AbstractServerConnectionFactory connectionFactory = new TcpNioServerConnectionFactory(0); + connectionFactory.setBeanFactory(getBeanFactory()); connectionFactory.setDeserializer(new RFC6587SyslogDeserializer()); connectionFactory.setApplicationEventPublisher(publisher); factory.setConnectionFactory(connectionFactory); @@ -191,6 +209,7 @@ public void testTcpRFC5424() throws Exception { factory.start(); TestingUtilities.waitListening(connectionFactory, null); TcpSyslogReceivingChannelAdapter adapter = (TcpSyslogReceivingChannelAdapter) factory.getObject(); + adapter.setBeanFactory(getBeanFactory()); LogAccessor logger = spy(TestUtils.getPropertyValue(adapter, "logger", LogAccessor.class)); doReturn(true).when(logger).isDebugEnabled(); final CountDownLatch sawLog = new CountDownLatch(1); @@ -223,21 +242,23 @@ public void testTcpRFC5424() throws Exception { public void testUdpRFC5424() throws Exception { SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean( SyslogReceivingChannelAdapterFactoryBean.Protocol.udp); + factory.setBeanFactory(getBeanFactory()); factory.setPort(0); PollableChannel outputChannel = new QueueChannel(); factory.setOutputChannel(outputChannel); - factory.setBeanFactory(mock(BeanFactory.class)); factory.setConverter(new RFC5424MessageConverter()); factory.afterPropertiesSet(); factory.start(); UnicastReceivingChannelAdapter server = TestUtils.getPropertyValue(factory, "syslogAdapter.udpAdapter", UnicastReceivingChannelAdapter.class); + server.setBeanFactory(getBeanFactory()); TestingUtilities.waitListening(server, null); UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject(); byte[] buf = ("<14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - " + "[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"]" + "[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"] Removing instance") .getBytes(StandardCharsets.UTF_8); + adapter.setBeanFactory(getBeanFactory()); DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", adapter.getPort())); DatagramSocket socket = new DatagramSocket(); From c51bdbf42b894a68d9722d67ee074b51f9f5f37c Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Fri, 13 Jun 2025 10:34:31 -0400 Subject: [PATCH 6/8] Resolve second set of test failures * Remove Nullunmarked from FluxAggregatorMessageHandler * Add TaskScheuler to tests that are failing because of nullability * In the past the TaskScheduler attribute in the testscould be set to null and the tests would succeed. But because of nullability additions these need to be populated --- .../FluxAggregatorMessageHandler.java | 7 +- .../context/IntegrationObjectSupport.java | 2 +- .../FluxAggregatorMessageHandlerTests.java | 16 +--- .../registry/HeaderChannelRegistryTests.java | 14 +--- .../reactivestreams/ReactiveStreamsTests.java | 18 +---- .../gateway/AsyncGatewayTests.java | 79 ++++++------------- .../handler/AsyncHandlerTests.java | 19 ++--- .../MethodInvokingMessageProcessorTests.java | 17 +--- .../ip/dsl/ConnectionFactoryTests.java | 17 +--- .../ip/dsl/IpIntegrationTests.java | 2 + .../tcp/TcpReceivingChannelAdapterTests.java | 15 +--- .../ip/tcp/TcpSendingMessageHandlerTests.java | 19 +---- .../CachingClientConnectionFactoryTests.java | 15 +--- .../connection/ConnectionFactoryTests.java | 24 ++---- .../FailoverClientConnectionFactoryTests.java | 16 +--- .../ip/tcp/connection/SocketSupportTests.java | 16 +--- .../TcpNetConnectionSupportTests.java | 18 +---- .../tcp/connection/TcpNetConnectionTests.java | 16 +--- .../connection/TcpNioConnectionReadTests.java | 19 +---- .../tcp/connection/TcpNioConnectionTests.java | 33 +++----- .../ip/tcp/connection/TcpSenderTests.java | 20 +---- .../tcp/serializer/DeserializationTests.java | 16 +--- .../mail/ImapMailReceiverTests.java | 14 +++- .../mail/ImapMailSearchTermsTests.java | 20 +---- .../SyslogReceivingChannelAdapterTests.java | 35 ++++---- 25 files changed, 119 insertions(+), 368 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java index dac5e2ddb7b..6a0aef85e89 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandler.java @@ -17,11 +17,11 @@ package org.springframework.integration.aggregator; import java.time.Duration; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.function.Predicate; -import org.jspecify.annotations.NullUnmarked; import org.jspecify.annotations.Nullable; import reactor.core.Disposable; import reactor.core.publisher.Flux; @@ -108,7 +108,6 @@ private Flux> releaseBy(Flux> groupFlux) { .flatMap((windowFlux) -> windowFlux.transform(this.combineFunction)); } - @NullUnmarked private Flux>> applyWindowOptions(Flux> groupFlux) { if (this.boundaryTrigger != null) { return groupFlux.windowUntil(this.boundaryTrigger); @@ -117,7 +116,7 @@ private Flux>> applyWindowOptions(Flux> groupFlux) { .switchOnFirst((signal, group) -> { if (signal.hasValue()) { Assert.notNull(this.windowSizeFunction, "'windowSizeFunction' must not be null"); - Integer maxSize = this.windowSizeFunction.apply(signal.get()); + Integer maxSize = this.windowSizeFunction.apply(Objects.requireNonNull(signal.get())); if (maxSize != null) { if (this.windowTimespan != null) { return group.windowTimeout(maxSize, this.windowTimespan); @@ -196,7 +195,7 @@ public void setWindowSize(int windowSize) { /** * Specify a {@link Function} to determine a size for windows to close against the first message in group. * Tne result of the function can be combined with the {@link #setWindowTimespan(Duration)}. - * By default an {@link IntegrationMessageHeaderAccessor#SEQUENCE_SIZE} header is consulted. + * By default, an {@link IntegrationMessageHeaderAccessor#SEQUENCE_SIZE} header is consulted. * @param windowSizeFunction the {@link Function} to use to determine a window size * against a first message in the group. * @see Flux#window(int) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java index 281af0ab08b..29326a7f3f9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationObjectSupport.java @@ -224,7 +224,7 @@ public final void setPrimaryExpression(Expression expression) { } @Override - @SuppressWarnings("NullAway.Init") + @SuppressWarnings("NullAway") public final void afterPropertiesSet() { this.integrationProperties = IntegrationContextUtils.getIntegrationProperties(this.beanFactory); if (this.messageBuilderFactory == null) { diff --git a/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java index 02083f69ddc..87d91025a2d 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/aggregator/FluxAggregatorMessageHandlerTests.java @@ -29,19 +29,14 @@ import reactor.core.publisher.Flux; import reactor.test.StepVerifier; -import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Artem Bilan @@ -165,7 +160,7 @@ void testCustomCombineFunction() { void testWindowTimespan() { QueueChannel resultChannel = new QueueChannel(); FluxAggregatorMessageHandler fluxAggregatorMessageHandler = new FluxAggregatorMessageHandler(); - fluxAggregatorMessageHandler.setBeanFactory(getBeanFactory()); + fluxAggregatorMessageHandler.setTaskScheduler(mock()); fluxAggregatorMessageHandler.setOutputChannel(resultChannel); fluxAggregatorMessageHandler.setWindowTimespan(Duration.ofMillis(100)); fluxAggregatorMessageHandler.start(); @@ -220,15 +215,6 @@ void testWindowTimespan() { executorService.shutdown(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - @Test void testBoundaryTrigger() { QueueChannel resultChannel = new QueueChannel(); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java b/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java index 1c2b5386a69..ab41c2b1766 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/channel/registry/HeaderChannelRegistryTests.java @@ -41,13 +41,12 @@ import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -240,7 +239,7 @@ public void testBFCRNoRegistry() { @Test public void testRemoveOnGet() { DefaultHeaderChannelRegistry registry = new DefaultHeaderChannelRegistry(); - registry.setBeanFactory(getBeanFactory()); + registry.setTaskScheduler(new SimpleAsyncTaskScheduler()); MessageChannel channel = new DirectChannel(); String foo = (String) registry.channelToChannelName(channel); Map map = TestUtils.getPropertyValue(registry, "channels", Map.class); @@ -252,15 +251,6 @@ public void testRemoveOnGet() { assertThat(map.size()).isEqualTo(0); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - public static class Foo extends AbstractReplyProducingMessageHandler { @Override diff --git a/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java b/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java index f25354f5421..9e215b32305 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java @@ -36,7 +36,6 @@ import reactor.core.scheduler.Schedulers; import reactor.test.StepVerifier; -import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ConfigurableApplicationContext; @@ -58,15 +57,11 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Artem Bilan @@ -136,7 +131,7 @@ void testReactiveFlow() throws Exception { @Test void testPollableReactiveFlow() throws Exception { assertThat(this.reactiveTransformer).isInstanceOf(ReactiveStreamsConsumer.class); - this.reactiveTransformer.setBeanFactory(getBeanFactory()); + this.reactiveTransformer.setTaskScheduler(new SimpleAsyncTaskScheduler()); this.inputChannel.send(new GenericMessage<>("1,2,3,4,5")); CountDownLatch latch = new CountDownLatch(6); @@ -172,15 +167,6 @@ void testPollableReactiveFlow() throws Exception { exec.shutdownNow(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - @Test void testFromPublisher() { Flux> messageFlux = diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java index 6fa45ba6de5..dd4509ed491 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/AsyncGatewayTests.java @@ -29,7 +29,6 @@ import reactor.test.StepVerifier; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.MessageDispatchingException; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.GatewayHeader; @@ -42,15 +41,12 @@ import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.messaging.support.GenericMessage; import org.springframework.messaging.support.MessageBuilder; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Mark Fisher @@ -67,9 +63,7 @@ public void futureWithMessageReturned() throws Exception { QueueChannel requestChannel = new QueueChannel(); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future> f = service.returnMessage("foo"); @@ -90,9 +84,7 @@ protected boolean doSend(Message message, long timeout) { }; GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(channel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(channel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future> f = service.returnMessage("foo"); @@ -108,9 +100,7 @@ public void listenableFutureWithMessageReturned() throws Exception { addThreadEnricher(requestChannel); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); CompletableFuture> f = service.returnMessageListenable("foo"); @@ -134,9 +124,7 @@ public void customFutureReturned() { addThreadEnricher(requestChannel); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); CustomFuture f = service.returnCustomFuture("foo"); @@ -151,10 +139,7 @@ public void nonAsyncFutureReturned() { addThreadEnricher(requestChannel); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); - + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.setAsyncExecutor(null); // Not async - user flow returns Future proxyFactory.afterPropertiesSet(); @@ -183,9 +168,7 @@ public void futureWithPayloadReturned() throws Exception { QueueChannel requestChannel = new QueueChannel(); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future f = service.returnString("foo"); @@ -199,9 +182,7 @@ public void futureWithWildcardReturned() throws Exception { QueueChannel requestChannel = new QueueChannel(); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future f = service.returnSomething("foo"); @@ -213,9 +194,7 @@ public void futureWithWildcardReturned() throws Exception { @Test public void futureVoid() throws Exception { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(new NullChannel()); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(new NullChannel(), proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Future f = service.asyncSendAndForget("test1"); @@ -253,9 +232,7 @@ public void futureVoidReply() throws Exception { } }).start(); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.setAsyncExecutor(null); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); @@ -270,9 +247,7 @@ public void monoWithMessageReturned() { QueueChannel requestChannel = new QueueChannel(); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(getBeanFactory()); - proxyFactory.setBeanName("testGateway"); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Mono> mono = service.returnMessagePromise("foo"); @@ -285,9 +260,7 @@ public void monoWithPayloadReturned() { QueueChannel requestChannel = new QueueChannel(); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(getBeanFactory()); - proxyFactory.setBeanName("testGateway"); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Mono mono = service.returnStringPromise("foo"); @@ -300,9 +273,7 @@ public void monoWithWildcardReturned() { QueueChannel requestChannel = new QueueChannel(); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(getBeanFactory()); - proxyFactory.setBeanName("testGateway"); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Mono mono = service.returnSomethingPromise("foo"); @@ -316,9 +287,7 @@ public void monoWithConsumer() { QueueChannel requestChannel = new QueueChannel(); startResponder(requestChannel); GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(requestChannel); - proxyFactory.setBeanFactory(getBeanFactory()); - proxyFactory.setBeanName("testGateway"); + setupProxyFactory(requestChannel, proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Mono mono = service.returnStringPromise("foo"); @@ -331,9 +300,7 @@ public void monoWithConsumer() { @Test public void monoVoid() throws InterruptedException { GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean<>(TestEchoService.class); - proxyFactory.setDefaultRequestChannel(new NullChannel()); - proxyFactory.setBeanName("testGateway"); - proxyFactory.setBeanFactory(getBeanFactory()); + setupProxyFactory(new NullChannel(), proxyFactory); proxyFactory.afterPropertiesSet(); TestEchoService service = proxyFactory.getObject(); Mono mono = service.monoVoid("test1"); @@ -376,15 +343,6 @@ private static void startResponder(final PollableChannel requestChannel) { }).start(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - private interface TestEchoService { Future returnString(String s); @@ -415,6 +373,13 @@ private interface TestEchoService { } + private static void setupProxyFactory(MessageChannel messageChannel, GatewayProxyFactoryBean proxyFactory) { + proxyFactory.setDefaultRequestChannel(messageChannel); + proxyFactory.setBeanName("testGateway"); + proxyFactory.setTaskScheduler(new SimpleAsyncTaskScheduler()); + proxyFactory.setBeanFactory(mock()); + } + private record CustomFuture(String result, Thread thread) implements Future { @Override diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java index 9d592125124..7a981066a4f 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/AsyncHandlerTests.java @@ -41,15 +41,13 @@ import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.support.GenericMessage; import org.springframework.messaging.support.MessageBuilder; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -221,7 +219,8 @@ public void testMessagingExceptionNoErrorChannel() throws Exception { public void testGateway() { this.whichTest = 0; GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>(Foo.class); - gpfb.setBeanFactory(getBeanFactory()); + gpfb.setBeanFactory(mock()); + gpfb.setTaskScheduler(new SimpleAsyncTaskScheduler()); DirectChannel input = new DirectChannel(); gpfb.setDefaultRequestChannel(input); gpfb.setDefaultReplyTimeout(10000L); @@ -236,20 +235,12 @@ public void testGateway() { assertThat(result).isEqualTo("reply"); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - @Test public void testGatewayWithException() { this.whichTest = 0; GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>(Foo.class); - gpfb.setBeanFactory(getBeanFactory()); + gpfb.setBeanFactory(mock()); + gpfb.setTaskScheduler(new SimpleAsyncTaskScheduler()); DirectChannel input = new DirectChannel(); gpfb.setDefaultRequestChannel(input); gpfb.setDefaultReplyTimeout(10000L); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java index 5dd2a5b5a2e..10bf9c6f329 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java @@ -79,7 +79,7 @@ import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.util.StopWatch; import static org.assertj.core.api.Assertions.assertThat; @@ -88,12 +88,9 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.fail; import static org.mockito.AdditionalAnswers.returnsFirstArg; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willAnswer; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Mark Fisher @@ -609,7 +606,8 @@ public void testOverloadedNonVoidReturningMethodsWithExactMatchForType() { @Test public void gatewayTest() throws Exception { GatewayProxyFactoryBean gwFactoryBean = new GatewayProxyFactoryBean<>(); - gwFactoryBean.setBeanFactory(getBeanFactory()); + gwFactoryBean.setTaskScheduler(new SimpleAsyncTaskScheduler()); + gwFactoryBean.setBeanFactory(mock()); gwFactoryBean.afterPropertiesSet(); Object target = gwFactoryBean.getObject(); // just instantiate a helper with a simple target; we're going to invoke getTargetClass with reflection @@ -621,15 +619,6 @@ public void gatewayTest() throws Exception { assertThat(result).isSameAs(RequestReplyExchanger.class); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - @Test public void testInt3199GenericTypeResolvingAndObjectMethod() { diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java index de71a257307..ac99f0a6a1b 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/ConnectionFactoryTests.java @@ -22,7 +22,6 @@ import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory; import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory; @@ -39,13 +38,10 @@ import org.springframework.integration.transformer.ObjectToStringTransformer; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -62,7 +58,7 @@ public void test() throws Exception { ApplicationEventPublisher publisher = e -> { }; AbstractServerConnectionFactory server = Tcp.netServer(0).backlog(2).soTimeout(5000).getObject(); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); final AtomicReference> received = new AtomicReference<>(); final CountDownLatch latch = new CountDownLatch(1); server.registerListener(m -> { @@ -85,15 +81,6 @@ public void test() throws Exception { server.stop(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - @Test public void shouldReturnNioFlavor() { AbstractServerConnectionFactory server = Tcp.nioServer(0).getObject(); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java index a5b0aff0f2a..c68fcd447fe 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/dsl/IpIntegrationTests.java @@ -69,6 +69,7 @@ import org.springframework.messaging.PollableChannel; import org.springframework.messaging.support.GenericMessage; import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.util.ReflectionUtils; @@ -185,6 +186,7 @@ void testUdp() throws Exception { .setHeader("udp_dest", "udp://localhost:" + this.udpInbound.getPort()) .build(); this.udpOut.send(outMessage); + this.udpIn.setTaskScheduler(new SimpleAsyncTaskScheduler()); Message received = this.udpIn.receive(10000); assertThat(received).isNotNull(); assertThat(Transformers.objectToString().transform(received).getPayload()).isEqualTo("foo"); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java index 110328862e6..a6b61770bb9 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java @@ -56,13 +56,11 @@ import org.springframework.messaging.Message; import org.springframework.messaging.SubscribableChannel; import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -452,18 +450,9 @@ public void testNetInterceptors() throws Exception { scf.stop(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - private AbstractServerConnectionFactory getDefaultServerConnectionFactory() { AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); - scf.setBeanFactory(getBeanFactory()); + scf.setTaskScheduler(new SimpleAsyncTaskScheduler()); return scf; } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java index c7f48107e1f..8d9b93ff9b9 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java @@ -73,16 +73,13 @@ import org.springframework.messaging.MessagingException; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.awaitility.Awaitility.await; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -1207,7 +1204,7 @@ public void testConnectionException() throws Exception { public void testInterceptedConnection() throws Exception { final CountDownLatch latch = new CountDownLatch(1); AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); - scf.setBeanFactory(getBeanFactory()); + scf.setTaskScheduler(new SimpleAsyncTaskScheduler()); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); scf.setDeserializer(serializer); @@ -1241,7 +1238,7 @@ public void testInterceptedConnection() throws Exception { public void testInterceptedCleanup() throws Exception { final CountDownLatch latch = new CountDownLatch(1); AbstractServerConnectionFactory scf = new TcpNetServerConnectionFactory(0); - scf.setBeanFactory(getBeanFactory()); + scf.setTaskScheduler(new SimpleAsyncTaskScheduler()); ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer(); scf.setSerializer(serializer); scf.setDeserializer(serializer); @@ -1266,14 +1263,4 @@ public void testInterceptedCleanup() throws Exception { await().untilAsserted(() -> assertThat(handler.getConnections()).isEmpty()); scf.stop(); } - - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java index f82b36f922f..4520a0c61c2 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/CachingClientConnectionFactoryTests.java @@ -68,7 +68,7 @@ import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @@ -78,7 +78,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -700,7 +699,7 @@ public void testRealConnection() throws Exception { @Test //INT-3722 public void testGatewayRelease() { TcpNetServerConnectionFactory in = new TcpNetServerConnectionFactory(0); - in.setBeanFactory(getBeanFactory()); + in.setTaskScheduler(new SimpleAsyncTaskScheduler()); in.setApplicationEventPublisher(mock(ApplicationEventPublisher.class)); final TcpSendingMessageHandler handler = new TcpSendingMessageHandler(); handler.setConnectionFactory(in); @@ -823,14 +822,4 @@ private static AbstractClientConnectionFactory createFactoryWithMockConnection(T when(factory.isActive()).thenReturn(true); return factory; } - - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java index f343282602d..93c3ba3fd79 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionFactoryTests.java @@ -40,14 +40,12 @@ import org.mockito.ArgumentCaptor; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.log.LogAccessor; import org.springframework.core.log.LogMessage; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.integration.channel.NullChannel; import org.springframework.integration.channel.QueueChannel; -import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.integration.ip.config.TcpConnectionFactoryFactoryBean; import org.springframework.integration.ip.event.IpIntegrationEvent; import org.springframework.integration.ip.tcp.TcpOutboundGateway; @@ -57,7 +55,7 @@ import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; @@ -66,7 +64,6 @@ import static org.awaitility.Awaitility.await; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -163,10 +160,8 @@ public void testObtainConnectionIds(AbstractServerConnectionFactory serverFactor ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); scheduler.afterPropertiesSet(); - BeanFactory bf = getBeanFactory(); - when(bf.containsBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)).thenReturn(true); - when(bf.getBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, TaskScheduler.class)).thenReturn(scheduler); - serverFactory.setBeanFactory(bf); + + serverFactory.setTaskScheduler(new SimpleAsyncTaskScheduler()); TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter(); adapter.setOutputChannel(new NullChannel()); adapter.setConnectionFactory(serverFactory); @@ -299,7 +294,7 @@ private void healthCheckSuccess(AbstractServerConnectionFactory server, boolean serverUp.countDown(); } }); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); AtomicReference connection = new AtomicReference<>(); server.registerSender(conn -> { connection.set(conn); @@ -370,19 +365,10 @@ private void healthCheckSuccess(AbstractServerConnectionFactory server, boolean private TcpNetServerConnectionFactory getTcpNetServerConnectionFactory(int port) { TcpNetServerConnectionFactory result = new TcpNetServerConnectionFactory(port); - result.setBeanFactory(getBeanFactory()); + result.setTaskScheduler(new SimpleAsyncTaskScheduler()); return result; } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - @SuppressWarnings("serial") private class FooEvent extends TcpConnectionOpenEvent { diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java index 4a40125ac08..90b9ac73772 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java @@ -54,13 +54,12 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; @@ -702,25 +701,16 @@ private static AbstractClientConnectionFactory createFactoryWithMockConnection(T private TcpNetServerConnectionFactory getTcpNetServerConnectionFactory(int port) { TcpNetServerConnectionFactory result = new TcpNetServerConnectionFactory(port); - result.setBeanFactory(getBeanFactory()); + result.setTaskScheduler(new SimpleAsyncTaskScheduler()); return result; } private TcpNetClientConnectionFactory getTcpNetServerConnectionFactory(String host, int port) { TcpNetClientConnectionFactory result = new TcpNetClientConnectionFactory(host, port); - result.setBeanFactory(getBeanFactory()); + result.setTaskScheduler(new SimpleAsyncTaskScheduler()); return result; } - - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java index b571f462139..096b58d165e 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/SocketSupportTests.java @@ -41,7 +41,6 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer; import org.springframework.integration.ip.util.TestingUtilities; import org.springframework.integration.test.util.TestUtils; @@ -49,7 +48,7 @@ import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.ErrorMessage; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -472,7 +471,7 @@ public void postProcessServerSocket(ServerSocket serverSocket) { public void testNioClientAndServerSSL() throws Exception { System.setProperty("javax.net.debug", "all"); // SSL activity in the console TcpNioServerConnectionFactory server = new TcpNioServerConnectionFactory(0); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); server.setSslHandshakeTimeout(43); DefaultTcpSSLContextSupport sslContextSupport = new DefaultTcpSSLContextSupport("test.ks", "test.truststore.ks", "secret", "secret"); @@ -579,7 +578,7 @@ protected void postProcessSSLEngine(SSLEngine sslEngine) { public void testNioClientAndServerSSLDifferentContextsLargeDataWithReply() throws Exception { System.setProperty("javax.net.debug", "all"); // SSL activity in the console TcpNioServerConnectionFactory server = new TcpNioServerConnectionFactory(0); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); TcpSSLContextSupport serverSslContextSupport = new DefaultTcpSSLContextSupport("server.ks", "server.truststore.ks", "secret", "secret"); DefaultTcpNioSSLConnectionSupport serverTcpNioConnectionSupport = @@ -649,15 +648,6 @@ public void testNioClientAndServerSSLDifferentContextsLargeDataWithReply() throw server.stop(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - private static class Replier implements TcpSender { private TcpConnection connection; diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java index 17152c2df9c..8b84ab66a23 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionSupportTests.java @@ -26,16 +26,11 @@ import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.messaging.Message; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -47,7 +42,7 @@ public class TcpNetConnectionSupportTests { @Test public void testBadCode() throws Exception { TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); AtomicReference> message = new AtomicReference<>(); CountDownLatch latch1 = new CountDownLatch(1); server.registerListener(m -> { @@ -87,13 +82,4 @@ public TcpNetConnection createNewConnection(Socket socket, boolean isServer, boo assertThat(message.get()).isNotNull(); server.stop(); } - - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java index 61ff6f8784e..207f7bf4b7d 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNetConnectionTests.java @@ -36,7 +36,6 @@ import org.mockito.Mockito; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.integration.ip.tcp.connection.TcpNioConnection.ChannelInputStream; import org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer; @@ -47,12 +46,10 @@ import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; import org.springframework.messaging.support.ErrorMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -157,7 +154,7 @@ public void transferHeaders() throws Exception { @Test public void socketClosedNextRead() throws InterruptedException, IOException { TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); AtomicInteger port = new AtomicInteger(); CountDownLatch latch = new CountDownLatch(1); ApplicationEventPublisher publisher = ev -> { @@ -179,13 +176,4 @@ public void socketClosedNextRead() throws InterruptedException, IOException { server.stop(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java index e22f26f0e4a..a3aac38a7fa 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionReadTests.java @@ -30,7 +30,6 @@ import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.ip.tcp.serializer.AbstractByteArraySerializer; import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer; import org.springframework.integration.ip.tcp.serializer.ByteArrayLengthHeaderSerializer; @@ -39,14 +38,10 @@ import org.springframework.integration.ip.util.TestingUtilities; import org.springframework.messaging.Message; import org.springframework.messaging.support.ErrorMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.with; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -68,7 +63,7 @@ private AbstractServerConnectionFactory getConnectionFactory( AbstractByteArraySerializer serializer, TcpListener listener, TcpSender sender) { TcpNioServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); - scf.setBeanFactory(getBeanFactory()); + scf.setTaskScheduler(new SimpleAsyncTaskScheduler()); scf.setUsingDirectBuffers(true); scf.setApplicationEventPublisher(e -> { }); @@ -538,14 +533,4 @@ private void whileOpen(Semaphore semaphore, List added) .atMost(Duration.ofSeconds(20)) .until(() -> !added.get(0).isOpen()); } - - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java index cf6d660aaa5..a86233d012b 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpNioConnectionTests.java @@ -59,7 +59,6 @@ import org.mockito.stubbing.Answer; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; @@ -77,7 +76,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.ErrorMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.ReflectionUtils; import org.springframework.util.StopWatch; @@ -90,7 +89,6 @@ import static org.awaitility.Awaitility.with; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.contains; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willReturn; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -546,9 +544,8 @@ public Integer answer(InvocationOnMock invocation) { @Test public void testAssemblerUsesSecondaryExecutor() throws Exception { - TcpNioServerConnectionFactory factory = new TcpNioServerConnectionFactory(0); + TcpNioServerConnectionFactory factory = newTcpNioServerConnectionFactory(); factory.setApplicationEventPublisher(nullPublisher); - factory.setBeanFactory(getBeanFactory()); CompositeExecutor compositeExec = compositeExecutor(); factory.setSoTimeout(1000); @@ -589,6 +586,12 @@ public void testAssemblerUsesSecondaryExecutor() throws Exception { cleanupCompositeExecutor(compositeExec); } + private static TcpNioServerConnectionFactory newTcpNioServerConnectionFactory() { + TcpNioServerConnectionFactory tcpNioServerConnectionFactory = new TcpNioServerConnectionFactory(0); + tcpNioServerConnectionFactory.setTaskScheduler(new SimpleAsyncTaskScheduler()); + return tcpNioServerConnectionFactory; + } + private void cleanupCompositeExecutor(CompositeExecutor compositeExec) throws Exception { TestUtils.getPropertyValue(compositeExec, "primaryTaskExecutor", DisposableBean.class).destroy(); TestUtils.getPropertyValue(compositeExec, "secondaryTaskExecutor", DisposableBean.class).destroy(); @@ -598,7 +601,7 @@ private void cleanupCompositeExecutor(CompositeExecutor compositeExec) throws Ex public void testAllMessagesDelivered() throws Exception { final int numberOfSockets = 10; TcpNioServerConnectionFactory factory = new TcpNioServerConnectionFactory(0); - factory.setBeanFactory(getBeanFactory()); + factory.setTaskScheduler(mock()); factory.setApplicationEventPublisher(nullPublisher); CompositeExecutor compositeExec = compositeExecutor(); @@ -665,15 +668,6 @@ public void testAllMessagesDelivered() throws Exception { cleanupCompositeExecutor(compositeExec); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - private CompositeExecutor compositeExecutor() { ThreadPoolTaskExecutor ioExec = new ThreadPoolTaskExecutor(); ioExec.setCorePoolSize(2); @@ -695,7 +689,7 @@ private CompositeExecutor compositeExecutor() { @Test public void int3453RaceTest() throws Exception { TcpNioServerConnectionFactory factory = new TcpNioServerConnectionFactory(0); - factory.setBeanFactory(getBeanFactory()); + factory.setTaskScheduler(mock()); final CountDownLatch connectionLatch = new CountDownLatch(1); factory.setApplicationEventPublisher(new ApplicationEventPublisher() { @@ -782,8 +776,7 @@ public void publishEvent(Object event) { @Test public void testNoDelayOnClose() throws Exception { - TcpNioServerConnectionFactory cf = new TcpNioServerConnectionFactory(0); - cf.setBeanFactory(getBeanFactory()); + TcpNioServerConnectionFactory cf = newTcpNioServerConnectionFactory(); final CountDownLatch reading = new CountDownLatch(1); final StopWatch watch = new StopWatch(); cf.setDeserializer(is -> { @@ -822,8 +815,8 @@ private void testMulti(boolean multiAccept) throws InterruptedException, IOExcep CountDownLatch serverReadyLatch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(21); List sockets = new ArrayList<>(); - TcpNioServerConnectionFactory server = new TcpNioServerConnectionFactory(0); - server.setBeanFactory(getBeanFactory()); + TcpNioServerConnectionFactory server = newTcpNioServerConnectionFactory(); + try { List events = Collections.synchronizedList(new ArrayList<>()); List> messages = Collections.synchronizedList(new ArrayList<>()); diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java index d143f966421..85e0bce8d88 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/TcpSenderTests.java @@ -27,14 +27,9 @@ import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -50,7 +45,7 @@ public class TcpSenderTests { void senderCalledForDeadConnectionClientNet() throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); server.registerListener(msg -> false); server.afterPropertiesSet(); server.setApplicationEventPublisher(event -> { @@ -69,7 +64,7 @@ void senderCalledForDeadConnectionClientNet() throws InterruptedException { void senderCalledForDeadConnectionClientNio() throws InterruptedException { CountDownLatch latch = new CountDownLatch(1); TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0); - server.setBeanFactory(getBeanFactory()); + server.setTaskScheduler(new SimpleAsyncTaskScheduler()); server.registerListener(msg -> false); server.afterPropertiesSet(); server.setApplicationEventPublisher(event -> { @@ -169,13 +164,4 @@ public synchronized void removeDeadConnection(TcpConnection connection) { assertThat(passedConnectionsToSenderViaAddNewConnection.get(0)).isSameAs(interceptorsPerInstance.get(3)); assertThat(passedConnectionsToSenderViaAddNewConnection.get(1)).isSameAs(interceptorsPerInstance.get(6)); } - - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } } diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java index cbb244597cc..d36430bca18 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/DeserializationTests.java @@ -44,16 +44,13 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.GenericMessage; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatException; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIOException; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * @author Gary Russell @@ -314,19 +311,10 @@ public void testTimeoutWithRawDeserializer() { private TcpNioServerConnectionFactory getTcpNioServerConnectionFactory(int port) { TcpNioServerConnectionFactory result = new TcpNioServerConnectionFactory(port); - result.setBeanFactory(getBeanFactory()); + result.setTaskScheduler(new SimpleAsyncTaskScheduler()); return result; } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - private void testTimeoutWhileDecoding(AbstractByteArraySerializer deserializer, String reply) { ByteArrayRawSerializer serializer = new ByteArrayRawSerializer(); TcpNioServerConnectionFactory serverNio = getTcpNioServerConnectionFactory(0); diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java index d33aa847beb..152986fdc51 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java @@ -83,6 +83,7 @@ import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.PollableChannel; import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @@ -171,6 +172,7 @@ void stopImapServer() { public void testIdleWithServerCustomSearch() throws Exception { ImapMailReceiver receiver = new ImapMailReceiver("imap://user:pw@localhost:" + imapIdleServer.getImap().getPort() + "/INBOX"); + receiver.setTaskScheduler(new SimpleAsyncTaskScheduler()); receiver.setSearchTermStrategy((supportedFlags, folder) -> { try { FromTerm fromTerm = new FromTerm(new InternetAddress("bar@baz")); @@ -187,6 +189,7 @@ public void testIdleWithServerCustomSearch() throws Exception { public void testIdleWithServerDefaultSearch() throws Exception { ImapMailReceiver receiver = new ImapMailReceiver("imap://user:pw@localhost:" + imapIdleServer.getImap().getPort() + "/INBOX"); + receiver.setTaskScheduler(new SimpleAsyncTaskScheduler()); testIdleWithServerGuts(receiver, false); assertThat(imapSearches.searches.get(0)).contains("testSIUserFlag"); } @@ -214,6 +217,7 @@ public void testIdleWithMessageMappingSimple() throws Exception { ImapMailReceiver receiver = new ImapMailReceiver("imap://user:pw@localhost:" + imapIdleServer.getImap().getPort() + "/INBOX"); receiver.setSimpleContent(true); + receiver.setTaskScheduler(new SimpleAsyncTaskScheduler()); receiver.setHeaderMapper(new DefaultMailHeaderMapper()); testIdleWithServerGuts(receiver, true, true); } @@ -983,7 +987,7 @@ public void testIdleReconnects() throws Exception { private void setUpScheduler(ImapMailReceiver mailReceiver, ThreadPoolTaskScheduler taskScheduler) { taskScheduler.setPoolSize(5); taskScheduler.initialize(); - BeanFactory bf = getBeanFactory(); + BeanFactory bf = getBeanFactory(taskScheduler); given(bf.containsBean("taskScheduler")).willReturn(true); given(bf.getBean("taskScheduler", TaskScheduler.class)).willReturn(taskScheduler); mailReceiver.setBeanFactory(bf); @@ -1014,6 +1018,14 @@ public void receiveAndMarkAsReadDontDeleteWithThrowingWhenCopying() throws Excep verify(receiver, times(0)).deleteMessages(Mockito.any()); } + private BeanFactory getBeanFactory(TaskScheduler taskScheduler) { + BeanFactory beanFactory = mock(BeanFactory.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } + private BeanFactory getBeanFactory() { BeanFactory beanFactory = mock(BeanFactory.class); TaskScheduler taskScheduler = mock(TaskScheduler.class); diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java index 15d21521ec6..d0bbc0553a1 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java @@ -29,13 +29,10 @@ import jakarta.mail.search.SearchTerm; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -65,7 +62,7 @@ public void validateSearchTermsWhenShouldMarkAsReadNoExistingFlagsCustom() throw public void validateSearchTermsWhenShouldMarkAsReadNoExistingFlagsGuts(String userFlag, ImapMailReceiver receiver) throws NoSuchFieldException, IllegalAccessException, InvocationTargetException { receiver.setShouldMarkMessagesAsRead(true); - receiver.setBeanFactory(getBeanFactory()); + receiver.setTaskScheduler(new SimpleAsyncTaskScheduler()); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); folderField.setAccessible(true); @@ -88,7 +85,7 @@ public void validateSearchTermsWhenShouldMarkAsReadNoExistingFlagsGuts(String us public void validateSearchTermsWhenShouldMarkAsReadWithExistingFlags() throws Exception { ImapMailReceiver receiver = new ImapMailReceiver(); receiver.setShouldMarkMessagesAsRead(true); - receiver.setBeanFactory(getBeanFactory()); + receiver.setTaskScheduler(new SimpleAsyncTaskScheduler()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -118,7 +115,7 @@ public void validateSearchTermsWhenShouldMarkAsReadWithExistingFlags() throws Ex public void validateSearchTermsWhenShouldNotMarkAsReadNoExistingFlags() throws Exception { ImapMailReceiver receiver = new ImapMailReceiver(); receiver.setShouldMarkMessagesAsRead(false); - receiver.setBeanFactory(getBeanFactory()); + receiver.setTaskScheduler(new SimpleAsyncTaskScheduler()); receiver.afterPropertiesSet(); Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); @@ -134,13 +131,4 @@ public void validateSearchTermsWhenShouldNotMarkAsReadNoExistingFlags() throws E assertThat(searchTerms instanceof NotTerm).isTrue(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - } diff --git a/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java b/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java index 81e717f6313..4eeb56f1e2d 100644 --- a/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java +++ b/spring-integration-syslog/src/test/java/org/springframework/integration/syslog/inbound/SyslogReceivingChannelAdapterTests.java @@ -75,14 +75,14 @@ public void testUdp() throws Exception { PollableChannel outputChannel = new QueueChannel(); factory.setPort(0); factory.setOutputChannel(outputChannel); - factory.setBeanFactory(getBeanFactory()); + factory.setBeanFactory(mock()); factory.afterPropertiesSet(); factory.start(); UnicastReceivingChannelAdapter server = TestUtils.getPropertyValue(factory, "syslogAdapter.udpAdapter", UnicastReceivingChannelAdapter.class); TestingUtilities.waitListening(server, null); UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject(); - adapter.setBeanFactory(getBeanFactory()); + adapter.setBeanFactory(mock()); byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE".getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", server.getPort())); @@ -141,15 +141,6 @@ public void testTcp() throws Exception { assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); } - private BeanFactory getBeanFactory() { - BeanFactory beanFactory = mock(BeanFactory.class); - TaskScheduler taskScheduler = mock(TaskScheduler.class); - when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) - .thenReturn(taskScheduler); - when(beanFactory.containsBean("taskScheduler")).thenReturn(true); - return beanFactory; - } - @Test public void testAsMapFalse() throws Exception { SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean( @@ -157,18 +148,18 @@ public void testAsMapFalse() throws Exception { factory.setPort(0); PollableChannel outputChannel = new QueueChannel(); factory.setOutputChannel(outputChannel); - factory.setBeanFactory(getBeanFactory()); + factory.setBeanFactory(mock()); factory.afterPropertiesSet(); factory.start(); UnicastReceivingChannelAdapter server = TestUtils.getPropertyValue(factory, "syslogAdapter.udpAdapter", UnicastReceivingChannelAdapter.class); - server.setBeanFactory(getBeanFactory()); + server.setBeanFactory(mock()); TestingUtilities.waitListening(server, null); UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject(); - adapter.setBeanFactory(getBeanFactory()); + adapter.setBeanFactory(mock()); DefaultMessageConverter defaultMessageConverter = new DefaultMessageConverter(); defaultMessageConverter.setAsMap(false); - defaultMessageConverter.setBeanFactory(getBeanFactory()); + defaultMessageConverter.setBeanFactory(mock()); adapter.setConverter(defaultMessageConverter); byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE".getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", @@ -242,7 +233,7 @@ public void testTcpRFC5424() throws Exception { public void testUdpRFC5424() throws Exception { SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean( SyslogReceivingChannelAdapterFactoryBean.Protocol.udp); - factory.setBeanFactory(getBeanFactory()); + factory.setBeanFactory(mock()); factory.setPort(0); PollableChannel outputChannel = new QueueChannel(); factory.setOutputChannel(outputChannel); @@ -251,14 +242,14 @@ public void testUdpRFC5424() throws Exception { factory.start(); UnicastReceivingChannelAdapter server = TestUtils.getPropertyValue(factory, "syslogAdapter.udpAdapter", UnicastReceivingChannelAdapter.class); - server.setBeanFactory(getBeanFactory()); + server.setBeanFactory(mock()); TestingUtilities.waitListening(server, null); UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject(); byte[] buf = ("<14>1 2014-06-20T09:14:07+00:00 loggregator d0602076-b14a-4c55-852a-981e7afeed38 DEA - " + "[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"]" + "[exampleSDID@32473 iut=\\\"3\\\" eventSource=\\\"Application\\\" eventID=\\\"1011\\\"] Removing instance") .getBytes(StandardCharsets.UTF_8); - adapter.setBeanFactory(getBeanFactory()); + adapter.setBeanFactory(mock()); DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", adapter.getPort())); DatagramSocket socket = new DatagramSocket(); @@ -272,4 +263,12 @@ public void testUdpRFC5424() throws Exception { adapter.stop(); } + private BeanFactory getBeanFactory() { + BeanFactory beanFactory = mock(BeanFactory.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + when(beanFactory.getBean(eq("taskScheduler"), any(Class.class))) + .thenReturn(taskScheduler); + when(beanFactory.containsBean("taskScheduler")).thenReturn(true); + return beanFactory; + } } From 608110005722fcb396210471232b9dbf2ff51cd6 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Fri, 13 Jun 2025 16:49:13 -0400 Subject: [PATCH 7/8] Add TaskScheduler for adapter in testNet tests --- .../integration/ip/tcp/TcpReceivingChannelAdapterTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java index a6b61770bb9..59e2682157c 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java @@ -82,7 +82,8 @@ public void testNet() throws Exception { int port = scf.getPort(); QueueChannel channel = new QueueChannel(); adapter.setOutputChannel(channel); - adapter.setBeanFactory(mock(BeanFactory.class)); + adapter.setBeanFactory(mock()); + adapter.setTaskScheduler(new SimpleAsyncTaskScheduler()); adapter.afterPropertiesSet(); Socket socket = SocketFactory.getDefault().createSocket("localhost", port); socket.getOutputStream().write("Test1\r\n".getBytes()); From 7305d7b7e97b842d1c3431cc7adb22c91981e119 Mon Sep 17 00:00:00 2001 From: Glenn Renfro Date: Mon, 16 Jun 2025 08:18:34 -0400 Subject: [PATCH 8/8] Update code based on second review. * Added style to IDE to resolve style issues * Resolved the missed remove from IntegrationContextUtils. * Made sure that private test methods were marked static * Updated Assert.NotNulls to Assert.state and updated their messages * Rebased and updated nullification for changes --- .../AbstractCorrelatingMessageHandler.java | 2 +- .../ExpressionEvaluatingMessageGroupProcessor.java | 2 +- .../ExpressionEvaluatingMessageListProcessor.java | 2 +- .../MethodInvokingMessageGroupProcessor.java | 2 +- .../MethodInvokingMessageListProcessor.java | 3 ++- .../integration/context/IntegrationContextUtils.java | 5 +++-- .../ip/tcp/TcpReceivingChannelAdapterTests.java | 12 ++++++------ .../FailoverClientConnectionFactoryTests.java | 3 ++- 8 files changed, 17 insertions(+), 14 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java index 1b361faf143..6110ed63ba2 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java @@ -937,7 +937,7 @@ protected Collection> completeGroup(Message message, Object correl this.logger.debug(() -> "Completing group with correlationKey [" + correlationKey + "]"); result = this.outputProcessor.processMessageGroup(group); - Assert.notNull(result, "the group returned a null result"); + Assert.state(result != null, "The processorMessageGroup returned a null result. Null result is not expected."); if (isResultCollectionOfMessages(result)) { partialSequence = (Collection>) result; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java index 83956d86c3a..ed842e2b194 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageGroupProcessor.java @@ -61,7 +61,7 @@ public void setExpectedType(Class expectedType) { @Override protected Object aggregatePayloads(MessageGroup group, Map headers) { Object object = this.processor.process(group.getMessages()); - Assert.notNull(object, "Result from processor must not be null"); + Assert.state(object != null, "The process returned a null result. Null result is not expected."); return object; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java index 85db32f537d..85d31c1194a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/ExpressionEvaluatingMessageListProcessor.java @@ -106,7 +106,7 @@ public void setExpectedType(Class expectedType) { @Override public Object process(Collection> messages) { Object object = this.evaluateExpression(this.expression, messages, this.expectedType); - Assert.state(object != null, "Failed to evaluate expression: " + this.expression); + Assert.state(object != null, "The evaluation of the expression returned a null. Null result is not expected." + this.expression); return object; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java index 4fd0ab27967..580f6b1477a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageGroupProcessor.java @@ -89,7 +89,7 @@ public void setBeanFactory(BeanFactory beanFactory) { protected final Object aggregatePayloads(MessageGroup group, Map headers) { final Collection> messagesUpForProcessing = group.getMessages(); Object object = this.processor.process(messagesUpForProcessing, headers); - Assert.notNull(object, "Result from processor must not be null"); + Assert.state(object != null, "The process returned a null result. Null result is not expected."); return object; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageListProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageListProcessor.java index eea61289da7..0eedc66f6b6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageListProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/MethodInvokingMessageListProcessor.java @@ -22,6 +22,7 @@ import java.util.Map; import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.handler.support.MessagingMethodInvokerHelper; @@ -89,7 +90,7 @@ public String toString() { } @SuppressWarnings("unchecked") - public T process(Collection> messages, Map aggregateHeaders) { + public @Nullable T process(Collection> messages, @Nullable Map aggregateHeaders) { return (T) this.delegate.process(messages, aggregateHeaders); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java index f6c11183691..f1626b83b5e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java @@ -131,9 +131,10 @@ public static MetadataStore getMetadataStore(BeanFactory beanFactory) { * @param beanFactory BeanFactory for lookup, must not be null. * @return The {@link MessageChannel} bean whose name is "errorChannel". */ - @Nullable public static MessageChannel getErrorChannel(BeanFactory beanFactory) { - return getBeanOfType(beanFactory, ERROR_CHANNEL_BEAN_NAME, MessageChannel.class); + MessageChannel channel = getBeanOfType(beanFactory, ERROR_CHANNEL_BEAN_NAME, MessageChannel.class); + Assert.state(channel != null, "Error Channel was not found"); + return channel; } /** diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java index 59e2682157c..6b05834bf0a 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapterTests.java @@ -451,12 +451,6 @@ public void testNetInterceptors() throws Exception { scf.stop(); } - private AbstractServerConnectionFactory getDefaultServerConnectionFactory() { - AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); - scf.setTaskScheduler(new SimpleAsyncTaskScheduler()); - return scf; - } - @Test public void testNetSingleNoOutboundInterceptors() throws Exception { AbstractServerConnectionFactory scf = getDefaultServerConnectionFactory(); @@ -660,6 +654,12 @@ public void testException() throws Exception { scf.stop(); } + private static AbstractServerConnectionFactory getDefaultServerConnectionFactory() { + AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(0); + scf.setTaskScheduler(new SimpleAsyncTaskScheduler()); + return scf; + } + private class FailingService { @SuppressWarnings("unused") diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java index 90b9ac73772..f7249518fd2 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/FailoverClientConnectionFactoryTests.java @@ -706,11 +706,12 @@ private TcpNetServerConnectionFactory getTcpNetServerConnectionFactory(int port) return result; } - private TcpNetClientConnectionFactory getTcpNetServerConnectionFactory(String host, int port) { + private static TcpNetClientConnectionFactory getTcpNetServerConnectionFactory(String host, int port) { TcpNetClientConnectionFactory result = new TcpNetClientConnectionFactory(host, port); result.setTaskScheduler(new SimpleAsyncTaskScheduler()); return result; } + }