INT-4517: Refactor beans in IntegrationRegistrar (#2537)
* INT-4517: Refactor beans in IntegrationRegistrar JIRA: https://jira.spring.io/browse/INT-4517 The `IntegrationRegistrar` populates beans into the application context too early and when the `allowBeanDefinitionsOverride` is disabled we end up with the `BeanDefinitionOverrideException` just because end-user beans are applied later. * Move most of the bean definitions which can be overridden in the target application from the `IntegrationRegistrar` into the `DefaultConfiguringBeanFactoryPostProcessor` * Revise their registration logic to be sure that some of them are registered only once in the parent context nad others are registered in the child context as well * Refactor a `DslIntegrationConfigurationInitializer` do not register an `IntegrationFlowDefinition.ReplyProducerCleaner` in the child context one more time: it doesn't bring any local store within the current child context * Introduce a `NoBeansOverrideAnnotationConfigContextLoader` in tests to ensure that in some test-cases we disallow an `allowBeanDefinitionsOverride` as it is now in Spring Boot since it is enabled by default in the Spring Framework * Revernt DslIntegrationConfigurationInitializer changes Regsiter all the required infrastructure beans in all the application contexts to avoid class loader issue for `static` store access
This commit is contained in:
committed by
Gary Russell
parent
60db7bc159
commit
5e47a6a9c4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 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,156 +16,483 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
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.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.integration.channel.DefaultHeaderChannelRegistry;
|
||||
import org.springframework.integration.channel.MessagePublishingErrorHandler;
|
||||
import org.springframework.integration.channel.NullChannel;
|
||||
import org.springframework.integration.channel.PublishSubscribeChannel;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.context.IntegrationProperties;
|
||||
import org.springframework.integration.handler.LoggingHandler;
|
||||
import org.springframework.integration.handler.support.CollectionArgumentResolver;
|
||||
import org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder;
|
||||
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.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.SmartLifecycleRoleController;
|
||||
import org.springframework.integration.support.converter.ConfigurableCompositeMessageConverter;
|
||||
import org.springframework.integration.support.converter.DefaultDatatypeChannelMessageConverter;
|
||||
import org.springframework.integration.support.json.JacksonPresent;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import org.springframework.messaging.converter.CompositeMessageConverter;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A {@link BeanFactoryPostProcessor} implementation that provides default beans for the error handling and task
|
||||
* scheduling if those beans have not already been explicitly defined within the registry. It also registers a single
|
||||
* null channel with the bean name "nullChannel".
|
||||
* A {@link BeanFactoryPostProcessor} implementation that registers bean definitions
|
||||
* for many infrastructure components with their default configurations.
|
||||
* All of them can be overridden using particular bean names.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @see IntegrationContextUtils
|
||||
*/
|
||||
class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
|
||||
class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProcessor, BeanClassLoaderAware {
|
||||
|
||||
private static final String ERROR_LOGGER_BEAN_NAME = "_org.springframework.integration.errorLogger";
|
||||
private static final Log logger = LogFactory.getLog(DefaultConfiguringBeanFactoryPostProcessor.class);
|
||||
|
||||
private final static IntegrationConverterInitializer INTEGRATION_CONVERTER_INITIALIZER =
|
||||
new IntegrationConverterInitializer();
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
private static final Set<Integer> registriesProcessed = new HashSet<>();
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private BeanDefinitionRegistry registry;
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (beanFactory instanceof BeanDefinitionRegistry) {
|
||||
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
|
||||
this.registerNullChannel(registry);
|
||||
if (!beanFactory.containsBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)) {
|
||||
this.registerErrorChannel(registry);
|
||||
}
|
||||
if (!beanFactory.containsBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)) {
|
||||
this.registerTaskScheduler(registry);
|
||||
}
|
||||
this.registerIdGeneratorConfigurer(registry);
|
||||
this.beanFactory = beanFactory;
|
||||
this.registry = (BeanDefinitionRegistry) beanFactory;
|
||||
|
||||
registerNullChannel();
|
||||
registerErrorChannel();
|
||||
registerIntegrationEvaluationContext();
|
||||
registerTaskScheduler();
|
||||
registerIdGeneratorConfigurer();
|
||||
registerIntegrationProperties();
|
||||
registerBuiltInBeans();
|
||||
registerRoleController();
|
||||
registerMessageBuilderFactory();
|
||||
registerHeaderChannelRegistry();
|
||||
registerGlobalChannelInterceptorProcessor();
|
||||
registerDefaultDatatypeChannelMessageConverter();
|
||||
registerArgumentResolverMessageConverter();
|
||||
registerArgumentResolvers();
|
||||
registerListCapableArgumentResolvers();
|
||||
}
|
||||
else if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn("BeanFactory is not a BeanDefinitionRegistry. The default '"
|
||||
+ IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME + "' and '"
|
||||
+ IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME + "' cannot be configured."
|
||||
+ " Also, any custom IdGenerator implementation configured in this BeanFactory"
|
||||
+ " will not be recognized.");
|
||||
else if (logger.isWarnEnabled()) {
|
||||
logger.warn("BeanFactory is not a BeanDefinitionRegistry. " +
|
||||
"The default Spring Integration infrastructure beans are not going to be registered");
|
||||
}
|
||||
}
|
||||
|
||||
private void registerInfrastructureBean(BeanDefinitionRegistry registry, String className) {
|
||||
String[] definitionNames = registry.getBeanDefinitionNames();
|
||||
for (String definitionName : definitionNames) {
|
||||
BeanDefinition definition = registry.getBeanDefinition(definitionName);
|
||||
if (className.equals(definition.getBeanClassName())) {
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info(className + " is already registered and will be used");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(className);
|
||||
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
|
||||
}
|
||||
|
||||
private void registerIdGeneratorConfigurer(BeanDefinitionRegistry registry) {
|
||||
registerInfrastructureBean(registry, "org.springframework.integration.config.IdGeneratorConfigurer");
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a null channel in the given BeanDefinitionRegistry. The bean name is defined by the constant
|
||||
* {@link IntegrationContextUtils#NULL_CHANNEL_BEAN_NAME}.
|
||||
* Register a null channel in the application context.
|
||||
* The bean name is defined by the constant {@link IntegrationContextUtils#NULL_CHANNEL_BEAN_NAME}.
|
||||
*/
|
||||
private void registerNullChannel(BeanDefinitionRegistry registry) {
|
||||
if (registry.containsBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) {
|
||||
BeanDefinition nullChannelDefinition = registry.getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
|
||||
if (NullChannel.class.getName().equals(nullChannelDefinition.getBeanClassName())) {
|
||||
return;
|
||||
private void registerNullChannel() {
|
||||
if (this.beanFactory.containsBean(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) {
|
||||
BeanDefinition nullChannelDefinition = null;
|
||||
if (this.beanFactory.containsBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) {
|
||||
nullChannelDefinition =
|
||||
this.beanFactory.getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
nullChannelDefinition =
|
||||
((BeanDefinitionRegistry) this.beanFactory.getParentBeanFactory())
|
||||
.getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
|
||||
}
|
||||
if (!NullChannel.class.getName().equals(nullChannelDefinition.getBeanClassName())) {
|
||||
throw new IllegalStateException("The bean name '" + IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME
|
||||
+ "' is reserved.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
RootBeanDefinition nullChannelDef = new RootBeanDefinition();
|
||||
nullChannelDef.setBeanClassName(IntegrationConfigUtils.BASE_PACKAGE + ".channel.NullChannel");
|
||||
BeanDefinitionHolder nullChannelHolder = new BeanDefinitionHolder(nullChannelDef,
|
||||
IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(nullChannelHolder, registry);
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME,
|
||||
new RootBeanDefinition(NullChannel.class));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an error channel in the given BeanDefinitionRegistry.
|
||||
* Register an error channel in the application context.
|
||||
* The bean name is defined by the constant {@link IntegrationContextUtils#ERROR_CHANNEL_BEAN_NAME}.
|
||||
* Also a {@link IntegrationContextUtils#ERROR_LOGGER_BEAN_NAME} is registered as a subscriber for this
|
||||
* error channel.
|
||||
*/
|
||||
private void registerErrorChannel(BeanDefinitionRegistry registry) {
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info("No bean named '" + IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME +
|
||||
"' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.");
|
||||
private void registerErrorChannel() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("No bean named '" + IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME +
|
||||
"' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.");
|
||||
}
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME,
|
||||
new RootBeanDefinition(PublishSubscribeChannel.class));
|
||||
|
||||
BeanDefinition loggingHandler =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(LoggingHandler.class)
|
||||
.addConstructorArgValue("ERROR")
|
||||
.getBeanDefinition();
|
||||
|
||||
String errorLoggerBeanName =
|
||||
IntegrationContextUtils.ERROR_LOGGER_BEAN_NAME + IntegrationConfigUtils.HANDLER_ALIAS_SUFFIX;
|
||||
this.registry.registerBeanDefinition(errorLoggerBeanName, loggingHandler);
|
||||
|
||||
BeanDefinitionBuilder loggingEndpointBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ConsumerEndpointFactoryBean.class)
|
||||
.addPropertyReference("handler", errorLoggerBeanName)
|
||||
.addPropertyValue("inputChannelName", IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME);
|
||||
|
||||
BeanComponentDefinition componentDefinition =
|
||||
new BeanComponentDefinition(loggingEndpointBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.ERROR_LOGGER_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(componentDefinition, this.registry);
|
||||
}
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME,
|
||||
new RootBeanDefinition(PublishSubscribeChannel.class));
|
||||
|
||||
BeanDefinition loggingHandler =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(LoggingHandler.class).addConstructorArgValue("ERROR")
|
||||
.getBeanDefinition();
|
||||
|
||||
String errorLoggerBeanName = ERROR_LOGGER_BEAN_NAME + IntegrationConfigUtils.HANDLER_ALIAS_SUFFIX;
|
||||
registry.registerBeanDefinition(errorLoggerBeanName, loggingHandler);
|
||||
|
||||
BeanDefinitionBuilder loggingEndpointBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ConsumerEndpointFactoryBean.class)
|
||||
.addPropertyReference("handler", errorLoggerBeanName)
|
||||
.addPropertyValue("inputChannelName", IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME);
|
||||
|
||||
BeanComponentDefinition componentDefinition =
|
||||
new BeanComponentDefinition(loggingEndpointBuilder.getBeanDefinition(), ERROR_LOGGER_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(componentDefinition, registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a TaskScheduler in the given BeanDefinitionRegistry.
|
||||
* Register {@link IntegrationEvaluationContextFactoryBean}
|
||||
* and {@link IntegrationSimpleEvaluationContextFactoryBean} beans, if necessary.
|
||||
*/
|
||||
private void registerTaskScheduler(BeanDefinitionRegistry registry) {
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info("No bean named '" + IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME +
|
||||
"' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.");
|
||||
}
|
||||
BeanDefinition scheduler = BeanDefinitionBuilder.genericBeanDefinition(ThreadPoolTaskScheduler.class)
|
||||
.addPropertyValue("poolSize", IntegrationProperties.getExpressionFor(IntegrationProperties.TASK_SCHEDULER_POOL_SIZE))
|
||||
.addPropertyValue("threadNamePrefix", "task-scheduler-")
|
||||
.addPropertyValue("rejectedExecutionHandler", new CallerRunsPolicy())
|
||||
.addPropertyValue("errorHandler", new RootBeanDefinition(MessagePublishingErrorHandler.class))
|
||||
.getBeanDefinition();
|
||||
private void registerIntegrationEvaluationContext() {
|
||||
if (!this.registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder integrationEvaluationContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationEvaluationContextFactoryBean.class);
|
||||
integrationEvaluationContextBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, scheduler);
|
||||
BeanDefinitionHolder integrationEvaluationContextHolder =
|
||||
new BeanDefinitionHolder(integrationEvaluationContextBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME);
|
||||
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, this.registry);
|
||||
}
|
||||
|
||||
if (!this.registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME)) {
|
||||
|
||||
BeanDefinitionBuilder integrationEvaluationContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationSimpleEvaluationContextFactoryBean.class);
|
||||
integrationEvaluationContextBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
BeanDefinitionHolder integrationEvaluationContextHolder =
|
||||
new BeanDefinitionHolder(integrationEvaluationContextBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME);
|
||||
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, this.registry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an {@link IdGeneratorConfigurer} in the application context.
|
||||
*/
|
||||
private void registerIdGeneratorConfigurer() {
|
||||
Class<?> clazz = IdGeneratorConfigurer.class;
|
||||
String className = clazz.getName();
|
||||
String[] definitionNames = this.registry.getBeanDefinitionNames();
|
||||
for (String definitionName : definitionNames) {
|
||||
BeanDefinition definition = this.registry.getBeanDefinition(definitionName);
|
||||
if (className.equals(definition.getBeanClassName())) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(className + " is already registered and will be used");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(clazz);
|
||||
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, this.registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link ThreadPoolTaskScheduler} bean in the application context.
|
||||
*/
|
||||
private void registerTaskScheduler() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("No bean named '" + IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME +
|
||||
"' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.");
|
||||
}
|
||||
BeanDefinition scheduler = BeanDefinitionBuilder.genericBeanDefinition(ThreadPoolTaskScheduler.class)
|
||||
.addPropertyValue("poolSize", IntegrationProperties
|
||||
.getExpressionFor(IntegrationProperties.TASK_SCHEDULER_POOL_SIZE))
|
||||
.addPropertyValue("threadNamePrefix", "task-scheduler-")
|
||||
.addPropertyValue("rejectedExecutionHandler", new CallerRunsPolicy())
|
||||
.addPropertyValue("errorHandler", new RootBeanDefinition(MessagePublishingErrorHandler.class))
|
||||
.getBeanDefinition();
|
||||
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, scheduler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an {@code integrationGlobalProperties} bean if necessary.
|
||||
*/
|
||||
private void registerIntegrationProperties() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME)) {
|
||||
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(this.classLoader);
|
||||
try {
|
||||
Resource[] defaultResources =
|
||||
resourceResolver.getResources("classpath*:META-INF/spring.integration.default.properties");
|
||||
Resource[] userResources =
|
||||
resourceResolver.getResources("classpath*:META-INF/spring.integration.properties");
|
||||
|
||||
List<Resource> resources = new LinkedList<>(Arrays.asList(defaultResources));
|
||||
resources.addAll(Arrays.asList(userResources));
|
||||
|
||||
BeanDefinitionBuilder integrationPropertiesBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(PropertiesFactoryBean.class)
|
||||
.addPropertyValue("locations", resources);
|
||||
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME,
|
||||
integrationPropertiesBuilder.getBeanDefinition());
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.warn("Cannot load 'spring.integration.properties' Resources.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@code jsonPath} and {@code xpath} SpEL-function beans, if necessary.
|
||||
*/
|
||||
private void registerBuiltInBeans() {
|
||||
int registryId = System.identityHashCode(this.registry);
|
||||
|
||||
String jsonPathBeanName = "jsonPath";
|
||||
if (!this.beanFactory.containsBean(jsonPathBeanName) && !registriesProcessed.contains(registryId)) {
|
||||
Class<?> jsonPathClass = null;
|
||||
try {
|
||||
jsonPathClass = ClassUtils.forName("com.jayway.jsonpath.JsonPath", this.classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
logger.debug("The '#jsonPath' SpEL function cannot be registered: " +
|
||||
"there is no jayway json-path.jar on the classpath.");
|
||||
}
|
||||
|
||||
if (jsonPathClass != null) {
|
||||
try {
|
||||
ClassUtils.forName("com.jayway.jsonpath.Predicate", this.classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
jsonPathClass = null;
|
||||
logger.warn("The '#jsonPath' SpEL function cannot be registered. " +
|
||||
"An old json-path.jar version is detected in the classpath." +
|
||||
"At least 1.2.0 is required; see version information at: " +
|
||||
"https://github.com/jayway/JsonPath/releases", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonPathClass != null) {
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(this.registry, jsonPathBeanName,
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".json.JsonPathUtils", "evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
String xpathBeanName = "xpath";
|
||||
if (!this.beanFactory.containsBean(xpathBeanName) && !registriesProcessed.contains(registryId)) {
|
||||
Class<?> xpathClass = null;
|
||||
try {
|
||||
xpathClass = ClassUtils.forName(IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils",
|
||||
this.classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
logger.debug("SpEL function '#xpath' isn't registered: " +
|
||||
"there is no spring-integration-xml.jar on the classpath.");
|
||||
}
|
||||
|
||||
if (xpathClass != null) {
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(this.registry, xpathBeanName,
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils", "evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.beanFactory.containsBean(
|
||||
IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME) &&
|
||||
!registriesProcessed.contains(registryId) && JacksonPresent.isJackson2Present()) {
|
||||
|
||||
this.registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME,
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationConfigUtils.BASE_PACKAGE +
|
||||
".json.ToStringFriendlyJsonNodeToStringConverter")
|
||||
.getBeanDefinition());
|
||||
INTEGRATION_CONVERTER_INITIALIZER.registerConverter(this.registry,
|
||||
new RuntimeBeanReference(
|
||||
IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME));
|
||||
}
|
||||
|
||||
registriesProcessed.add(registryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link SmartLifecycleRoleController} if necessary.
|
||||
*/
|
||||
private void registerRoleController() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.INTEGRATION_LIFECYCLE_ROLE_CONTROLLER)) {
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(SmartLifecycleRoleController.class);
|
||||
builder.addConstructorArgValue(new ManagedList<String>());
|
||||
builder.addConstructorArgValue(new ManagedList<Lifecycle>());
|
||||
this.registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_LIFECYCLE_ROLE_CONTROLLER, builder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link DefaultMessageBuilderFactory} if necessary.
|
||||
*/
|
||||
private void registerMessageBuilderFactory() {
|
||||
if (!this.beanFactory.containsBean(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder mbfBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(DefaultMessageBuilderFactory.class)
|
||||
.addPropertyValue("readOnlyHeaders",
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.READ_ONLY_HEADERS));
|
||||
this.registry.registerBeanDefinition(
|
||||
IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME,
|
||||
mbfBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link DefaultHeaderChannelRegistry} if necessary.
|
||||
*/
|
||||
private void registerHeaderChannelRegistry() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("No bean named '" + IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME +
|
||||
"' has been explicitly defined. " +
|
||||
"Therefore, a default DefaultHeaderChannelRegistry will be created.");
|
||||
}
|
||||
BeanDefinitionBuilder schedulerBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(DefaultHeaderChannelRegistry.class);
|
||||
BeanDefinitionHolder replyChannelRegistryComponent = new BeanDefinitionHolder(
|
||||
schedulerBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(replyChannelRegistryComponent, this.registry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link GlobalChannelInterceptorProcessor} if necessary.
|
||||
*/
|
||||
private void registerGlobalChannelInterceptorProcessor() {
|
||||
if (!this.registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(GlobalChannelInterceptorProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME,
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link DefaultDatatypeChannelMessageConverter} bean if necessary.
|
||||
*/
|
||||
private void registerDefaultDatatypeChannelMessageConverter() {
|
||||
if (!this.beanFactory.containsBean(
|
||||
IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
|
||||
BeanDefinitionBuilder converterBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(DefaultDatatypeChannelMessageConverter.class);
|
||||
this.registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
converterBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link CompositeMessageConverter} for argument resolvers
|
||||
* during handler method invocation.
|
||||
*/
|
||||
private void registerArgumentResolverMessageConverter() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder converterBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ConfigurableCompositeMessageConverter.class);
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
converterBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
|
||||
* method invocation.
|
||||
*/
|
||||
private void registerArgumentResolvers() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME)) {
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
internalArgumentResolversBuilder(false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
|
||||
* method invocation for lists.
|
||||
*/
|
||||
private void registerListCapableArgumentResolvers() {
|
||||
if (!this.beanFactory.containsBean(IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME)) {
|
||||
this.registry.registerBeanDefinition(IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
internalArgumentResolversBuilder(true));
|
||||
}
|
||||
}
|
||||
|
||||
private static BeanDefinition internalArgumentResolversBuilder(boolean listCapable) {
|
||||
ManagedList<BeanDefinition> resolvers = new ManagedList<>();
|
||||
resolvers.add(new RootBeanDefinition(PayloadExpressionArgumentResolver.class));
|
||||
resolvers.add(new RootBeanDefinition(PayloadsArgumentResolver.class));
|
||||
resolvers.add(new RootBeanDefinition(MapArgumentResolver.class));
|
||||
|
||||
if (listCapable) {
|
||||
resolvers.add(
|
||||
BeanDefinitionBuilder.genericBeanDefinition(CollectionArgumentResolver.class)
|
||||
.addConstructorArgValue(true)
|
||||
.getBeanDefinition());
|
||||
}
|
||||
|
||||
return BeanDefinitionBuilder.genericBeanDefinition(HandlerMethodArgumentResolversHolder.class)
|
||||
.addConstructorArgValue(resolvers)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2018 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,16 +20,13 @@ 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.ManagedList;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.support.SmartLifecycleRoleController;
|
||||
|
||||
/**
|
||||
* Shared utility methods for Integration configuration.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public final class IntegrationConfigUtils {
|
||||
@@ -43,6 +40,7 @@ public final class IntegrationConfigUtils {
|
||||
|
||||
public static void registerSpelFunctionBean(BeanDefinitionRegistry registry, String functionId, String className,
|
||||
String methodSignature) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SpelFunctionFactoryBean.class)
|
||||
.addConstructorArgValue(className)
|
||||
.addConstructorArgValue(methodSignature);
|
||||
@@ -55,17 +53,6 @@ public final class IntegrationConfigUtils {
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
|
||||
}
|
||||
|
||||
public static void registerRoleControllerDefinitionIfNecessary(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_LIFECYCLE_ROLE_CONTROLLER)) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SmartLifecycleRoleController.class);
|
||||
builder.addConstructorArgValue(new ManagedList<String>());
|
||||
builder.addConstructorArgValue(new ManagedList<Lifecycle>());
|
||||
registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_LIFECYCLE_ROLE_CONTROLLER, builder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
private IntegrationConfigUtils() {
|
||||
}
|
||||
|
||||
|
||||
@@ -16,51 +16,19 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
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.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.integration.aop.PublisherAnnotationBeanPostProcessor;
|
||||
import org.springframework.integration.channel.DefaultHeaderChannelRegistry;
|
||||
import org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.context.IntegrationProperties;
|
||||
import org.springframework.integration.handler.support.CollectionArgumentResolver;
|
||||
import org.springframework.integration.handler.support.HandlerMethodArgumentResolversHolder;
|
||||
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.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.converter.ConfigurableCompositeMessageConverter;
|
||||
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.converter.CompositeMessageConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} implementation that configures integration infrastructure.
|
||||
@@ -70,21 +38,7 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(IntegrationRegistrar.class);
|
||||
|
||||
private final static IntegrationConverterInitializer INTEGRATION_CONVERTER_INITIALIZER =
|
||||
new IntegrationConverterInitializer();
|
||||
|
||||
private static final Set<Integer> registriesProcessed = new HashSet<>();
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
/**
|
||||
* Invoked by the framework when an @EnableIntegration annotation is encountered.
|
||||
@@ -97,22 +51,11 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
registerImplicitChannelCreator(registry);
|
||||
registerIntegrationConfigurationBeanFactoryPostProcessor(registry);
|
||||
registerIntegrationEvaluationContext(registry);
|
||||
registerIntegrationProperties(registry);
|
||||
registerHeaderChannelRegistry(registry);
|
||||
registerGlobalChannelInterceptorProcessor(registry);
|
||||
registerBuiltInBeans(registry);
|
||||
registerDefaultConfiguringBeanFactoryPostProcessor(registry);
|
||||
registerDefaultDatatypeChannelMessageConverter(registry);
|
||||
registerArgumentResolverMessageConverter(registry);
|
||||
registerArgumentResolvers(registry);
|
||||
registerListCapableArgumentResolvers(registry);
|
||||
registerIntegrationConfigurationBeanFactoryPostProcessor(registry);
|
||||
if (importingClassMetadata != null) {
|
||||
registerMessagingAnnotationPostProcessors(importingClassMetadata, registry);
|
||||
}
|
||||
registerMessageBuilderFactory(registry);
|
||||
IntegrationConfigUtils.registerRoleControllerDefinitionIfNecessary(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,182 +89,12 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@code integrationGlobalProperties} bean if necessary.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private void registerIntegrationProperties(BeanDefinitionRegistry registry) {
|
||||
boolean alreadyRegistered = false;
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry)
|
||||
.containsBean(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered =
|
||||
registry.isBeanNameInUse(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME);
|
||||
}
|
||||
if (!alreadyRegistered) {
|
||||
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(this.classLoader);
|
||||
try {
|
||||
Resource[] defaultResources =
|
||||
resourceResolver.getResources("classpath*:META-INF/spring.integration.default.properties");
|
||||
Resource[] userResources =
|
||||
resourceResolver.getResources("classpath*:META-INF/spring.integration.properties");
|
||||
|
||||
List<Resource> resources = new LinkedList<Resource>(Arrays.asList(defaultResources));
|
||||
resources.addAll(Arrays.asList(userResources));
|
||||
|
||||
BeanDefinitionBuilder integrationPropertiesBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(PropertiesFactoryBean.class)
|
||||
.addPropertyValue("locations", resources);
|
||||
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME,
|
||||
integrationPropertiesBuilder.getBeanDefinition());
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.warn("Cannot load 'spring.integration.properties' Resources.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@link IntegrationEvaluationContextFactoryBean} bean, if necessary.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private void registerIntegrationEvaluationContext(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder integrationEvaluationContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationEvaluationContextFactoryBean.class);
|
||||
integrationEvaluationContextBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
BeanDefinitionHolder integrationEvaluationContextHolder =
|
||||
new BeanDefinitionHolder(integrationEvaluationContextBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME);
|
||||
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, registry);
|
||||
}
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder integrationEvaluationContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationSimpleEvaluationContextFactoryBean.class);
|
||||
integrationEvaluationContextBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
BeanDefinitionHolder integrationEvaluationContextHolder =
|
||||
new BeanDefinitionHolder(integrationEvaluationContextBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME);
|
||||
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, registry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@code jsonPath} and {@code xpath} SpEL-function beans, if necessary.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private void registerBuiltInBeans(BeanDefinitionRegistry registry) {
|
||||
int registryId = System.identityHashCode(registry);
|
||||
|
||||
String jsonPathBeanName = "jsonPath";
|
||||
boolean alreadyRegistered = false;
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry).containsBean(jsonPathBeanName);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered = registry.isBeanNameInUse(jsonPathBeanName);
|
||||
}
|
||||
if (!alreadyRegistered && !registriesProcessed.contains(registryId)) {
|
||||
Class<?> jsonPathClass = null;
|
||||
try {
|
||||
jsonPathClass = ClassUtils.forName("com.jayway.jsonpath.JsonPath", this.classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
logger.debug("The '#jsonPath' SpEL function cannot be registered: " +
|
||||
"there is no jayway json-path.jar on the classpath.");
|
||||
}
|
||||
|
||||
if (jsonPathClass != null) {
|
||||
try {
|
||||
ClassUtils.forName("com.jayway.jsonpath.Predicate", this.classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
jsonPathClass = null;
|
||||
logger.warn("The '#jsonPath' SpEL function cannot be registered. " +
|
||||
"An old json-path.jar version is detected in the classpath." +
|
||||
"At least 1.2.0 is required; see version information at: " +
|
||||
"https://github.com/jayway/JsonPath/releases", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonPathClass != null) {
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(registry, jsonPathBeanName,
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".json.JsonPathUtils", "evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
alreadyRegistered = false;
|
||||
String xpathBeanName = "xpath";
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry).containsBean(xpathBeanName);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered = registry.isBeanNameInUse(xpathBeanName);
|
||||
}
|
||||
if (!alreadyRegistered && !registriesProcessed.contains(registryId)) {
|
||||
Class<?> xpathClass = null;
|
||||
try {
|
||||
xpathClass = ClassUtils.forName(IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils",
|
||||
this.classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
logger.debug("SpEL function '#xpath' isn't registered: " +
|
||||
"there is no spring-integration-xml.jar on the classpath.");
|
||||
}
|
||||
|
||||
if (xpathClass != null) {
|
||||
IntegrationConfigUtils.registerSpelFunctionBean(registry, xpathBeanName,
|
||||
IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils", "evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
alreadyRegistered = false;
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry)
|
||||
.containsBean(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered = registry
|
||||
.isBeanNameInUse(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME);
|
||||
}
|
||||
|
||||
if (!alreadyRegistered && !registriesProcessed.contains(registryId) && JacksonPresent.isJackson2Present()) {
|
||||
registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME,
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationConfigUtils.BASE_PACKAGE +
|
||||
".json.ToStringFriendlyJsonNodeToStringConverter")
|
||||
.getBeanDefinition());
|
||||
INTEGRATION_CONVERTER_INITIALIZER.registerConverter(registry,
|
||||
new RuntimeBeanReference(
|
||||
IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME));
|
||||
}
|
||||
|
||||
registriesProcessed.add(registryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@code DefaultConfiguringBeanFactoryPostProcessor}, if necessary.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private void registerDefaultConfiguringBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
|
||||
boolean alreadyRegistered = false;
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry)
|
||||
.containsBean(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered =
|
||||
registry.isBeanNameInUse(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
|
||||
}
|
||||
if (!alreadyRegistered) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder postProcessorBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(DefaultConfiguringBeanFactoryPostProcessor.class);
|
||||
BeanDefinitionHolder postProcessorHolder = new BeanDefinitionHolder(
|
||||
@@ -332,46 +105,18 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link DefaultHeaderChannelRegistry} in the given {@link BeanDefinitionRegistry}, if necessary.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
* Register {@link IntegrationConfigurationBeanFactoryPostProcessor}
|
||||
* to process the external Integration infrastructure.
|
||||
*/
|
||||
private void registerHeaderChannelRegistry(BeanDefinitionRegistry registry) {
|
||||
boolean alreadyRegistered = false;
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry)
|
||||
.containsBean(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered =
|
||||
registry.isBeanNameInUse(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
|
||||
}
|
||||
if (!alreadyRegistered) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("No bean named '" + IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME +
|
||||
"' has been explicitly defined. " +
|
||||
"Therefore, a default DefaultHeaderChannelRegistry will be created.");
|
||||
}
|
||||
BeanDefinitionBuilder schedulerBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(DefaultHeaderChannelRegistry.class);
|
||||
BeanDefinitionHolder replyChannelRegistryComponent = new BeanDefinitionHolder(
|
||||
schedulerBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(replyChannelRegistryComponent, registry);
|
||||
}
|
||||
}
|
||||
private void registerIntegrationConfigurationBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME)) {
|
||||
|
||||
/**
|
||||
* Register a {@link GlobalChannelInterceptorProcessor} in the given {@link BeanDefinitionRegistry}, if necessary.
|
||||
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
|
||||
*/
|
||||
private void registerGlobalChannelInterceptorProcessor(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder builder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(GlobalChannelInterceptorProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME,
|
||||
builder.getBeanDefinition());
|
||||
BeanDefinitionBuilder postProcessorBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationConfigurationBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME,
|
||||
postProcessorBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,122 +142,4 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@link IntegrationConfigurationBeanFactoryPostProcessor}
|
||||
* to process the external Integration infrastructure.
|
||||
*/
|
||||
private void registerIntegrationConfigurationBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME)) {
|
||||
|
||||
BeanDefinitionBuilder postProcessorBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationConfigurationBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME,
|
||||
postProcessorBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default datatype channel MessageConverter.
|
||||
* @param registry the registry.
|
||||
*/
|
||||
private void registerDefaultDatatypeChannelMessageConverter(BeanDefinitionRegistry registry) {
|
||||
boolean alreadyRegistered = false;
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry)
|
||||
.containsBean(IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered = registry
|
||||
.isBeanNameInUse(IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME);
|
||||
}
|
||||
if (!alreadyRegistered) {
|
||||
BeanDefinitionBuilder converterBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(DefaultDatatypeChannelMessageConverter.class);
|
||||
registry.registerBeanDefinition(
|
||||
IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
converterBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link CompositeMessageConverter} for argument resolvers
|
||||
* during handler method invocation.
|
||||
* @param registry the registry.
|
||||
*/
|
||||
private void registerArgumentResolverMessageConverter(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder converterBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(ConfigurableCompositeMessageConverter.class);
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME,
|
||||
converterBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
|
||||
* method invocation.
|
||||
* @param registry the registry.
|
||||
*/
|
||||
private void registerArgumentResolvers(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
internalArgumentResolversBuilder(false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the default {@link HandlerMethodArgumentResolversHolder} for handler
|
||||
* method invocation for lists.
|
||||
* @param registry the registry.
|
||||
*/
|
||||
private void registerListCapableArgumentResolvers(BeanDefinitionRegistry registry) {
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME)) {
|
||||
registry.registerBeanDefinition(IntegrationContextUtils.LIST_ARGUMENT_RESOLVERS_BEAN_NAME,
|
||||
internalArgumentResolversBuilder(true));
|
||||
}
|
||||
}
|
||||
|
||||
private BeanDefinition internalArgumentResolversBuilder(boolean listCapable) {
|
||||
ManagedList<BeanDefinition> resolvers = new ManagedList<>();
|
||||
resolvers.add(new RootBeanDefinition(PayloadExpressionArgumentResolver.class));
|
||||
resolvers.add(new RootBeanDefinition(PayloadsArgumentResolver.class));
|
||||
resolvers.add(new RootBeanDefinition(MapArgumentResolver.class));
|
||||
|
||||
if (listCapable) {
|
||||
resolvers.add(
|
||||
BeanDefinitionBuilder.genericBeanDefinition(CollectionArgumentResolver.class)
|
||||
.addConstructorArgValue(true)
|
||||
.getBeanDefinition());
|
||||
}
|
||||
|
||||
return BeanDefinitionBuilder.genericBeanDefinition(HandlerMethodArgumentResolversHolder.class)
|
||||
.addConstructorArgValue(resolvers)
|
||||
.getBeanDefinition();
|
||||
}
|
||||
|
||||
private void registerMessageBuilderFactory(BeanDefinitionRegistry registry) {
|
||||
boolean alreadyRegistered = false;
|
||||
if (registry instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) registry)
|
||||
.containsBean(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered = registry
|
||||
.isBeanNameInUse(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME);
|
||||
}
|
||||
if (!alreadyRegistered) {
|
||||
BeanDefinitionBuilder mbfBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(DefaultMessageBuilderFactory.class)
|
||||
.addPropertyValue("readOnlyHeaders",
|
||||
IntegrationProperties.getExpressionFor(IntegrationProperties.READ_ONLY_HEADERS));
|
||||
registry.registerBeanDefinition(
|
||||
IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME,
|
||||
mbfBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHa
|
||||
if (!this.initialized.getAndSet(true)) {
|
||||
verifySchemaVersion(element, parserContext);
|
||||
IntegrationRegistrar integrationRegistrar = new IntegrationRegistrar();
|
||||
integrationRegistrar.setBeanClassLoader(parserContext.getReaderContext().getBeanClassLoader());
|
||||
integrationRegistrar.registerBeanDefinitions(null, parserContext.getRegistry());
|
||||
}
|
||||
return this.delegate.parse(element, parserContext);
|
||||
|
||||
@@ -41,7 +41,6 @@ public class AnnotationConfigParser implements BeanDefinitionParser {
|
||||
@Override
|
||||
public BeanDefinition parse(final Element element, ParserContext parserContext) {
|
||||
IntegrationRegistrar integrationRegistrar = new IntegrationRegistrar();
|
||||
integrationRegistrar.setBeanClassLoader(parserContext.getReaderContext().getBeanClassLoader());
|
||||
|
||||
StandardAnnotationMetadata importingClassMetadata =
|
||||
new StandardAnnotationMetadata(Object.class) {
|
||||
|
||||
@@ -41,6 +41,8 @@ public abstract class IntegrationContextUtils {
|
||||
|
||||
public static final String ERROR_CHANNEL_BEAN_NAME = "errorChannel";
|
||||
|
||||
public static final String ERROR_LOGGER_BEAN_NAME = "_org.springframework.integration.errorLogger";
|
||||
|
||||
public static final String NULL_CHANNEL_BEAN_NAME = "nullChannel";
|
||||
|
||||
public static final String METADATA_STORE_BEAN_NAME = "metadataStore";
|
||||
|
||||
@@ -118,6 +118,7 @@ import org.springframework.integration.support.MutableMessageBuilder;
|
||||
import org.springframework.integration.support.SmartLifecycleRoleController;
|
||||
import org.springframework.integration.test.util.OnlyOnceTrigger;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.util.NoBeansOverrideAnnotationConfigContextLoader;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
@@ -136,7 +137,6 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
@@ -148,7 +148,7 @@ import reactor.core.publisher.Mono;
|
||||
* @author Gary Russell
|
||||
* @since 4.0
|
||||
*/
|
||||
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,
|
||||
@ContextConfiguration(loader = NoBeansOverrideAnnotationConfigContextLoader.class,
|
||||
classes = { EnableIntegrationTests.ContextConfiguration.class,
|
||||
EnableIntegrationTests.ContextConfiguration2.class })
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@@ -961,6 +961,7 @@ public class EnableIntegrationTests {
|
||||
public Integer getInvoked() {
|
||||
return invoked.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -1443,6 +1444,7 @@ public class EnableIntegrationTests {
|
||||
String phase() default "";
|
||||
|
||||
Poller[] poller() default { };
|
||||
|
||||
}
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@@ -1461,6 +1463,7 @@ public class EnableIntegrationTests {
|
||||
String phase() default "";
|
||||
|
||||
Poller[] poller() default { };
|
||||
|
||||
}
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@@ -1566,6 +1569,7 @@ public class EnableIntegrationTests {
|
||||
String phase() default "";
|
||||
|
||||
Poller[] poller() default { };
|
||||
|
||||
}
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@@ -1614,6 +1618,7 @@ public class EnableIntegrationTests {
|
||||
public @interface MyBridgeFrom {
|
||||
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
|
||||
@@ -75,6 +75,7 @@ import org.springframework.integration.store.SimpleMessageStore;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.MutableMessageBuilder;
|
||||
import org.springframework.integration.transformer.PayloadSerializingTransformer;
|
||||
import org.springframework.integration.util.NoBeansOverrideAnnotationConfigContextLoader;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
@@ -91,6 +92,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
@@ -101,6 +103,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration(loader = NoBeansOverrideAnnotationConfigContextLoader.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class IntegrationFlowTests {
|
||||
@@ -482,11 +485,13 @@ public class IntegrationFlowTests {
|
||||
public interface ControlBusGateway {
|
||||
|
||||
void send(String command);
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
public static class SupplierContextConfiguration1 {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow supplierFlow() {
|
||||
return IntegrationFlows.from(() -> "foo")
|
||||
@@ -512,15 +517,17 @@ public class IntegrationFlowTests {
|
||||
public MessageChannel suppliedChannel() {
|
||||
return MessageChannels.queue(10).get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
public static class SupplierContextConfiguration2 {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow supplierFlow2() {
|
||||
return IntegrationFlows.from(() -> "foo", c -> c.poller(Pollers.fixedDelay(100).maxMessagesPerPoll(1)))
|
||||
.<String, String>transform(p -> p.toUpperCase())
|
||||
.<String, String>transform(String::toUpperCase)
|
||||
.channel("suppliedChannel2")
|
||||
.get();
|
||||
}
|
||||
@@ -529,6 +536,7 @@ public class IntegrationFlowTests {
|
||||
public MessageChannel suppliedChannel2() {
|
||||
return MessageChannels.queue(10).get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -542,18 +550,6 @@ public class IntegrationFlowTests {
|
||||
.get();
|
||||
}
|
||||
|
||||
@Bean(name = PollerMetadata.DEFAULT_POLLER)
|
||||
public PollerMetadata poller() {
|
||||
return Pollers.fixedRate(500).get();
|
||||
}
|
||||
|
||||
@Bean(name = IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)
|
||||
public TaskScheduler taskScheduler() {
|
||||
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||
threadPoolTaskScheduler.setPoolSize(100);
|
||||
return threadPoolTaskScheduler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageChannel inputChannel() {
|
||||
return MessageChannels.direct().get();
|
||||
@@ -690,6 +686,7 @@ public class IntegrationFlowTests {
|
||||
public void handle(Object payload) {
|
||||
assertEquals(100, payload);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -856,6 +853,7 @@ public class IntegrationFlowTests {
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
return "Hello " + this.worldService.world() + " and " + requestMessage.getPayload();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Service
|
||||
@@ -864,6 +862,7 @@ public class IntegrationFlowTests {
|
||||
public String world() {
|
||||
return "World";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ import org.springframework.integration.history.MessageHistory;
|
||||
import org.springframework.integration.support.SmartLifecycleRoleController;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.transformer.MessageTransformingHandler;
|
||||
import org.springframework.integration.util.NoBeansOverrideAnnotationConfigContextLoader;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
@@ -102,7 +103,8 @@ import reactor.core.publisher.Flux;
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration(classes = ManualFlowTests.RootConfiguration.class)
|
||||
@ContextConfiguration(loader = NoBeansOverrideAnnotationConfigContextLoader.class,
|
||||
classes = ManualFlowTests.RootConfiguration.class)
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
public class ManualFlowTests {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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.util;
|
||||
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 5.1
|
||||
*/
|
||||
public class NoBeansOverrideAnnotationConfigContextLoader extends AnnotationConfigContextLoader {
|
||||
|
||||
@Override
|
||||
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
|
||||
beanFactory.setAllowBeanDefinitionOverriding(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -58,21 +57,23 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
public class UriVariableExpressionTests {
|
||||
|
||||
@Test
|
||||
public void testFromMessageWithExpressions() throws Exception {
|
||||
final AtomicReference<URI> uriHolder = new AtomicReference<URI>();
|
||||
public void testFromMessageWithExpressions() {
|
||||
final AtomicReference<URI> uriHolder = new AtomicReference<>();
|
||||
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("http://test/{foo}");
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
handler.setUriVariableExpressions(Collections.singletonMap("foo", parser.parseExpression("payload")));
|
||||
handler.setRequestFactory(new SimpleClientHttpRequestFactory() {
|
||||
|
||||
@Override
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
|
||||
uriHolder.set(uri);
|
||||
throw new RuntimeException("intentional");
|
||||
}
|
||||
|
||||
});
|
||||
handler.setBeanFactory(mock(BeanFactory.class));
|
||||
handler.afterPropertiesSet();
|
||||
Message<?> message = new GenericMessage<Object>("bar");
|
||||
Message<?> message = new GenericMessage<>("bar");
|
||||
try {
|
||||
handler.handleMessage(message);
|
||||
fail("Exception expected.");
|
||||
@@ -83,22 +84,26 @@ public class UriVariableExpressionTests {
|
||||
assertEquals("http://test/bar", uriHolder.get().toString());
|
||||
}
|
||||
|
||||
/** Test for INT-3054: Do not break if there are extra uri variables defined in the http outbound gateway. */
|
||||
/**
|
||||
* Test for INT-3054: Do not break if there are extra uri variables defined in the http outbound gateway.
|
||||
*/
|
||||
@Test
|
||||
public void testFromMessageWithSuperfluousExpressionsInt3054() throws Exception {
|
||||
final AtomicReference<URI> uriHolder = new AtomicReference<URI>();
|
||||
public void testFromMessageWithSuperfluousExpressionsInt3054() {
|
||||
final AtomicReference<URI> uriHolder = new AtomicReference<>();
|
||||
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("http://test/{foo}");
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Map<String, Expression> multipleExpressions = new HashMap<String, Expression>();
|
||||
Map<String, Expression> multipleExpressions = new HashMap<>();
|
||||
multipleExpressions.put("foo", parser.parseExpression("payload"));
|
||||
multipleExpressions.put("extra-to-be-ignored", parser.parseExpression("headers.extra"));
|
||||
handler.setUriVariableExpressions(multipleExpressions);
|
||||
handler.setRequestFactory(new SimpleClientHttpRequestFactory() {
|
||||
|
||||
@Override
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
|
||||
uriHolder.set(uri);
|
||||
throw new RuntimeException("intentional");
|
||||
}
|
||||
|
||||
});
|
||||
handler.setBeanFactory(mock(BeanFactory.class));
|
||||
handler.afterPropertiesSet();
|
||||
@@ -113,28 +118,29 @@ public class UriVariableExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt3055UriVariablesExpression() throws Exception {
|
||||
final AtomicReference<URI> uriHolder = new AtomicReference<URI>();
|
||||
public void testInt3055UriVariablesExpression() {
|
||||
final AtomicReference<URI> uriHolder = new AtomicReference<>();
|
||||
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("http://test/{foo}");
|
||||
|
||||
handler.setRequestFactory(new SimpleClientHttpRequestFactory() {
|
||||
|
||||
@Override
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
|
||||
uriHolder.set(uri);
|
||||
throw new RuntimeException("intentional");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
AbstractApplicationContext context = TestUtils.createTestApplicationContext();
|
||||
IntegrationRegistrar registrar = new IntegrationRegistrar();
|
||||
registrar.setBeanClassLoader(context.getClassLoader());
|
||||
registrar.registerBeanDefinitions(null, (BeanDefinitionRegistry) context.getBeanFactory());
|
||||
context.refresh();
|
||||
handler.setBeanFactory(context);
|
||||
handler.setUriVariablesExpression(new SpelExpressionParser().parseExpression("headers.uriVariables"));
|
||||
handler.afterPropertiesSet();
|
||||
|
||||
Map<String, Object> expressions = new HashMap<String, Object>();
|
||||
Map<String, Object> expressions = new HashMap<>();
|
||||
expressions.put("foo", "bar");
|
||||
|
||||
Map<String, ?> expressionsMap = ExpressionEvalMap.from(expressions).usingSimpleCallback().build();
|
||||
|
||||
Reference in New Issue
Block a user