From fc7d33830267675163d31cc62eb7eabf2197c598 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 1 Nov 2021 14:13:01 -0400 Subject: [PATCH] GH-3656: Fix package tangles Fixes https://github.com/spring-projects/spring-integration/issues/3656 * Move `JavaUtils` from `util` package to the root one to break any possible tangling to/from other packages. * Deprecate an existing `JavaUtils` for backward compatibility * Remove `@IntegrationConverter` from the `JsonNodeWrapperToJsonNodeConverter` and register it manually in the `ConverterRegistrar`. The bean registration for the `JsonNodeWrapperToJsonNodeConverter` must be removed in the next `6.0` * Remove usage of `IntegrationContextUtils` from the `support` package --- .../amqp/config/AmqpChannelFactoryBean.java | 4 +- .../integration/JavaUtils.java | 174 ++++++++++++++++++ ...stractSimpleMessageHandlerFactoryBean.java | 46 ++--- .../config/AggregatorFactoryBean.java | 2 +- .../config/ConverterRegistrar.java | 5 + ...ltConfiguringBeanFactoryPostProcessor.java | 1 + .../context/IntegrationProperties.java | 2 +- .../AnnotationGatewayProxyFactoryBean.java | 4 +- .../gateway/GatewayProxyFactoryBean.java | 4 +- .../JsonNodeWrapperToJsonNodeConverter.java | 2 - .../channel/BeanFactoryChannelResolver.java | 9 +- .../support/utils/IntegrationUtils.java | 3 +- ...TransactionSynchronizationFactoryBean.java | 4 +- .../transformer/ContentEnricher.java | 2 +- .../integration/util/JavaUtils.java | 5 +- ...eTailInboundChannelAdapterFactoryBean.java | 28 +-- .../FileWritingMessageHandlerFactoryBean.java | 34 ++-- .../session/DefaultFtpsSessionFactory.java | 4 +- .../integration/jms/JmsOutboundGateway.java | 4 +- .../jms/config/JmsChannelFactoryBean.java | 48 ++--- .../session/DefaultSftpSessionFactory.java | 2 +- .../syslog/RFC5424SyslogParser.java | 4 +- ...logReceivingChannelAdapterFactoryBean.java | 4 +- .../websocket/ServerWebSocketContainer.java | 2 +- .../ws/dsl/BaseWsOutboundGatewaySpec.java | 8 +- 25 files changed, 292 insertions(+), 113 deletions(-) create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/JavaUtils.java diff --git a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpChannelFactoryBean.java b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpChannelFactoryBean.java index 0ac46b6c62..f150c4fd5a 100644 --- a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpChannelFactoryBean.java +++ b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpChannelFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -39,13 +39,13 @@ import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.context.Lifecycle; import org.springframework.context.SmartLifecycle; +import org.springframework.integration.JavaUtils; import org.springframework.integration.amqp.channel.AbstractAmqpChannel; import org.springframework.integration.amqp.channel.PointToPointSubscribableAmqpChannel; import org.springframework.integration.amqp.channel.PollableAmqpChannel; import org.springframework.integration.amqp.channel.PublishSubscribeAmqpChannel; import org.springframework.integration.amqp.support.AmqpHeaderMapper; import org.springframework.integration.amqp.support.DefaultAmqpHeaderMapper; -import org.springframework.integration.util.JavaUtils; import org.springframework.lang.Nullable; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/JavaUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/JavaUtils.java new file mode 100644 index 0000000000..aedfcb6e9d --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/JavaUtils.java @@ -0,0 +1,174 @@ +/* + * Copyright 2019-2021 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration; + +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +/** + * Chained utility methods to simplify some Java repetitive code. Obtain a reference to + * the singleton {@link #INSTANCE} and then chain calls to the utility methods. + * + * @author Gary Russell + * @author Artem Bilan + * + * @since 5.1.3 + */ +public final class JavaUtils { + + /** + * The singleton instance of this utility class. + */ + public static final JavaUtils INSTANCE = new JavaUtils(); + + private JavaUtils() { + } + + /** + * Invoke {@link Consumer#accept(Object)} with the value if the condition is true. + * @param condition the condition. + * @param value the value. + * @param consumer the consumer. + * @param the value type. + * @return this. + */ + public JavaUtils acceptIfCondition(boolean condition, T value, Consumer consumer) { + if (condition) { + consumer.accept(value); + } + return this; + } + + /** + * Invoke {@link Consumer#accept(Object)} with the value if it is not null. + * @param value the value. + * @param consumer the consumer. + * @param the value type. + * @return this. + */ + public JavaUtils acceptIfNotNull(T value, Consumer consumer) { + if (value != null) { + consumer.accept(value); + } + return this; + } + + /** + * Invoke {@link Consumer#accept(Object)} with the value if it is not null or empty. + * @param value the value. + * @param consumer the consumer. + * @return this. + * @since 5.2 + */ + public JavaUtils acceptIfHasText(String value, Consumer consumer) { + if (StringUtils.hasText(value)) { + consumer.accept(value); + } + return this; + } + + /** + * Invoke {@link Consumer#accept(Object)} with the value if it is not null or empty. + * @param value the value. + * @param consumer the consumer. + * @param the value type. + * @return this. + * @since 5.2 + */ + public JavaUtils acceptIfNotEmpty(List value, Consumer> consumer) { + if (!CollectionUtils.isEmpty(value)) { + consumer.accept(value); + } + return this; + } + + /** + * Invoke {@link Consumer#accept(Object)} with the value if it is not null or empty. + * @param value the value. + * @param consumer the consumer. + * @param the value type. + * @return this. + * @since 5.2 + */ + public JavaUtils acceptIfNotEmpty(T[] value, Consumer consumer) { + if (!ObjectUtils.isEmpty(value)) { + consumer.accept(value); + } + return this; + } + + /** + * Invoke {@link BiConsumer#accept(Object, Object)} with the arguments if the + * condition is true. + * @param condition the condition. + * @param t1 the first consumer argument + * @param t2 the second consumer argument + * @param consumer the consumer. + * @param the first argument type. + * @param the second argument type. + * @return this. + * @since 5.2 + */ + public JavaUtils acceptIfCondition(boolean condition, T1 t1, T2 t2, BiConsumer consumer) { + if (condition) { + consumer.accept(t1, t2); + } + return this; + } + + /** + * Invoke {@link BiConsumer#accept(Object, Object)} with the arguments if the t2 + * argument is not null. + * @param t1 the first argument + * @param t2 the second consumer argument + * @param consumer the consumer. + * @param the first argument type. + * @param the second argument type. + * @return this. + * @since 5.2 + */ + public JavaUtils acceptIfNotNull(T1 t1, T2 t2, BiConsumer consumer) { + if (t2 != null) { + consumer.accept(t1, t2); + } + return this; + } + + /** + * Invoke {@link BiConsumer#accept(Object, Object)} with the arguments if the value + * argument is not null or empty. + * @param t1 the first consumer argument. + * @param value the second consumer argument + * @param the first argument type. + * @param consumer the consumer. + * @return this. + * @since 5.2 + */ + public JavaUtils acceptIfHasText(T t1, String value, BiConsumer consumer) { + if (StringUtils.hasText(value)) { + consumer.accept(t1, value); + } + return this; + } + + +} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java index 4fa5464621..c6cff07d10 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/AbstractSimpleMessageHandlerFactoryBean.java @@ -35,13 +35,13 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.integration.JavaUtils; import org.springframework.integration.context.IntegrationObjectSupport; import org.springframework.integration.context.Orderable; import org.springframework.integration.core.MessageProducer; import org.springframework.integration.handler.AbstractMessageProducingHandler; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.integration.support.context.NamedComponent; -import org.springframework.integration.util.JavaUtils; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.core.DestinationResolver; @@ -199,19 +199,19 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean ((ApplicationContextAware) this.handler).setApplicationContext(this.applicationContext)) - .acceptIfCondition(this.handler instanceof BeanFactoryAware && getBeanFactory() != null, - getBeanFactory(), - factory -> ((BeanFactoryAware) this.handler).setBeanFactory(factory)) - .acceptIfCondition(this.handler instanceof BeanNameAware && this.beanName != null, this.beanName, - name -> ((BeanNameAware) this.handler).setBeanName(this.beanName)) - .acceptIfCondition(this.handler instanceof ApplicationEventPublisherAware - && this.applicationEventPublisher != null, - this.applicationEventPublisher, - publisher -> ((ApplicationEventPublisherAware) this.handler) - .setApplicationEventPublisher(publisher)); + .acceptIfCondition(this.handler instanceof ApplicationContextAware && this.applicationContext != null, + this.applicationContext, + context -> ((ApplicationContextAware) this.handler).setApplicationContext(this.applicationContext)) + .acceptIfCondition(this.handler instanceof BeanFactoryAware && getBeanFactory() != null, + getBeanFactory(), + factory -> ((BeanFactoryAware) this.handler).setBeanFactory(factory)) + .acceptIfCondition(this.handler instanceof BeanNameAware && this.beanName != null, this.beanName, + name -> ((BeanNameAware) this.handler).setBeanName(this.beanName)) + .acceptIfCondition(this.handler instanceof ApplicationEventPublisherAware + && this.applicationEventPublisher != null, + this.applicationEventPublisher, + publisher -> ((ApplicationEventPublisherAware) this.handler) + .setApplicationEventPublisher(publisher)); configureOutputChannelIfAny(); Object actualHandler = extractTarget(this.handler); if (actualHandler == null) { @@ -221,11 +221,11 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean ((AbstractMessageProducingHandler) handlerToConfigure).setAsync(asyncValue)) - .acceptIfCondition(this.handler instanceof Orderable && this.order != null, - this.order, theOrder -> ((Orderable) this.handler).setOrder(theOrder)); + .acceptIfCondition(this.async != null && actualHandler instanceof AbstractMessageProducingHandler, + this.async, + asyncValue -> ((AbstractMessageProducingHandler) handlerToConfigure).setAsync(asyncValue)) + .acceptIfCondition(this.handler instanceof Orderable && this.order != null, + this.order, theOrder -> ((Orderable) this.handler).setOrder(theOrder)); this.initialized = true; } initializingBean(); @@ -235,10 +235,10 @@ public abstract class AbstractSimpleMessageHandlerFactoryBean ((IntegrationObjectSupport) handlerToConfigure).setComponentName(name)) - .acceptIfNotNull(this.channelResolver, - resolver -> ((IntegrationObjectSupport) handlerToConfigure).setChannelResolver(resolver)); + .acceptIfNotNull(this.componentName, + name -> ((IntegrationObjectSupport) handlerToConfigure).setComponentName(name)) + .acceptIfNotNull(this.channelResolver, + resolver -> ((IntegrationObjectSupport) handlerToConfigure).setChannelResolver(resolver)); } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/AggregatorFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/config/AggregatorFactoryBean.java index 9c04d3c10d..7832925b1d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/AggregatorFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/AggregatorFactoryBean.java @@ -26,6 +26,7 @@ import org.aopalliance.aop.Advice; import org.jetbrains.annotations.Nullable; import org.springframework.expression.Expression; +import org.springframework.integration.JavaUtils; import org.springframework.integration.aggregator.AbstractAggregatingMessageGroupProcessor; import org.springframework.integration.aggregator.AggregatingMessageHandler; import org.springframework.integration.aggregator.CorrelationStrategy; @@ -36,7 +37,6 @@ import org.springframework.integration.aggregator.ReleaseStrategy; import org.springframework.integration.store.MessageGroup; import org.springframework.integration.store.MessageGroupStore; import org.springframework.integration.support.locks.LockRegistry; -import org.springframework.integration.util.JavaUtils; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/ConverterRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/config/ConverterRegistrar.java index f8f7d95330..2f33091336 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/ConverterRegistrar.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/ConverterRegistrar.java @@ -26,6 +26,8 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.ConversionServiceFactory; import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.integration.json.JsonNodeWrapperToJsonNodeConverter; +import org.springframework.integration.support.json.JacksonPresent; import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.util.Assert; @@ -74,6 +76,9 @@ class ConverterRegistrar implements InitializingBean, ApplicationContextAware { private void registerConverters(GenericConversionService conversionService) { this.converters.addAll(this.applicationContext.getBeansWithAnnotation(IntegrationConverter.class).values()); + if (JacksonPresent.isJackson2Present()) { + this.converters.add(new JsonNodeWrapperToJsonNodeConverter()); + } ConversionServiceFactory.registerConverters(this.converters, conversionService); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java index 1700f496d2..d9d7eacb13 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java @@ -385,6 +385,7 @@ public class DefaultConfiguringBeanFactoryPostProcessor } } + // TODO Remove in 6.0 private void jsonNodeToString(int registryId) { if (!this.beanFactory.containsBean( IntegrationContextUtils.JSON_NODE_WRAPPER_TO_JSON_NODE_CONVERTER) && 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 d070588446..9629ac4160 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 @@ -19,7 +19,7 @@ package org.springframework.integration.context; import java.util.Arrays; import java.util.Properties; -import org.springframework.integration.util.JavaUtils; +import org.springframework.integration.JavaUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java index edd0bc079e..1e18b40934 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/AnnotationGatewayProxyFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 the original author or authors. + * Copyright 2017-2021 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. @@ -28,9 +28,9 @@ import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.expression.Expression; import org.springframework.expression.common.LiteralExpression; +import org.springframework.integration.JavaUtils; import org.springframework.integration.annotation.AnnotationConstants; import org.springframework.integration.annotation.MessagingGateway; -import org.springframework.integration.util.JavaUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 520ef495aa..2f45691ab2 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -58,6 +58,7 @@ import org.springframework.expression.Expression; import org.springframework.expression.common.LiteralExpression; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.integration.IntegrationPatternType; +import org.springframework.integration.JavaUtils; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.GatewayHeader; import org.springframework.integration.context.IntegrationContextUtils; @@ -68,7 +69,6 @@ import org.springframework.integration.support.channel.ChannelResolverUtils; import org.springframework.integration.support.management.IntegrationManagement; import org.springframework.integration.support.management.TrackableComponent; import org.springframework.integration.support.management.metrics.MetricsCaptor; -import org.springframework.integration.util.JavaUtils; import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; @@ -865,7 +865,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint String gatewayMethodBeanName = getComponentName() + '#' + method.getName() + - '(' + Arrays.stream(method.getParameterTypes()) + '(' + Arrays.stream(method.getParameterTypes()) .map(Class::getSimpleName) .collect(Collectors.joining(", ")) + ')'; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/json/JsonNodeWrapperToJsonNodeConverter.java b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonNodeWrapperToJsonNodeConverter.java index ddaaca11cc..9682a12e67 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/json/JsonNodeWrapperToJsonNodeConverter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonNodeWrapperToJsonNodeConverter.java @@ -21,7 +21,6 @@ import java.util.Set; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.GenericConverter; -import org.springframework.integration.config.IntegrationConverter; import org.springframework.integration.json.JsonPropertyAccessor.JsonNodeWrapper; import org.springframework.lang.Nullable; @@ -38,7 +37,6 @@ import com.fasterxml.jackson.databind.JsonNode; * * @since 5.5 */ -@IntegrationConverter public class JsonNodeWrapperToJsonNodeConverter implements GenericConverter { @Override diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/channel/BeanFactoryChannelResolver.java b/spring-integration-core/src/main/java/org/springframework/integration/support/channel/BeanFactoryChannelResolver.java index 192900553e..1817685c69 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/channel/BeanFactoryChannelResolver.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/channel/BeanFactoryChannelResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -23,7 +23,6 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.core.DestinationResolver; @@ -97,9 +96,9 @@ public class BeanFactoryChannelResolver implements DestinationResolver, E extends AbstractWebServiceOutboundGateway> - extends MessageHandlerSpec { + extends MessageHandlerSpec { private final Map uriVariableExpressions = new HashMap<>(); @@ -158,7 +158,7 @@ public abstract class BaseWsOutboundGatewaySpec< protected E assemble(E gateway) { gateway.setUriVariableExpressions(this.uriVariableExpressions); JavaUtils.INSTANCE - .acceptIfNotNull(this.headerMapper, gateway::setHeaderMapper); + .acceptIfNotNull(this.headerMapper, gateway::setHeaderMapper); gateway.setEncodingMode(this.encodingMode); gateway.setIgnoreEmptyResponses(this.ignoreEmptyResponses); gateway.setRequestCallback(this.requestCallback);