GH-3502: More refactoring to avoid reflection (#3532)
* GH-3502: More refactoring to avoid reflection Fixes https://github.com/spring-projects/spring-integration/issues/3502 * Move `ChannelInitializer` bean registration into an `AbstractIntegrationNamespaceHandler` - it was never used for annotations and Java DSL... * Rework `IntegrationFlows.fromSupplier()` to call a provided `Supplier` directly - not via reflection in the `MethodInvokingMessageSource` * Resolve new Sonar smells * Rework `EndpointSpec` to accept an expected factory bean instance via ctor arg instead of reflection * Rework `Jackson2JsonObjectMapper` to use well-known module instances directly - not via reflection from their class names * * Revert `DefaultMethodInvokingMethodInterceptor.methodHandleCache` property definition wrap
This commit is contained in:
12
build.gradle
12
build.gradle
@@ -440,7 +440,15 @@ project('spring-integration-core') {
|
||||
exclude group: 'org.springframework'
|
||||
}
|
||||
api 'io.projectreactor:reactor-core'
|
||||
|
||||
optionalApi 'com.fasterxml.jackson.core:jackson-databind'
|
||||
optionalApi 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8'
|
||||
optionalApi 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
|
||||
optionalApi 'com.fasterxml.jackson.datatype:jackson-datatype-joda'
|
||||
optionalApi ('com.fasterxml.jackson.module:jackson-module-kotlin') {
|
||||
exclude group: 'org.jetbrains.kotlin'
|
||||
}
|
||||
|
||||
optionalApi "com.jayway.jsonpath:json-path:$jsonpathVersion"
|
||||
optionalApi "com.esotericsoftware:kryo-shaded:$kryoShadedVersion"
|
||||
optionalApi "io.micrometer:micrometer-core:$micrometerVersion"
|
||||
@@ -449,10 +457,6 @@ project('spring-integration-core') {
|
||||
optionalApi 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||
|
||||
testImplementation "org.aspectj:aspectjweaver:$aspectjVersion"
|
||||
testImplementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
|
||||
testRuntime ('com.fasterxml.jackson.module:jackson-module-kotlin') {
|
||||
exclude group: 'org.jetbrains.kotlin'
|
||||
}
|
||||
testImplementation "org.hamcrest:hamcrest-core:$hamcrestVersion"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -40,16 +40,20 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.1.1
|
||||
*/
|
||||
final class ChannelInitializer implements BeanFactoryAware, InitializingBean {
|
||||
public final class ChannelInitializer implements BeanFactoryAware, InitializingBean {
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
private static final Log LOGGER = LogFactory.getLog(ChannelInitializer.class);
|
||||
|
||||
private volatile BeanFactory beanFactory;
|
||||
|
||||
private volatile boolean autoCreate = true;
|
||||
|
||||
ChannelInitializer() {
|
||||
}
|
||||
|
||||
public void setAutoCreate(boolean autoCreate) {
|
||||
this.autoCreate = autoCreate;
|
||||
@@ -68,17 +72,18 @@ final class ChannelInitializer implements BeanFactoryAware, InitializingBean {
|
||||
}
|
||||
else {
|
||||
AutoCreateCandidatesCollector channelCandidatesCollector =
|
||||
this.beanFactory.getBean(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME, AutoCreateCandidatesCollector.class);
|
||||
Assert.notNull(channelCandidatesCollector, "Failed to locate '" + IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
|
||||
this.beanFactory.getBean(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME,
|
||||
AutoCreateCandidatesCollector.class);
|
||||
// at this point channelNames are all resolved with placeholders and SpEL
|
||||
Collection<String> channelNames = channelCandidatesCollector.getChannelNames();
|
||||
if (channelNames != null) {
|
||||
for (String channelName : channelNames) {
|
||||
if (!this.beanFactory.containsBean(channelName)) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Auto-creating channel '" + channelName + "' as DirectChannel");
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Auto-creating channel '" + channelName + "' as DirectChannel");
|
||||
}
|
||||
IntegrationConfigUtils.autoCreateDirectChannel(channelName, (BeanDefinitionRegistry) this.beanFactory);
|
||||
IntegrationConfigUtils.autoCreateDirectChannel(channelName,
|
||||
(BeanDefinitionRegistry) this.beanFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,7 +93,7 @@ final class ChannelInitializer implements BeanFactoryAware, InitializingBean {
|
||||
/*
|
||||
* Collects candidate channel names to be auto-created by ChannelInitializer
|
||||
*/
|
||||
static class AutoCreateCandidatesCollector {
|
||||
public static class AutoCreateCandidatesCollector {
|
||||
|
||||
private final Collection<String> channelNames;
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.HierarchicalBeanFactory;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
@@ -58,6 +57,7 @@ import org.springframework.integration.handler.support.CollectionArgumentResolve
|
||||
import org.springframework.integration.handler.support.MapArgumentResolver;
|
||||
import org.springframework.integration.handler.support.PayloadExpressionArgumentResolver;
|
||||
import org.springframework.integration.handler.support.PayloadsArgumentResolver;
|
||||
import org.springframework.integration.json.JsonNodeWrapperToJsonNodeConverter;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.NullAwarePayloadArgumentResolver;
|
||||
import org.springframework.integration.support.SmartLifecycleRoleController;
|
||||
@@ -67,7 +67,6 @@ import org.springframework.integration.support.converter.ConfigurableCompositeMe
|
||||
import org.springframework.integration.support.converter.DefaultDatatypeChannelMessageConverter;
|
||||
import org.springframework.integration.support.json.JacksonPresent;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.converter.MessageConverter;
|
||||
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
|
||||
@@ -75,6 +74,7 @@ import org.springframework.messaging.handler.invocation.HandlerMethodArgumentRes
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ErrorHandler;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link BeanFactoryPostProcessor} implementation that registers bean definitions
|
||||
@@ -100,12 +100,44 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
|
||||
private static final Set<Integer> REGISTRIES_PROCESSED = new HashSet<>();
|
||||
|
||||
|
||||
private static final Class<?> XPATH_CLASS;
|
||||
|
||||
private static final Class<?> JSON_PATH_CLASS;
|
||||
|
||||
static {
|
||||
Class<?> xpathClass = null;
|
||||
try {
|
||||
xpathClass = ClassUtils.forName(IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils",
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
catch (@SuppressWarnings("unused") ClassNotFoundException e) {
|
||||
LOGGER.debug("SpEL function '#xpath' isn't registered: " +
|
||||
"there is no spring-integration-xml.jar on the classpath.");
|
||||
}
|
||||
finally {
|
||||
XPATH_CLASS = xpathClass;
|
||||
}
|
||||
|
||||
Class<?> jsonPathClass = null;
|
||||
try {
|
||||
jsonPathClass = ClassUtils.forName(IntegrationConfigUtils.BASE_PACKAGE + ".json.JsonPathUtils",
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
catch (@SuppressWarnings("unused") ClassNotFoundException e) {
|
||||
LOGGER.debug("The '#jsonPath' SpEL function cannot be registered: " +
|
||||
"there is no jayway json-path.jar on the classpath.");
|
||||
}
|
||||
finally {
|
||||
JSON_PATH_CLASS = jsonPathClass;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private BeanExpressionContext expressionContext;
|
||||
|
||||
private BeanDefinitionRegistry registry;
|
||||
|
||||
@Override
|
||||
@@ -117,7 +149,6 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (beanFactory instanceof BeanDefinitionRegistry) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.expressionContext = new BeanExpressionContext(beanFactory, null);
|
||||
this.registry = (BeanDefinitionRegistry) beanFactory;
|
||||
|
||||
registerBeanFactoryChannelResolver();
|
||||
@@ -242,16 +273,14 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
}
|
||||
|
||||
private PublishSubscribeChannel createErrorChannel() {
|
||||
String requireSubscribersExpression =
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.ERROR_CHANNEL_REQUIRE_SUBSCRIBERS);
|
||||
Boolean requireSubscribers = resolveExpression(requireSubscribersExpression, Boolean.class);
|
||||
Properties integrationProperties = IntegrationContextUtils.getIntegrationProperties(this.beanFactory);
|
||||
String requireSubscribers =
|
||||
integrationProperties.getProperty(IntegrationProperties.ERROR_CHANNEL_REQUIRE_SUBSCRIBERS);
|
||||
|
||||
PublishSubscribeChannel errorChannel = new PublishSubscribeChannel(Boolean.TRUE.equals(requireSubscribers));
|
||||
PublishSubscribeChannel errorChannel = new PublishSubscribeChannel(Boolean.parseBoolean(requireSubscribers));
|
||||
|
||||
String ignoreFailuresExpression =
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.ERROR_CHANNEL_IGNORE_FAILURES);
|
||||
Boolean ignoreFailures = resolveExpression(ignoreFailuresExpression, Boolean.class);
|
||||
errorChannel.setIgnoreFailures(Boolean.TRUE.equals(ignoreFailures));
|
||||
String ignoreFailures = integrationProperties.getProperty(IntegrationProperties.ERROR_CHANNEL_IGNORE_FAILURES);
|
||||
errorChannel.setIgnoreFailures(Boolean.parseBoolean(ignoreFailures));
|
||||
|
||||
return errorChannel;
|
||||
}
|
||||
@@ -323,12 +352,9 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
taskScheduler.setErrorHandler(
|
||||
this.beanFactory.getBean(ChannelUtils.MESSAGE_PUBLISHING_ERROR_HANDLER_BEAN_NAME, ErrorHandler.class));
|
||||
|
||||
String poolSizeExpression =
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.TASK_SCHEDULER_POOL_SIZE);
|
||||
Integer poolSize = resolveExpression(poolSizeExpression, Integer.class);
|
||||
if (poolSize != null) {
|
||||
taskScheduler.setPoolSize(poolSize);
|
||||
}
|
||||
Properties integrationProperties = IntegrationContextUtils.getIntegrationProperties(this.beanFactory);
|
||||
String poolSize = integrationProperties.getProperty(IntegrationProperties.TASK_SCHEDULER_POOL_SIZE);
|
||||
taskScheduler.setPoolSize(Integer.parseInt(poolSize));
|
||||
|
||||
return taskScheduler;
|
||||
}
|
||||
@@ -376,54 +402,21 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
|
||||
private void jsonPath(int registryId) throws LinkageError {
|
||||
String jsonPathBeanName = "jsonPath";
|
||||
if (!this.beanFactory.containsBean(jsonPathBeanName) && !REGISTRIES_PROCESSED.contains(registryId)) {
|
||||
Class<?> jsonPathClass = null;
|
||||
try {
|
||||
jsonPathClass = ClassUtils.forName("com.jayway.jsonpath.JsonPath", this.classLoader);
|
||||
}
|
||||
catch (@SuppressWarnings("unused") ClassNotFoundException e) {
|
||||
LOGGER.debug("The '#jsonPath' SpEL function cannot be registered: " +
|
||||
"there is no jayway json-path.jar on the classpath.");
|
||||
}
|
||||
if (JSON_PATH_CLASS != null
|
||||
&& !this.beanFactory.containsBean(jsonPathBeanName)
|
||||
&& !REGISTRIES_PROCESSED.contains(registryId)) {
|
||||
|
||||
if (jsonPathClass != null) {
|
||||
try {
|
||||
ClassUtils.forName("com.jayway.jsonpath.Predicate", this.classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
jsonPathClass = null;
|
||||
LOGGER.warn(ex, "The '#jsonPath' SpEL function cannot be registered. " +
|
||||
"An old json-path.jar version is detected in the classpath." +
|
||||
"At least 2.4.0 is required; see version information at: " +
|
||||
"https://github.com/jayway/JsonPath/releases");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonPathClass != null) {
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(this.registry, jsonPathBeanName,
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".json.JsonPathUtils", "evaluate");
|
||||
}
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(this.registry, jsonPathBeanName, JSON_PATH_CLASS, "evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
private void xpath(int registryId) throws LinkageError {
|
||||
String xpathBeanName = "xpath";
|
||||
if (!this.beanFactory.containsBean(xpathBeanName) && !REGISTRIES_PROCESSED.contains(registryId)) {
|
||||
Class<?> xpathClass = null;
|
||||
try {
|
||||
xpathClass = ClassUtils.forName(IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils",
|
||||
this.classLoader);
|
||||
}
|
||||
catch (@SuppressWarnings("unused") ClassNotFoundException e) {
|
||||
LOGGER.debug("SpEL function '#xpath' isn't registered: " +
|
||||
"there is no spring-integration-xml.jar on the classpath.");
|
||||
}
|
||||
if (XPATH_CLASS != null
|
||||
&& !this.beanFactory.containsBean(xpathBeanName)
|
||||
&& !REGISTRIES_PROCESSED.contains(registryId)) {
|
||||
|
||||
if (xpathClass != null) {
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(this.registry, xpathBeanName,
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils", "evaluate");
|
||||
}
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(this.registry, xpathBeanName, XPATH_CLASS, "evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,9 +427,9 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
|
||||
this.registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.JSON_NODE_WRAPPER_TO_JSON_NODE_CONVERTER,
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationConfigUtils.BASE_PACKAGE +
|
||||
".json.JsonNodeWrapperToJsonNodeConverter")
|
||||
.getBeanDefinition());
|
||||
new RootBeanDefinition(JsonNodeWrapperToJsonNodeConverter.class,
|
||||
JsonNodeWrapperToJsonNodeConverter::new));
|
||||
|
||||
INTEGRATION_CONVERTER_INITIALIZER.registerConverter(this.registry,
|
||||
new RuntimeBeanReference(IntegrationContextUtils.JSON_NODE_WRAPPER_TO_JSON_NODE_CONVERTER));
|
||||
}
|
||||
@@ -457,21 +450,19 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
*/
|
||||
private void registerMessageBuilderFactory() {
|
||||
if (!this.beanFactory.containsBean(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME)) {
|
||||
BeanDefinition mbfBean =
|
||||
new RootBeanDefinition(DefaultMessageBuilderFactory.class,
|
||||
() -> {
|
||||
DefaultMessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
|
||||
String readOnlyHeadersExpression =
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.READ_ONLY_HEADERS);
|
||||
String[] readOnlyHeaders = resolveExpression(readOnlyHeadersExpression, String[].class);
|
||||
messageBuilderFactory.setReadOnlyHeaders(readOnlyHeaders);
|
||||
return messageBuilderFactory;
|
||||
});
|
||||
|
||||
this.registry.registerBeanDefinition(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME, mbfBean);
|
||||
this.registry.registerBeanDefinition(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME,
|
||||
new RootBeanDefinition(DefaultMessageBuilderFactory.class, this::createDefaultMessageBuilderFactory));
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultMessageBuilderFactory createDefaultMessageBuilderFactory() {
|
||||
DefaultMessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
|
||||
Properties integrationProperties = IntegrationContextUtils.getIntegrationProperties(this.beanFactory);
|
||||
String readOnlyHeaders = integrationProperties.getProperty(IntegrationProperties.READ_ONLY_HEADERS);
|
||||
messageBuilderFactory.setReadOnlyHeaders(StringUtils.commaDelimitedListToStringArray(readOnlyHeaders));
|
||||
return messageBuilderFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link DefaultHeaderChannelRegistry} if necessary.
|
||||
*/
|
||||
@@ -585,10 +576,4 @@ class DefaultConfiguringBeanFactoryPostProcessor
|
||||
return resolvers;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> T resolveExpression(String expression, Class<T> expectedType) {
|
||||
Object value = this.beanFactory.getBeanExpressionResolver().evaluate(expression, this.expressionContext);
|
||||
return this.beanFactory.getTypeConverter().convertIfNecessary(value, expectedType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
* Copyright 2014-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.
|
||||
@@ -16,18 +16,22 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.integration.channel.interceptor.GlobalChannelInterceptorWrapper;
|
||||
import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
@@ -39,38 +43,72 @@ import org.springframework.util.CollectionUtils;
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public class GlobalChannelInterceptorInitializer implements IntegrationConfigurationInitializer {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private BeanExpressionContext beanExpressionContext;
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
|
||||
|
||||
this.beanExpressionContext = new BeanExpressionContext(beanFactory, null);
|
||||
for (String beanName : registry.getBeanDefinitionNames()) {
|
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
|
||||
if (beanDefinition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotationMetadata metadata = ((AnnotatedBeanDefinition) beanDefinition).getMetadata();
|
||||
Map<String, Object> annotationAttributes = metadata
|
||||
.getAnnotationAttributes(GlobalChannelInterceptor.class.getName());
|
||||
Map<String, Object> annotationAttributes =
|
||||
metadata.getAnnotationAttributes(GlobalChannelInterceptor.class.getName());
|
||||
if (CollectionUtils.isEmpty(annotationAttributes)
|
||||
&& beanDefinition.getSource() instanceof MethodMetadata) {
|
||||
MethodMetadata beanMethod = (MethodMetadata) beanDefinition.getSource();
|
||||
annotationAttributes =
|
||||
beanMethod.getAnnotationAttributes(GlobalChannelInterceptor.class.getName()); // NOSONAR not null
|
||||
beanMethod.getAnnotationAttributes(GlobalChannelInterceptor.class.getName()); // NOSONAR not null
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(annotationAttributes)) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(GlobalChannelInterceptorWrapper.class)
|
||||
.addConstructorArgReference(beanName)
|
||||
.addPropertyValue("patterns", annotationAttributes.get("patterns"))
|
||||
.addPropertyValue("order", annotationAttributes.get("order"));
|
||||
Map<String, Object> attributes = annotationAttributes;
|
||||
RootBeanDefinition channelInterceptorWrapper =
|
||||
new RootBeanDefinition(GlobalChannelInterceptorWrapper.class,
|
||||
() -> createGlobalChannelInterceptorWrapper(beanName, attributes));
|
||||
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), registry);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(channelInterceptorWrapper, registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GlobalChannelInterceptorWrapper createGlobalChannelInterceptorWrapper(String interceptorBeanName,
|
||||
Map<String, Object> annotationAttributes) {
|
||||
|
||||
ChannelInterceptor interceptor = this.beanFactory.getBean(interceptorBeanName, ChannelInterceptor.class);
|
||||
GlobalChannelInterceptorWrapper interceptorWrapper = new GlobalChannelInterceptorWrapper(interceptor);
|
||||
String[] patterns =
|
||||
Arrays.stream((String[]) annotationAttributes.get("patterns"))
|
||||
.map(this::resolveEmbeddedValue)
|
||||
.toArray(String[]::new);
|
||||
interceptorWrapper.setPatterns(patterns);
|
||||
interceptorWrapper.setOrder((Integer) annotationAttributes.get("order"));
|
||||
return interceptorWrapper;
|
||||
}
|
||||
|
||||
private String resolveEmbeddedValue(String value) {
|
||||
String valueToReturn = this.beanFactory.resolveEmbeddedValue(value);
|
||||
if (valueToReturn == null || !(valueToReturn.startsWith("#{") && value.endsWith("}"))) {
|
||||
return valueToReturn;
|
||||
}
|
||||
|
||||
BeanExpressionResolver beanExpressionResolver = this.beanFactory.getBeanExpressionResolver();
|
||||
if (beanExpressionResolver != null) {
|
||||
Object result = beanExpressionResolver.evaluate(valueToReturn, this.beanExpressionContext);
|
||||
return result != null ? result.toString() : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
* Copyright 2014-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.
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
|
||||
/**
|
||||
@@ -36,7 +35,7 @@ public final class IntegrationConfigUtils {
|
||||
public static final String HANDLER_ALIAS_SUFFIX = ".handler";
|
||||
|
||||
public static void registerSpelFunctionBean(BeanDefinitionRegistry registry, String functionId, String className,
|
||||
String methodSignature) {
|
||||
String methodSignature) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SpelFunctionFactoryBean.class)
|
||||
.addConstructorArgValue(className)
|
||||
@@ -44,10 +43,23 @@ public final class IntegrationConfigUtils {
|
||||
registry.registerBeanDefinition(functionId, builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link SpelFunctionFactoryBean} for the provided method signature
|
||||
* @param registry the registry for bean to register
|
||||
* @param functionId the bean name
|
||||
* @param aClass the class for function
|
||||
* @param methodSignature the function method to be called from SpEL
|
||||
* @since 5.5
|
||||
*/
|
||||
public static void registerSpelFunctionBean(BeanDefinitionRegistry registry, String functionId, Class<?> aClass,
|
||||
String methodSignature) {
|
||||
|
||||
registry.registerBeanDefinition(functionId, new RootBeanDefinition(SpelFunctionFactoryBean.class,
|
||||
() -> new SpelFunctionFactoryBean(aClass, methodSignature)));
|
||||
}
|
||||
|
||||
public static void autoCreateDirectChannel(String channelName, BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionBuilder channelBuilder = BeanDefinitionBuilder.genericBeanDefinition(DirectChannel.class);
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(channelBuilder.getBeanDefinition(), channelName);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
|
||||
registry.registerBeanDefinition(channelName, new RootBeanDefinition(DirectChannel.class, DirectChannel::new));
|
||||
}
|
||||
|
||||
private IntegrationConfigUtils() {
|
||||
|
||||
@@ -17,18 +17,14 @@
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.NativeDetector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.context.IntegrationProperties;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -63,42 +59,10 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
public void registerBeanDefinitions(@Nullable AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
registerImplicitChannelCreator(registry);
|
||||
registerDefaultConfiguringBeanFactoryPostProcessor(registry);
|
||||
registerIntegrationConfigurationBeanFactoryPostProcessor(registry);
|
||||
if (importingClassMetadata != null) {
|
||||
registerMessagingAnnotationPostProcessors(importingClassMetadata, registry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will auto-register a ChannelInitializer which could also be overridden by the user
|
||||
* by simply registering a ChannelInitializer {@code <bean>} with its {@code autoCreate} property
|
||||
* set to false to suppress channel creation.
|
||||
* It will also register a ChannelInitializer$AutoCreateCandidatesCollector
|
||||
* which simply collects candidate channel names.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private void registerImplicitChannelCreator(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.CHANNEL_INITIALIZER_BEAN_NAME)) {
|
||||
String channelsAutoCreateExpression =
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.CHANNELS_AUTOCREATE);
|
||||
BeanDefinitionBuilder channelDef = BeanDefinitionBuilder.genericBeanDefinition(ChannelInitializer.class)
|
||||
.addPropertyValue("autoCreate", channelsAutoCreateExpression);
|
||||
BeanDefinitionHolder channelCreatorHolder = new BeanDefinitionHolder(channelDef.getBeanDefinition(),
|
||||
IntegrationContextUtils.CHANNEL_INITIALIZER_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(channelCreatorHolder, registry);
|
||||
}
|
||||
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder channelRegistryBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ChannelInitializer.AutoCreateCandidatesCollector.class);
|
||||
channelRegistryBuilder.addConstructorArgValue(new ManagedSet<String>());
|
||||
channelRegistryBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //SPR-12761
|
||||
BeanDefinitionHolder channelRegistryHolder =
|
||||
new BeanDefinitionHolder(channelRegistryBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(channelRegistryHolder, registry);
|
||||
registerMessagingAnnotationPostProcessors(registry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,13 +72,9 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
*/
|
||||
private void registerDefaultConfiguringBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder postProcessorBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(DefaultConfiguringBeanFactoryPostProcessor.class,
|
||||
DefaultConfiguringBeanFactoryPostProcessor::new);
|
||||
BeanDefinitionHolder postProcessorHolder = new BeanDefinitionHolder(
|
||||
postProcessorBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(postProcessorHolder, registry);
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME,
|
||||
new RootBeanDefinition(DefaultConfiguringBeanFactoryPostProcessor.class,
|
||||
DefaultConfiguringBeanFactoryPostProcessor::new));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,13 +83,13 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
* to process the external Integration infrastructure.
|
||||
*/
|
||||
private void registerIntegrationConfigurationBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
|
||||
if (!(NativeDetector.inNativeImage()) // Spring Native detects all the 'spring.factories'
|
||||
&& !registry.containsBeanDefinition(
|
||||
if (!registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME)) {
|
||||
|
||||
BeanDefinitionBuilder postProcessorBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationConfigurationBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
BeanDefinitionBuilder postProcessorBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationConfigurationBeanFactoryPostProcessor.class,
|
||||
IntegrationConfigurationBeanFactoryPostProcessor::new)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME,
|
||||
postProcessorBuilder.getBeanDefinition());
|
||||
}
|
||||
@@ -140,10 +100,9 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
* {@link org.springframework.integration.aop.PublisherAnnotationBeanPostProcessor},
|
||||
* if necessary.
|
||||
* Inject {@code defaultPublishedChannel} from provided {@link AnnotationMetadata}, if any.
|
||||
* @param meta The {@link AnnotationMetadata} to get additional properties for {@link BeanDefinition}s.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private void registerMessagingAnnotationPostProcessors(AnnotationMetadata meta, BeanDefinitionRegistry registry) {
|
||||
private void registerMessagingAnnotationPostProcessors(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.MESSAGING_ANNOTATION_POSTPROCESSOR_NAME)) {
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(MessagingAnnotationPostProcessor.class,
|
||||
@@ -153,11 +112,6 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.MESSAGING_ANNOTATION_POSTPROCESSOR_NAME,
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (meta.getAnnotationAttributes(EnablePublisher.class.getName()) != null) {
|
||||
new PublisherRegistrar().
|
||||
registerBeanDefinitions(meta, registry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-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.
|
||||
@@ -21,17 +21,18 @@ import java.util.Map;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.integration.aop.PublisherAnnotationBeanPostProcessor;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -49,50 +50,62 @@ public class PublisherRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
Map<String, Object> annotationAttributes =
|
||||
importingClassMetadata.getAnnotationAttributes(EnablePublisher.class.getName());
|
||||
|
||||
String defaultChannel =
|
||||
annotationAttributes == null
|
||||
? (String) AnnotationUtils.getDefaultValue(EnablePublisher.class)
|
||||
: (String) annotationAttributes.get("defaultChannel");
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.PUBLISHER_ANNOTATION_POSTPROCESSOR_NAME)) {
|
||||
ConfigurableBeanFactory beanFactory;
|
||||
if (registry instanceof ConfigurableBeanFactory) {
|
||||
beanFactory = (ConfigurableBeanFactory) registry;
|
||||
}
|
||||
else if (registry instanceof ConfigurableApplicationContext) {
|
||||
beanFactory = ((ConfigurableApplicationContext) registry).getBeanFactory();
|
||||
}
|
||||
else {
|
||||
beanFactory = null;
|
||||
}
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(PublisherAnnotationBeanPostProcessor.class)
|
||||
BeanDefinitionBuilder.genericBeanDefinition(PublisherAnnotationBeanPostProcessor.class,
|
||||
() -> createPublisherAnnotationBeanPostProcessor(annotationAttributes, beanFactory))
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
if (StringUtils.hasText(defaultChannel)) {
|
||||
builder.addPropertyValue("defaultChannelName", defaultChannel);
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info("Setting '@Publisher' default-output-channel to '" + defaultChannel + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
if (annotationAttributes != null) {
|
||||
Object proxyTargetClass = annotationAttributes.get("proxyTargetClass");
|
||||
builder.addPropertyValue("proxyTargetClass", proxyTargetClass);
|
||||
Object order = annotationAttributes.get("order");
|
||||
builder.addPropertyValue("order", order);
|
||||
}
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.PUBLISHER_ANNOTATION_POSTPROCESSOR_NAME,
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
else {
|
||||
BeanDefinition beanDefinition =
|
||||
registry.getBeanDefinition(IntegrationContextUtils.PUBLISHER_ANNOTATION_POSTPROCESSOR_NAME);
|
||||
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
|
||||
PropertyValue defaultChannelPropertyValue = propertyValues.getPropertyValue("defaultChannelName");
|
||||
if (StringUtils.hasText(defaultChannel)) {
|
||||
if (defaultChannelPropertyValue == null) {
|
||||
propertyValues.addPropertyValue("defaultChannelName", defaultChannel);
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info("Setting '@Publisher' default-output-channel to '" + defaultChannel + "'.");
|
||||
}
|
||||
}
|
||||
else if (!defaultChannel.equals(defaultChannelPropertyValue.getValue())) {
|
||||
throw new BeanDefinitionStoreException("When more than one enable publisher definition " +
|
||||
"(@EnablePublisher or <annotation-config>) is found in the context, " +
|
||||
"they all must have the same 'default-publisher-channel' attribute value.");
|
||||
}
|
||||
}
|
||||
throw new BeanDefinitionStoreException("Only one enable publisher definition " +
|
||||
"(@EnablePublisher or <annotation-config>) can be declared in the application context.");
|
||||
}
|
||||
}
|
||||
|
||||
private PublisherAnnotationBeanPostProcessor createPublisherAnnotationBeanPostProcessor(
|
||||
@Nullable Map<String, Object> annotationAttributes, @Nullable ConfigurableBeanFactory beanFactory) {
|
||||
|
||||
PublisherAnnotationBeanPostProcessor postProcessor = new PublisherAnnotationBeanPostProcessor();
|
||||
String defaultChannel =
|
||||
annotationAttributes == null
|
||||
? (String) AnnotationUtils.getDefaultValue(EnablePublisher.class)
|
||||
: (String) annotationAttributes.get("defaultChannel");
|
||||
if (StringUtils.hasText(defaultChannel)) {
|
||||
if (beanFactory != null) {
|
||||
defaultChannel = beanFactory.resolveEmbeddedValue(defaultChannel);
|
||||
}
|
||||
postProcessor.setDefaultChannelName(defaultChannel);
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info("Setting '@Publisher' default-output-channel to '" + defaultChannel + "'.");
|
||||
}
|
||||
}
|
||||
if (annotationAttributes != null) {
|
||||
String proxyTargetClass = annotationAttributes.get("proxyTargetClass").toString();
|
||||
if (beanFactory != null) {
|
||||
proxyTargetClass = beanFactory.resolveEmbeddedValue(proxyTargetClass);
|
||||
}
|
||||
postProcessor.setProxyTargetClass(Boolean.parseBoolean(proxyTargetClass));
|
||||
|
||||
String order = annotationAttributes.get("order").toString();
|
||||
if (beanFactory != null) {
|
||||
order = beanFactory.resolveEmbeddedValue(order);
|
||||
}
|
||||
postProcessor.setOrder(Integer.parseInt(order));
|
||||
}
|
||||
return postProcessor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -21,9 +21,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.ChannelInitializer;
|
||||
import org.springframework.integration.config.IntegrationRegistrar;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.context.IntegrationProperties;
|
||||
|
||||
/**
|
||||
* Base class for NamespaceHandlers that registers a BeanFactoryPostProcessor
|
||||
@@ -41,10 +49,42 @@ public abstract class AbstractIntegrationNamespaceHandler extends NamespaceHandl
|
||||
@Override
|
||||
public final BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
if (!this.initialized.getAndSet(true)) {
|
||||
IntegrationRegistrar integrationRegistrar = new IntegrationRegistrar();
|
||||
integrationRegistrar.registerBeanDefinitions(null, parserContext.getRegistry());
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
new IntegrationRegistrar().registerBeanDefinitions(null, registry);
|
||||
registerImplicitChannelCreator(registry);
|
||||
}
|
||||
return super.parse(element, parserContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will auto-register a ChannelInitializer which could also be overridden by the user
|
||||
* by simply registering a ChannelInitializer {@code <bean>} with its {@code autoCreate} property
|
||||
* set to false to suppress channel creation.
|
||||
* It will also register a ChannelInitializer$AutoCreateCandidatesCollector
|
||||
* which simply collects candidate channel names.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private static void registerImplicitChannelCreator(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.CHANNEL_INITIALIZER_BEAN_NAME)) {
|
||||
String channelsAutoCreateExpression =
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.CHANNELS_AUTOCREATE);
|
||||
BeanDefinitionBuilder channelDef = BeanDefinitionBuilder.genericBeanDefinition(ChannelInitializer.class)
|
||||
.addPropertyValue("autoCreate", channelsAutoCreateExpression);
|
||||
BeanDefinitionHolder channelCreatorHolder = new BeanDefinitionHolder(channelDef.getBeanDefinition(),
|
||||
IntegrationContextUtils.CHANNEL_INITIALIZER_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(channelCreatorHolder, registry);
|
||||
}
|
||||
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder channelRegistryBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ChannelInitializer.AutoCreateCandidatesCollector.class);
|
||||
channelRegistryBuilder.addConstructorArgValue(new ManagedSet<String>());
|
||||
channelRegistryBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
BeanDefinitionHolder channelRegistryHolder =
|
||||
new BeanDefinitionHolder(channelRegistryBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(channelRegistryHolder, registry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -22,16 +22,20 @@ import java.util.Map;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.EnablePublisher;
|
||||
import org.springframework.integration.config.IntegrationRegistrar;
|
||||
import org.springframework.integration.config.PublisherRegistrar;
|
||||
import org.springframework.integration.config.annotation.AnnotationMetadataAdapter;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* Parser for the <annotation-config> element of the integration namespace.
|
||||
* Just delegate the real configuration to the {@link IntegrationRegistrar}.
|
||||
* Parser for the {@code <annotation-config>} element of the integration namespace.
|
||||
* Delegates the real configuration to the {@link IntegrationRegistrar}.
|
||||
* If {@code <enable-publisher>} sub-element is present, the {@link PublisherRegistrar}
|
||||
* is called, too.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
@@ -40,9 +44,15 @@ import org.springframework.util.xml.DomUtils;
|
||||
public class AnnotationConfigParser implements BeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(final Element element, ParserContext parserContext) {
|
||||
new IntegrationRegistrar().registerBeanDefinitions(new ExtendedAnnotationMetadata(element),
|
||||
parserContext.getRegistry());
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
ExtendedAnnotationMetadata importingClassMetadata = new ExtendedAnnotationMetadata(element);
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
new IntegrationRegistrar()
|
||||
.registerBeanDefinitions(importingClassMetadata, registry);
|
||||
if (DomUtils.getChildElementByTagName(element, "enable-publisher") != null) {
|
||||
new PublisherRegistrar()
|
||||
.registerBeanDefinitions(importingClassMetadata, registry);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -3106,9 +3106,6 @@ public abstract class BaseIntegrationFlowDefinition<B extends BaseIntegrationFlo
|
||||
|
||||
public static final class ReplyProducerCleaner implements DestructionAwareBeanPostProcessor {
|
||||
|
||||
private ReplyProducerCleaner() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresDestruction(Object bean) {
|
||||
return bean instanceof MessageProducer &&
|
||||
|
||||
@@ -63,7 +63,7 @@ public abstract class ConsumerEndpointSpec<S extends ConsumerEndpointSpec<S, H>,
|
||||
protected final List<Advice> adviceChain = new LinkedList<>(); // NOSONAR final
|
||||
|
||||
protected ConsumerEndpointSpec(H messageHandler) {
|
||||
super(messageHandler);
|
||||
super(messageHandler, new ConsumerEndpointFactoryBean());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -20,10 +20,10 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -44,20 +44,18 @@ import reactor.util.function.Tuples;
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public abstract class EndpointSpec<S extends EndpointSpec<S, F, H>, F extends BeanNameAware, H>
|
||||
public abstract class EndpointSpec<S extends EndpointSpec<S, F, H>, F extends BeanNameAware & FactoryBean<? extends AbstractEndpoint>, H>
|
||||
extends IntegrationComponentSpec<S, Tuple2<F, H>>
|
||||
implements ComponentsRegistration {
|
||||
|
||||
protected final Map<Object, String> componentsToRegister = new LinkedHashMap<>(); // NOSONAR final
|
||||
|
||||
protected H handler; // NOSONAR final
|
||||
protected final F endpointFactoryBean; // NOSONAR final
|
||||
|
||||
protected F endpointFactoryBean; // NOSONAR final
|
||||
protected H handler; // NOSONAR
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected EndpointSpec(H handler) {
|
||||
Class<?> fClass = ResolvableType.forClass(this.getClass()).as(EndpointSpec.class).resolveGenerics()[1];
|
||||
this.endpointFactoryBean = (F) BeanUtils.instantiateClass(fClass);
|
||||
protected EndpointSpec(H handler, F endpointFactoryBean) {
|
||||
this.endpointFactoryBean = endpointFactoryBean;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -26,8 +26,8 @@ import org.springframework.integration.channel.FluxMessageChannel;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.dsl.support.FixedSubscriberChannelPrototype;
|
||||
import org.springframework.integration.dsl.support.MessageChannelReference;
|
||||
import org.springframework.integration.endpoint.AbstractMessageSource;
|
||||
import org.springframework.integration.endpoint.MessageProducerSupport;
|
||||
import org.springframework.integration.endpoint.MethodInvokingMessageSource;
|
||||
import org.springframework.integration.gateway.MessagingGatewaySupport;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -160,10 +160,19 @@ public final class IntegrationFlows {
|
||||
Consumer<SourcePollingChannelAdapterSpec> endpointConfigurer) {
|
||||
|
||||
Assert.notNull(messageSource, "'messageSource' must not be null");
|
||||
MethodInvokingMessageSource methodInvokingMessageSource = new MethodInvokingMessageSource();
|
||||
methodInvokingMessageSource.setObject(messageSource);
|
||||
methodInvokingMessageSource.setMethodName("get");
|
||||
return from(methodInvokingMessageSource, endpointConfigurer);
|
||||
return from(new AbstractMessageSource<Object>() {
|
||||
|
||||
@Override
|
||||
protected Object doReceive() {
|
||||
return messageSource.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "inbound-channel-adapter";
|
||||
}
|
||||
|
||||
}, endpointConfigurer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -29,7 +29,7 @@ public class SourcePollingChannelAdapterSpec extends
|
||||
EndpointSpec<SourcePollingChannelAdapterSpec, SourcePollingChannelAdapterFactoryBean, MessageSource<?>> {
|
||||
|
||||
protected SourcePollingChannelAdapterSpec(MessageSource<?> messageSource) {
|
||||
super(messageSource);
|
||||
super(messageSource, new SourcePollingChannelAdapterFactoryBean());
|
||||
this.endpointFactoryBean.setSource(messageSource);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2019 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -60,11 +60,13 @@ public class DslIntegrationConfigurationInitializer implements IntegrationConfig
|
||||
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) configurableListableBeanFactory;
|
||||
if (!registry.containsBeanDefinition(INTEGRATION_FLOW_BPP_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(INTEGRATION_FLOW_BPP_BEAN_NAME,
|
||||
new RootBeanDefinition(IntegrationFlowBeanPostProcessor.class));
|
||||
new RootBeanDefinition(IntegrationFlowBeanPostProcessor.class,
|
||||
IntegrationFlowBeanPostProcessor::new));
|
||||
registry.registerBeanDefinition(INTEGRATION_FLOW_CONTEXT_BEAN_NAME,
|
||||
new RootBeanDefinition(StandardIntegrationFlowContext.class));
|
||||
new RootBeanDefinition(StandardIntegrationFlowContext.class, StandardIntegrationFlowContext::new));
|
||||
registry.registerBeanDefinition(INTEGRATION_FLOW_REPLY_PRODUCER_CLEANER_BEAN_NAME,
|
||||
new RootBeanDefinition(IntegrationFlowDefinition.ReplyProducerCleaner.class));
|
||||
new RootBeanDefinition(IntegrationFlowDefinition.ReplyProducerCleaner.class,
|
||||
IntegrationFlowDefinition.ReplyProducerCleaner::new));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2019 the original author or authors.
|
||||
* Copyright 2015-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.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Method interceptor to invoke default methods on the repository proxy.
|
||||
* Method interceptor to invoke default methods on the gateway proxy.
|
||||
*
|
||||
* The copy of {@code DefaultMethodInvokingMethodInterceptor} from Spring Data Commons.
|
||||
*
|
||||
|
||||
@@ -37,7 +37,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
*
|
||||
* @since 5.5
|
||||
*/
|
||||
class JsonNodeWrapperToJsonNodeConverter implements GenericConverter {
|
||||
public class JsonNodeWrapperToJsonNodeConverter implements GenericConverter {
|
||||
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -26,7 +26,6 @@ import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -38,14 +37,13 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
|
||||
/**
|
||||
* Jackson 2 JSON-processor (@link https://github.com/FasterXML)
|
||||
* {@linkplain JsonObjectMapper} implementation.
|
||||
* Delegates <code>toJson</code> and <code>fromJson</code>
|
||||
* Delegates {@link #toJson} and {@link #fromJson}
|
||||
* to the {@linkplain com.fasterxml.jackson.databind.ObjectMapper}
|
||||
* <p>
|
||||
* It customizes Jackson's default properties with the following ones:
|
||||
@@ -66,7 +64,20 @@ import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
*/
|
||||
public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<JsonNode, JsonParser, JavaType> {
|
||||
|
||||
private static final String UNUSED = "unused";
|
||||
private static final ClassLoader CLASS_LOADER = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private static final boolean JDK8_MODULE_PRESENT =
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.datatype.jdk8.Jdk8Module", CLASS_LOADER);
|
||||
|
||||
private static final boolean JAVA_TIME_MODULE_PRESENT =
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", CLASS_LOADER);
|
||||
|
||||
private static final boolean JODA_MODULE_PRESENT =
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.datatype.joda.JodaModule", CLASS_LOADER);
|
||||
|
||||
private static final boolean KOTLIN_MODULE_PRESENT =
|
||||
ClassUtils.isPresent("kotlin.Unit", CLASS_LOADER) &&
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.module.kotlin.KotlinModule", CLASS_LOADER);
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@@ -185,58 +196,48 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<Js
|
||||
return this.objectMapper.constructType(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerWellKnownModulesIfAvailable() {
|
||||
try {
|
||||
Class<? extends Module> jdk7Module = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.jdk7.Jdk7Module", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(jdk7Module));
|
||||
}
|
||||
catch (@SuppressWarnings(UNUSED) ClassNotFoundException ex) {
|
||||
// jackson-datatype-jdk7 not available
|
||||
if (JDK8_MODULE_PRESENT) {
|
||||
this.objectMapper.registerModule(Jdk8ModuleProvider.module);
|
||||
}
|
||||
|
||||
try {
|
||||
Class<? extends Module> jdk8Module = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.jdk8.Jdk8Module", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(jdk8Module));
|
||||
}
|
||||
catch (@SuppressWarnings(UNUSED) ClassNotFoundException ex) {
|
||||
// jackson-datatype-jdk8 not available
|
||||
if (JAVA_TIME_MODULE_PRESENT) {
|
||||
this.objectMapper.registerModule(JavaTimeModuleProvider.module);
|
||||
}
|
||||
|
||||
try {
|
||||
Class<? extends Module> javaTimeModule = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(javaTimeModule));
|
||||
}
|
||||
catch (@SuppressWarnings(UNUSED) ClassNotFoundException ex) {
|
||||
// jackson-datatype-jsr310 not available
|
||||
if (JODA_MODULE_PRESENT) {
|
||||
this.objectMapper.registerModule(JodaModuleProvider.module);
|
||||
}
|
||||
|
||||
// Joda-Time present?
|
||||
if (ClassUtils.isPresent("org.joda.time.LocalDate", getClassLoader())) {
|
||||
try {
|
||||
Class<? extends Module> jodaModule = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.joda.JodaModule", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(jodaModule));
|
||||
}
|
||||
catch (@SuppressWarnings(UNUSED) ClassNotFoundException ex) {
|
||||
// jackson-datatype-joda not available
|
||||
}
|
||||
}
|
||||
|
||||
// Kotlin present?
|
||||
if (ClassUtils.isPresent("kotlin.Unit", getClassLoader())) {
|
||||
try {
|
||||
Class<? extends Module> kotlinModule = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.module.kotlin.KotlinModule", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(kotlinModule));
|
||||
}
|
||||
catch (@SuppressWarnings(UNUSED) ClassNotFoundException ex) {
|
||||
//jackson-module-kotlin not available
|
||||
}
|
||||
if (KOTLIN_MODULE_PRESENT) {
|
||||
this.objectMapper.registerModule(KotlinModuleProvider.module);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Jdk8ModuleProvider {
|
||||
|
||||
static final com.fasterxml.jackson.databind.Module module = new com.fasterxml.jackson.datatype.jdk8.Jdk8Module();
|
||||
|
||||
}
|
||||
|
||||
private static final class JavaTimeModuleProvider {
|
||||
|
||||
static final com.fasterxml.jackson.databind.Module module =
|
||||
new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule();
|
||||
|
||||
}
|
||||
|
||||
private static final class JodaModuleProvider {
|
||||
|
||||
static final com.fasterxml.jackson.databind.Module module = new com.fasterxml.jackson.datatype.joda.JodaModule();
|
||||
|
||||
}
|
||||
|
||||
private static final class KotlinModuleProvider {
|
||||
|
||||
static final com.fasterxml.jackson.databind.Module module =
|
||||
new com.fasterxml.jackson.module.kotlin.KotlinModule();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
|
||||
<message-history tracked-components="publishedChannel,input,annotationTestService*"/>
|
||||
|
||||
<annotation-config>
|
||||
<enable-publisher default-publisher-channel="publishedChannel" proxy-target-class="true" order="2147483646"/>
|
||||
</annotation-config>
|
||||
|
||||
<channel-interceptor pattern="none">
|
||||
<wire-tap channel="bar" />
|
||||
</channel-interceptor>
|
||||
|
||||
@@ -554,11 +554,11 @@ public class EnableIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void testIntegrationConverter() {
|
||||
this.numberChannel.send(new GenericMessage<Integer>(10));
|
||||
this.numberChannel.send(new GenericMessage<Boolean>(true));
|
||||
this.numberChannel.send(new GenericMessage<>(10));
|
||||
this.numberChannel.send(new GenericMessage<>(true));
|
||||
assertThat(this.testConverter.getInvoked()).isGreaterThan(0);
|
||||
|
||||
assertThat(this.bytesChannel.send(new GenericMessage<byte[]>("foo".getBytes()))).isTrue();
|
||||
assertThat(this.bytesChannel.send(new GenericMessage<>("foo".getBytes()))).isTrue();
|
||||
assertThat(this.bytesChannel.send(new GenericMessage<>(MutableMessageBuilder.withPayload("").build())))
|
||||
.isTrue();
|
||||
|
||||
@@ -1046,7 +1046,7 @@ public class EnableIntegrationTests {
|
||||
@EnableIntegration
|
||||
@ImportResource("classpath:org/springframework/integration/configuration/EnableIntegrationTests-context.xml")
|
||||
@EnableMessageHistory("${message.history.tracked.components}")
|
||||
@EnablePublisher(defaultChannel = "publishedChannel")
|
||||
@EnablePublisher(defaultChannel = "publishedChannel", proxyTargetClass = true, order = 2147483646)
|
||||
@EnableAsync
|
||||
public static class ContextConfiguration2 {
|
||||
|
||||
@@ -1069,7 +1069,7 @@ public class EnableIntegrationTests {
|
||||
|
||||
@Bean
|
||||
public AtomicReference<Thread> asyncAnnotationProcessThread() {
|
||||
return new AtomicReference<Thread>();
|
||||
return new AtomicReference<>();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.integration.dsl.ComponentsRegistration;
|
||||
import org.springframework.integration.dsl.MessageHandlerSpec;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
@@ -312,9 +311,10 @@ public abstract class BaseHttpMessageHandlerSpec<S extends BaseHttpMessageHandle
|
||||
}
|
||||
|
||||
/**
|
||||
* The flag to extract a body of the {@link ResponseEntity} for reply message payload.
|
||||
* Defaults to true.
|
||||
* @param extractResponseBody produce a reply message with a whole {@link ResponseEntity} or just its body.
|
||||
* The flag to extract a body of the {@link org.springframework.http.ResponseEntity}
|
||||
* for reply message payload. Defaults to true.
|
||||
* @param extractResponseBody produce a reply message with a whole
|
||||
* {@link org.springframework.http.ResponseEntity} or just its body.
|
||||
* @return the current Spec.
|
||||
* @since 5.5
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user