diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java index 72af6bb5bd8..d51b17dccfd 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/DefaultConfiguringBeanFactoryPostProcessor.java @@ -20,20 +20,19 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Properties; 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.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.BeanDefinitionHolder; +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; @@ -42,12 +41,11 @@ 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.core.log.LogAccessor; import org.springframework.integration.channel.ChannelUtils; import org.springframework.integration.channel.DefaultHeaderChannelRegistry; import org.springframework.integration.channel.MessagePublishingErrorHandler; @@ -69,9 +67,14 @@ 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; +import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.ClassUtils; +import org.springframework.util.ErrorHandler; /** * A {@link BeanFactoryPostProcessor} implementation that registers bean definitions @@ -90,7 +93,7 @@ class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProcessor, BeanClassLoaderAware, SmartInitializingSingleton { - private static final Log LOGGER = LogFactory.getLog(DefaultConfiguringBeanFactoryPostProcessor.class); + private static final LogAccessor LOGGER = new LogAccessor(DefaultConfiguringBeanFactoryPostProcessor.class); private static final IntegrationConverterInitializer INTEGRATION_CONVERTER_INITIALIZER = new IntegrationConverterInitializer(); @@ -101,6 +104,8 @@ class DefaultConfiguringBeanFactoryPostProcessor private ConfigurableListableBeanFactory beanFactory; + private BeanExpressionContext expressionContext; + private BeanDefinitionRegistry registry; @Override @@ -112,6 +117,7 @@ public void setBeanClassLoader(ClassLoader classLoader) { 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(); @@ -132,7 +138,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) registerMessageHandlerMethodFactory(); registerListMessageHandlerMethodFactory(); } - else if (LOGGER.isWarnEnabled()) { + else { LOGGER.warn("BeanFactory is not a BeanDefinitionRegistry. " + "The default Spring Integration infrastructure beans are not going to be registered"); } @@ -154,15 +160,14 @@ public void afterSingletonsInstantiated() { private void registerBeanFactoryChannelResolver() { if (!this.beanFactory.containsBeanDefinition(ChannelResolverUtils.CHANNEL_RESOLVER_BEAN_NAME)) { this.registry.registerBeanDefinition(ChannelResolverUtils.CHANNEL_RESOLVER_BEAN_NAME, - new RootBeanDefinition(BeanFactoryChannelResolver.class)); + new RootBeanDefinition(BeanFactoryChannelResolver.class, BeanFactoryChannelResolver::new)); } } private void registerMessagePublishingErrorHandler() { - if (!this.beanFactory.containsBeanDefinition( - ChannelUtils.MESSAGE_PUBLISHING_ERROR_HANDLER_BEAN_NAME)) { + if (!this.beanFactory.containsBeanDefinition(ChannelUtils.MESSAGE_PUBLISHING_ERROR_HANDLER_BEAN_NAME)) { this.registry.registerBeanDefinition(ChannelUtils.MESSAGE_PUBLISHING_ERROR_HANDLER_BEAN_NAME, - new RootBeanDefinition(MessagePublishingErrorHandler.class)); + new RootBeanDefinition(MessagePublishingErrorHandler.class, MessagePublishingErrorHandler::new)); } } @@ -178,8 +183,8 @@ private void registerNullChannel() { if (beanFactoryToUse instanceof ConfigurableListableBeanFactory) { ConfigurableListableBeanFactory listable = (ConfigurableListableBeanFactory) beanFactoryToUse; if (listable.containsBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) { - nullChannelDefinition = listable - .getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME); + nullChannelDefinition = + listable.getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME); } } if (beanFactoryToUse instanceof HierarchicalBeanFactory) { @@ -195,7 +200,7 @@ private void registerNullChannel() { } else { this.registry.registerBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME, - new RootBeanDefinition(NullChannel.class)); + new RootBeanDefinition(NullChannel.class, NullChannel::new)); } } @@ -207,33 +212,27 @@ private void registerNullChannel() { */ 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, - BeanDefinitionBuilder.rootBeanDefinition(PublishSubscribeChannel.class) - .addConstructorArgValue(IntegrationProperties.getExpressionFor( - IntegrationProperties.ERROR_CHANNEL_REQUIRE_SUBSCRIBERS)) - .addPropertyValue("ignoreFailures", - IntegrationProperties.getExpressionFor( - IntegrationProperties.ERROR_CHANNEL_IGNORE_FAILURES)) - .getBeanDefinition()); + LOGGER.info(() -> "No bean named '" + IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME + + "' has been explicitly defined. " + + "Therefore, a default PublishSubscribeChannel will be created."); - BeanDefinition loggingHandler = - BeanDefinitionBuilder.genericBeanDefinition(LoggingHandler.class) - .addConstructorArgValue("ERROR") - .getBeanDefinition(); + this.registry.registerBeanDefinition(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME, + new RootBeanDefinition(PublishSubscribeChannel.class, this::createErrorChannel)); String errorLoggerBeanName = IntegrationContextUtils.ERROR_LOGGER_BEAN_NAME + IntegrationConfigUtils.HANDLER_ALIAS_SUFFIX; - this.registry.registerBeanDefinition(errorLoggerBeanName, loggingHandler); + this.registry.registerBeanDefinition(errorLoggerBeanName, + new RootBeanDefinition(LoggingHandler.class, () -> new LoggingHandler(LoggingHandler.Level.ERROR))); BeanDefinitionBuilder loggingEndpointBuilder = - BeanDefinitionBuilder.genericBeanDefinition(ConsumerEndpointFactoryBean.class) - .addPropertyReference("handler", errorLoggerBeanName) - .addPropertyValue("inputChannelName", IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME); + BeanDefinitionBuilder.genericBeanDefinition(ConsumerEndpointFactoryBean.class, + () -> { + ConsumerEndpointFactoryBean endpointFactoryBean = new ConsumerEndpointFactoryBean(); + endpointFactoryBean.setInputChannelName(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME); + endpointFactoryBean.setHandler(this.beanFactory.getBean(errorLoggerBeanName, + MessageHandler.class)); + return endpointFactoryBean; + }); BeanComponentDefinition componentDefinition = new BeanComponentDefinition(loggingEndpointBuilder.getBeanDefinition(), @@ -242,35 +241,46 @@ private void registerErrorChannel() { } } + private PublishSubscribeChannel createErrorChannel() { + String requireSubscribersExpression = + IntegrationProperties.getExpressionFor(IntegrationProperties.ERROR_CHANNEL_REQUIRE_SUBSCRIBERS); + Boolean requireSubscribers = resolveExpression(requireSubscribersExpression, Boolean.class); + + PublishSubscribeChannel errorChannel = new PublishSubscribeChannel(Boolean.TRUE.equals(requireSubscribers)); + + String ignoreFailuresExpression = + IntegrationProperties.getExpressionFor(IntegrationProperties.ERROR_CHANNEL_IGNORE_FAILURES); + Boolean ignoreFailures = resolveExpression(ignoreFailuresExpression, Boolean.class); + errorChannel.setIgnoreFailures(Boolean.TRUE.equals(ignoreFailures)); + + return errorChannel; + } + /** * Register {@link IntegrationEvaluationContextFactoryBean} * and {@link IntegrationSimpleEvaluationContextFactoryBean} beans, if necessary. */ private void registerIntegrationEvaluationContext() { if (!this.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); + BeanDefinitionBuilder integrationEvaluationContextBuilder = + BeanDefinitionBuilder.genericBeanDefinition(IntegrationEvaluationContextFactoryBean.class, + IntegrationEvaluationContextFactoryBean::new) + .setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, this.registry); + this.registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, + integrationEvaluationContextBuilder.getBeanDefinition()); } 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); + BeanDefinitionBuilder integrationEvaluationContextBuilder = + BeanDefinitionBuilder.genericBeanDefinition(IntegrationSimpleEvaluationContextFactoryBean.class, + IntegrationSimpleEvaluationContextFactoryBean::new) + .setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, this.registry); + this.registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME, + integrationEvaluationContextBuilder.getBeanDefinition()); } } @@ -278,19 +288,17 @@ private void registerIntegrationEvaluationContext() { * Register an {@link IdGeneratorConfigurer} in the application context. */ private void registerIdGeneratorConfigurer() { - Class clazz = IdGeneratorConfigurer.class; + 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"); - } + LOGGER.info(() -> className + " is already registered and will be used"); return; } } - RootBeanDefinition beanDefinition = new RootBeanDefinition(clazz); + RootBeanDefinition beanDefinition = new RootBeanDefinition(clazz, IdGeneratorConfigurer::new); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, this.registry); } @@ -300,24 +308,31 @@ private void registerIdGeneratorConfigurer() { */ 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()) - .addPropertyReference("errorHandler", - ChannelUtils.MESSAGE_PUBLISHING_ERROR_HANDLER_BEAN_NAME) - .getBeanDefinition(); - - this.registry.registerBeanDefinition(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, scheduler); + LOGGER.info(() -> "No bean named '" + IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME + + "' has been explicitly defined. " + + "Therefore, a default ThreadPoolTaskScheduler will be created."); + this.registry.registerBeanDefinition(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, + new RootBeanDefinition(ThreadPoolTaskScheduler.class, this::createTaskScheduler)); } } + private ThreadPoolTaskScheduler createTaskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setThreadNamePrefix("task-scheduler-"); + taskScheduler.setRejectedExecutionHandler(new CallerRunsPolicy()); + 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); + } + + return taskScheduler; + } + /** * Register an {@code integrationGlobalProperties} bean if necessary. */ @@ -329,17 +344,21 @@ private void registerIntegrationProperties() { resourceResolver.getResources("classpath*:META-INF/spring.integration.properties"); // TODO Revise in favor of 'IntegrationProperties' instance in the next 6.0 version - BeanDefinitionBuilder integrationPropertiesBuilder = BeanDefinitionBuilder - .genericBeanDefinition(PropertiesFactoryBean.class) - .addPropertyValue("properties", IntegrationProperties.defaults()) - .addPropertyValue("locations", resources) - .setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + BeanDefinitionBuilder integrationPropertiesBuilder = + BeanDefinitionBuilder.genericBeanDefinition(PropertiesFactoryBean.class, + () -> { + PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); + propertiesFactoryBean.setProperties(IntegrationProperties.defaults()); + propertiesFactoryBean.setLocations(resources); + return propertiesFactoryBean; + }) + .setRole(BeanDefinition.ROLE_INFRASTRUCTURE); this.registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME, integrationPropertiesBuilder.getBeanDefinition()); } - catch (IOException e) { - LOGGER.warn("Cannot load 'spring.integration.properties' Resources.", e); + catch (IOException ex) { + LOGGER.warn(ex, "Cannot load 'spring.integration.properties' Resources."); } } } @@ -371,12 +390,12 @@ private void jsonPath(int registryId) throws LinkageError { try { ClassUtils.forName("com.jayway.jsonpath.Predicate", this.classLoader); } - catch (ClassNotFoundException e) { + catch (ClassNotFoundException ex) { jsonPathClass = null; - LOGGER.warn("The '#jsonPath' SpEL function cannot be registered. " + + 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", e); + "https://github.com/jayway/JsonPath/releases"); } } @@ -419,8 +438,7 @@ private void jsonNodeToString(int registryId) { ".json.JsonNodeWrapperToJsonNodeConverter") .getBeanDefinition()); INTEGRATION_CONVERTER_INITIALIZER.registerConverter(this.registry, - new RuntimeBeanReference( - IntegrationContextUtils.JSON_NODE_WRAPPER_TO_JSON_NODE_CONVERTER)); + new RuntimeBeanReference(IntegrationContextUtils.JSON_NODE_WRAPPER_TO_JSON_NODE_CONVERTER)); } } @@ -429,12 +447,8 @@ private void jsonNodeToString(int registryId) { */ private void registerRoleController() { if (!this.beanFactory.containsBean(IntegrationContextUtils.INTEGRATION_LIFECYCLE_ROLE_CONTROLLER)) { - BeanDefinitionBuilder builder = - BeanDefinitionBuilder.genericBeanDefinition(SmartLifecycleRoleController.class); - builder.addConstructorArgValue(new ManagedList()); - builder.addConstructorArgValue(new ManagedList()); - this.registry.registerBeanDefinition( - IntegrationContextUtils.INTEGRATION_LIFECYCLE_ROLE_CONTROLLER, builder.getBeanDefinition()); + this.registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_LIFECYCLE_ROLE_CONTROLLER, + new RootBeanDefinition(SmartLifecycleRoleController.class, SmartLifecycleRoleController::new)); } } @@ -443,13 +457,18 @@ private void registerRoleController() { */ 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()); + 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); } } @@ -458,17 +477,11 @@ private void registerMessageBuilderFactory() { */ 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); + LOGGER.info(() -> "No bean named '" + IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME + + "' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created."); + + this.registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME, + new RootBeanDefinition(DefaultHeaderChannelRegistry.class, DefaultHeaderChannelRegistry::new)); } } @@ -479,7 +492,8 @@ private void registerGlobalChannelInterceptorProcessor() { if (!this.registry.containsBeanDefinition( IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME)) { BeanDefinitionBuilder builder = - BeanDefinitionBuilder.genericBeanDefinition(GlobalChannelInterceptorProcessor.class) + BeanDefinitionBuilder.genericBeanDefinition(GlobalChannelInterceptorProcessor.class, + GlobalChannelInterceptorProcessor::new) .setRole(BeanDefinition.ROLE_INFRASTRUCTURE); this.registry.registerBeanDefinition(IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME, @@ -494,11 +508,10 @@ 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()); + new RootBeanDefinition(DefaultDatatypeChannelMessageConverter.class, + DefaultDatatypeChannelMessageConverter::new)); } } @@ -508,57 +521,74 @@ private void registerDefaultDatatypeChannelMessageConverter() { */ 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()); + new RootBeanDefinition(ConfigurableCompositeMessageConverter.class, + ConfigurableCompositeMessageConverter::new)); } } private void registerMessageHandlerMethodFactory() { if (!this.beanFactory.containsBean(IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME)) { - BeanDefinitionBuilder messageHandlerMethodFactoryBuilder = - createMessageHandlerMethodFactoryBeanDefinition(false); this.registry.registerBeanDefinition(IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME, - messageHandlerMethodFactoryBuilder.getBeanDefinition()); + new RootBeanDefinition(DefaultMessageHandlerMethodFactory.class, + () -> createMessageHandlerMethodFactory(false))); } } private void registerListMessageHandlerMethodFactory() { if (!this.beanFactory.containsBean(IntegrationContextUtils.LIST_MESSAGE_HANDLER_FACTORY_BEAN_NAME)) { - BeanDefinitionBuilder messageHandlerMethodFactoryBuilder = - createMessageHandlerMethodFactoryBeanDefinition(true); this.registry.registerBeanDefinition(IntegrationContextUtils.LIST_MESSAGE_HANDLER_FACTORY_BEAN_NAME, - messageHandlerMethodFactoryBuilder.getBeanDefinition()); + new RootBeanDefinition(DefaultMessageHandlerMethodFactory.class, + () -> createMessageHandlerMethodFactory(true))); } } - private BeanDefinitionBuilder createMessageHandlerMethodFactoryBeanDefinition(boolean listCapable) { - return BeanDefinitionBuilder.genericBeanDefinition(DefaultMessageHandlerMethodFactory.class) - .addPropertyReference("messageConverter", - IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME) - .addPropertyValue("customArgumentResolvers", buildArgumentResolvers(listCapable)); + private DefaultMessageHandlerMethodFactory createMessageHandlerMethodFactory(boolean listCapable) { + DefaultMessageHandlerMethodFactory methodFactory = new DefaultMessageHandlerMethodFactory(); + methodFactory.setMessageConverter( + this.beanFactory.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME, + MessageConverter.class)); + methodFactory.setCustomArgumentResolvers(buildArgumentResolvers(listCapable)); + return methodFactory; } - private ManagedList buildArgumentResolvers(boolean listCapable) { - ManagedList resolvers = new ManagedList<>(); - resolvers.add(new RootBeanDefinition(PayloadExpressionArgumentResolver.class)); - BeanDefinitionBuilder builder = - BeanDefinitionBuilder.genericBeanDefinition(NullAwarePayloadArgumentResolver.class); - builder.addConstructorArgReference(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME); - // TODO Validator ? - resolvers.add(builder.getBeanDefinition()); - resolvers.add(new RootBeanDefinition(PayloadsArgumentResolver.class)); + private List buildArgumentResolvers(boolean listCapable) { + List resolvers = new LinkedList<>(); + MessageConverter messageConverter = + this.beanFactory.getBean(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME, + MessageConverter.class); + + PayloadExpressionArgumentResolver payloadExpressionArgumentResolver = new PayloadExpressionArgumentResolver(); + payloadExpressionArgumentResolver.setBeanFactory(this.beanFactory); + payloadExpressionArgumentResolver.afterPropertiesSet(); + resolvers.add(payloadExpressionArgumentResolver); + + resolvers.add(new NullAwarePayloadArgumentResolver(messageConverter)); + + PayloadsArgumentResolver payloadsArgumentResolver = new PayloadsArgumentResolver(); + payloadsArgumentResolver.setBeanFactory(this.beanFactory); + payloadsArgumentResolver.afterPropertiesSet(); + resolvers.add(payloadsArgumentResolver); if (listCapable) { - resolvers.add( - BeanDefinitionBuilder.genericBeanDefinition(CollectionArgumentResolver.class) - .addConstructorArgValue(true) - .getBeanDefinition()); + CollectionArgumentResolver collectionArgumentResolver = new CollectionArgumentResolver(true); + collectionArgumentResolver.setBeanFactory(this.beanFactory); + collectionArgumentResolver.afterPropertiesSet(); + resolvers.add(collectionArgumentResolver); } - resolvers.add(new RootBeanDefinition(MapArgumentResolver.class)); + MapArgumentResolver mapArgumentResolver = new MapArgumentResolver(); + mapArgumentResolver.setBeanFactory(this.beanFactory); + mapArgumentResolver.afterPropertiesSet(); + resolvers.add(mapArgumentResolver); + return resolvers; } + @Nullable + private T resolveExpression(String expression, Class expectedType) { + Object value = this.beanFactory.getBeanExpressionResolver().evaluate(expression, this.expressionContext); + return this.beanFactory.getTypeConverter().convertIfNecessary(value, expectedType); + } + } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationManagementConfigurer.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationManagementConfigurer.java index d0d19c4605e..f40be94a88e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationManagementConfigurer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationManagementConfigurer.java @@ -17,8 +17,6 @@ package org.springframework.integration.config; import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import org.springframework.beans.BeansException; @@ -130,39 +128,18 @@ public void afterSingletonsInstantiated() { Assert.state(this.applicationContext != null, "'applicationContext' must not be null"); Assert.state(MANAGEMENT_CONFIGURER_NAME.equals(this.beanName), getClass().getSimpleName() + " bean name must be " + MANAGEMENT_CONFIGURER_NAME); + if (obtainMetricsCaptor() != null) { - injectCaptor(); registerComponentGauges(); } - Map managed = this.applicationContext - .getBeansOfType(IntegrationManagement.class); - for (Entry entry : managed.entrySet()) { - IntegrationManagement bean = entry.getValue(); - if (!getOverrides(bean).loggingConfigured) { - bean.setLoggingEnabled(this.defaultLoggingEnabled); - } - } - this.singletonsInstantiated = true; - } - private void injectCaptor() { - Map managed = - this.applicationContext.getBeansOfType(IntegrationManagement.class); - for (Entry entry : managed.entrySet()) { - IntegrationManagement bean = entry.getValue(); - if (!getOverrides(bean).loggingConfigured) { - bean.setLoggingEnabled(this.defaultLoggingEnabled); - } - bean.registerMetricsCaptor(this.metricsCaptor); - } - } + for (IntegrationManagement integrationManagement : + this.applicationContext.getBeansOfType(IntegrationManagement.class).values()) { - @Override - public Object postProcessAfterInitialization(Object bean, String name) throws BeansException { - if (this.singletonsInstantiated && obtainMetricsCaptor() != null && bean instanceof IntegrationManagement) { - ((IntegrationManagement) bean).registerMetricsCaptor(this.metricsCaptor); + enhanceIntegrationManagement(integrationManagement); } - return bean; + + this.singletonsInstantiated = true; } private void registerComponentGauges() { @@ -185,6 +162,23 @@ private void registerComponentGauges() { .build()); } + private void enhanceIntegrationManagement(IntegrationManagement integrationManagement) { + if (!getOverrides(integrationManagement).loggingConfigured) { + integrationManagement.setLoggingEnabled(this.defaultLoggingEnabled); + } + if (this.metricsCaptor != null) { + integrationManagement.registerMetricsCaptor(this.metricsCaptor); + } + } + + @Override + public Object postProcessAfterInitialization(Object bean, String name) throws BeansException { + if (this.singletonsInstantiated && bean instanceof IntegrationManagement) { + enhanceIntegrationManagement((IntegrationManagement) bean); + } + return bean; + } + @Override public void onApplicationEvent(ContextClosedEvent event) { if (event.getApplicationContext().equals(this.applicationContext)) { this.gauges.forEach(MeterFacade::remove); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java index 28e74d80730..834a15bdd69 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java @@ -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. @@ -24,6 +24,7 @@ import org.springframework.beans.factory.support.ManagedSet; 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; @@ -46,7 +47,7 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar { IntegrationRegistrar.class.getClassLoader())) { throw new ApplicationContextException("Starting with Spring Integration 5.0, " - + "the 'spring-integration-java-dsl' dependency is no longer needed; " + + "the 'spring-integration-java-dsl' dependency is no longer needed; " + "the Java DSL has been merged into the core project. " + "If it is present on the classpath, it will cause class loading conflicts."); } @@ -108,7 +109,8 @@ private void registerImplicitChannelCreator(BeanDefinitionRegistry registry) { private void registerDefaultConfiguringBeanFactoryPostProcessor(BeanDefinitionRegistry registry) { if (!registry.containsBeanDefinition(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME)) { BeanDefinitionBuilder postProcessorBuilder = - BeanDefinitionBuilder.genericBeanDefinition(DefaultConfiguringBeanFactoryPostProcessor.class); + BeanDefinitionBuilder.genericBeanDefinition(DefaultConfiguringBeanFactoryPostProcessor.class, + DefaultConfiguringBeanFactoryPostProcessor::new); BeanDefinitionHolder postProcessorHolder = new BeanDefinitionHolder( postProcessorBuilder.getBeanDefinition(), IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME); @@ -121,7 +123,8 @@ private void registerDefaultConfiguringBeanFactoryPostProcessor(BeanDefinitionRe * to process the external Integration infrastructure. */ private void registerIntegrationConfigurationBeanFactoryPostProcessor(BeanDefinitionRegistry registry) { - if (!registry.containsBeanDefinition( + if (!(NativeDetector.inNativeImage()) // Spring Native detects all the 'spring.factories' + && !registry.containsBeanDefinition( IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME)) { BeanDefinitionBuilder postProcessorBuilder = BeanDefinitionBuilder @@ -143,7 +146,8 @@ private void registerIntegrationConfigurationBeanFactoryPostProcessor(BeanDefini private void registerMessagingAnnotationPostProcessors(AnnotationMetadata meta, BeanDefinitionRegistry registry) { if (!registry.containsBeanDefinition(IntegrationContextUtils.MESSAGING_ANNOTATION_POSTPROCESSOR_NAME)) { BeanDefinitionBuilder builder = - BeanDefinitionBuilder.genericBeanDefinition(MessagingAnnotationPostProcessor.class) + BeanDefinitionBuilder.genericBeanDefinition(MessagingAnnotationPostProcessor.class, + MessagingAnnotationPostProcessor::new) .setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(IntegrationContextUtils.MESSAGING_ANNOTATION_POSTPROCESSOR_NAME, diff --git a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java index c65fa8e6915..702483eabb6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/context/IntegrationContextUtils.java @@ -85,7 +85,7 @@ public abstract class IntegrationContextUtils { IntegrationConfigUtils.BASE_PACKAGE + ".internalPublisherAnnotationBeanPostProcessor"; public static final String INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME = - "IntegrationConfigurationBeanFactoryPostProcessor"; + "integrationConfigurationBeanFactoryPostProcessor"; public static final String INTEGRATION_MESSAGE_HISTORY_CONFIGURER_BEAN_NAME = "messageHistoryConfigurer"; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/support/PayloadExpressionArgumentResolver.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/support/PayloadExpressionArgumentResolver.java index 4c3c72e7ef9..d92a3cafeab 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/support/PayloadExpressionArgumentResolver.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/support/PayloadExpressionArgumentResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * Copyright 2017-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ * * @since 5.0 * - * @see org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver + * @see org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver */ public class PayloadExpressionArgumentResolver extends AbstractExpressionEvaluator implements HandlerMethodArgumentResolver { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java index bd17d48102d..894e93d7887 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/DefaultMessageBuilderFactory.java @@ -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. @@ -18,6 +18,7 @@ import java.util.Arrays; +import org.springframework.lang.Nullable; import org.springframework.messaging.Message; /** @@ -39,7 +40,7 @@ public class DefaultMessageBuilderFactory implements MessageBuilderFactory { * and {@link org.springframework.messaging.MessageHeaders#TIMESTAMP}. * @since 4.3.2 */ - public void setReadOnlyHeaders(String... readOnlyHeaders) { + public void setReadOnlyHeaders(@Nullable String... readOnlyHeaders) { this.readOnlyHeaders = readOnlyHeaders != null ? Arrays.copyOf(readOnlyHeaders, readOnlyHeaders.length) : null; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java b/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java index 9dc5d9fa778..e122610a42c 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/SmartLifecycleRoleController.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 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. @@ -69,6 +69,14 @@ public class SmartLifecycleRoleController implements ApplicationListener METER_REGISTRY_CLASS; - - static { - Class aClass = null; - try { - aClass = ClassUtils.forName("io.micrometer.core.instrument.MeterRegistry", - ClassUtils.getDefaultClassLoader()); - } - catch (ClassNotFoundException e) { - // Ignore - no Micrometer in classpath - } - METER_REGISTRY_CLASS = aClass; - } + private static final boolean METER_REGISTRY_PRESENT + = ClassUtils.isPresent("io.micrometer.core.instrument.MeterRegistry", ClassUtils.getDefaultClassLoader()); @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { ListableBeanFactory beanFactory = (ListableBeanFactory) registry; - if (METER_REGISTRY_CLASS != null + if (METER_REGISTRY_PRESENT && !registry.containsBeanDefinition(MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME) - && beanFactory.getBeanNamesForType(METER_REGISTRY_CLASS, false, false).length > 0) { + && beanFactory.getBeanNamesForType(MeterRegistry.class, false, false).length > 0) { registry.registerBeanDefinition(MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME, - BeanDefinitionBuilder.genericBeanDefinition(MicrometerMetricsCaptor.class) - .addConstructorArgValue(beanFactory.getBeanProvider(METER_REGISTRY_CLASS)) + BeanDefinitionBuilder.genericBeanDefinition(MicrometerMetricsCaptor.class, + () -> new MicrometerMetricsCaptor(beanFactory.getBeanProvider(MeterRegistry.class))) .setRole(BeanDefinition.ROLE_INFRASTRUCTURE) .getBeanDefinition()); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/EnableIntegrationGraphController.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/EnableIntegrationGraphController.java index cc60dfee049..be506e6d100 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/EnableIntegrationGraphController.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/EnableIntegrationGraphController.java @@ -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. @@ -40,7 +40,7 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited -@Import(IntegrationGraphControllerRegistrarImportSelector.class) +@Import(IntegrationGraphControllerRegistrar.class) public @interface EnableIntegrationGraphController { /** diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerParser.java index a32c450d7c6..9d7509dc799 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerParser.java @@ -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. @@ -28,6 +28,7 @@ /** * The {@link BeanDefinitionParser} for the {@code } component. + * * @author Artem Bilan * * @since 4.3 @@ -39,22 +40,15 @@ public class IntegrationGraphControllerParser implements BeanDefinitionParser { @Override public BeanDefinition parse(final Element element, ParserContext parserContext) { - if (HttpContextUtils.WEB_MVC_PRESENT) { - this.graphControllerRegistrar.registerBeanDefinitions( - new AnnotationMetadataAdapter() { - - @Override - public Map getAnnotationAttributes(String annotationType) { - return Collections.singletonMap("value", element.getAttribute("path")); - } - - }, parserContext.getRegistry()); - } - else { - parserContext.getReaderContext().warning("The 'IntegrationGraphController' isn't registered " + - "with the application context because" + - " there is no 'org.springframework.web.servlet.DispatcherServlet' in the classpath.", element); - } + this.graphControllerRegistrar.registerBeanDefinitions( + new AnnotationMetadataAdapter() { + + @Override + public Map getAnnotationAttributes(String annotationType) { + return Collections.singletonMap("value", element.getAttribute("path")); + } + + }, parserContext.getRegistry()); return null; } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrar.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrar.java index ed65a023d49..918cffba857 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrar.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrar.java @@ -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. @@ -20,7 +20,11 @@ import java.util.HashMap; import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -52,8 +56,17 @@ */ class IntegrationGraphControllerRegistrar implements ImportBeanDefinitionRegistrar { + private static final Log LOGGER = LogFactory.getLog(IntegrationGraphControllerRegistrar.class); + @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + if (!HttpContextUtils.WEB_MVC_PRESENT && !HttpContextUtils.WEB_FLUX_PRESENT) { + LOGGER.warn("The 'IntegrationGraphController' isn't registered with the application context because" + + " there is no 'org.springframework.web.servlet.DispatcherServlet' or" + + " 'org.springframework.web.reactive.DispatcherHandler' in the classpath."); + return; + } + Map annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableIntegrationGraphController.class.getName()); if (annotationAttributes == null) { @@ -62,40 +75,41 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_GRAPH_SERVER_BEAN_NAME)) { registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_GRAPH_SERVER_BEAN_NAME, - new RootBeanDefinition(IntegrationGraphServer.class)); + new RootBeanDefinition(IntegrationGraphServer.class, IntegrationGraphServer::new)); } + String path = (String) annotationAttributes.get("value"); String[] allowedOrigins = (String[]) annotationAttributes.get("allowedOrigins"); if (allowedOrigins != null && allowedOrigins.length > 0) { AbstractBeanDefinition controllerCorsConfigurer = - BeanDefinitionBuilder.genericBeanDefinition(IntegrationGraphCorsConfigurer.class) - .addConstructorArgValue(annotationAttributes.get("value")) - .addConstructorArgValue(allowedOrigins) - .getBeanDefinition(); + new RootBeanDefinition(IntegrationGraphCorsConfigurer.class, + () -> new IntegrationGraphCorsConfigurer(path, allowedOrigins)); BeanDefinitionReaderUtils.registerWithGeneratedName(controllerCorsConfigurer, registry); } if (!registry.containsBeanDefinition(HttpContextUtils.GRAPH_CONTROLLER_BEAN_NAME)) { + Map properties = annotationAttributes; AbstractBeanDefinition controllerPropertiesPopulator = - BeanDefinitionBuilder.genericBeanDefinition(GraphControllerPropertiesPopulator.class) - .addConstructorArgValue(annotationAttributes) + BeanDefinitionBuilder.genericBeanDefinition(GraphControllerPropertiesPopulator.class, + () -> new GraphControllerPropertiesPopulator(properties)) .setRole(BeanDefinition.ROLE_INFRASTRUCTURE) .getBeanDefinition(); BeanDefinitionReaderUtils.registerWithGeneratedName(controllerPropertiesPopulator, registry); BeanDefinition graphController = - BeanDefinitionBuilder.genericBeanDefinition(IntegrationGraphController.class) - .addConstructorArgReference(IntegrationContextUtils.INTEGRATION_GRAPH_SERVER_BEAN_NAME) - .getBeanDefinition(); + new RootBeanDefinition(IntegrationGraphController.class, () -> + new IntegrationGraphController( + ((BeanFactory) registry) + .getBean(IntegrationContextUtils.INTEGRATION_GRAPH_SERVER_BEAN_NAME, + IntegrationGraphServer.class))); registry.registerBeanDefinition(HttpContextUtils.GRAPH_CONTROLLER_BEAN_NAME, graphController); } } - private static final class GraphControllerPropertiesPopulator - implements BeanFactoryPostProcessor, EnvironmentAware { + private static final class GraphControllerPropertiesPopulator implements BeanFactoryPostProcessor, EnvironmentAware { - private final Map properties = new HashMap(); + private final Map properties = new HashMap<>(); private GraphControllerPropertiesPopulator(Map annotationAttributes) { Object graphControllerPath = annotationAttributes.get(AnnotationUtils.VALUE); diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrarImportSelector.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrarImportSelector.java deleted file mode 100644 index 2d7267256c8..00000000000 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrarImportSelector.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2016-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.http.config; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.context.annotation.ImportSelector; -import org.springframework.core.type.AnnotationMetadata; - -/** - * @author Artem Bilan - * - * @since 4.3 - */ -class IntegrationGraphControllerRegistrarImportSelector implements ImportSelector { - - private static final Log LOGGER = LogFactory.getLog(IntegrationGraphControllerRegistrarImportSelector.class); - - @Override - public String[] selectImports(AnnotationMetadata importingClassMetadata) { - if (HttpContextUtils.WEB_MVC_PRESENT || HttpContextUtils.WEB_FLUX_PRESENT) { - return new String[] { IntegrationGraphControllerRegistrar.class.getName() }; - } - else { - LOGGER.warn("The 'IntegrationGraphController' isn't registered with the application context because" + - " there is no 'org.springframework.web.servlet.DispatcherServlet' or" + - " 'org.springframework.web.reactive.DispatcherHandler' in the classpath."); - return new String[0]; - } - } - -}