INT-4322: Log merged global properties on startup (#2612)

* INT-4322: Log merged global properties on startup

JIRA: https://jira.spring.io/browse/INT-4322

Now we have DEBUG message in logs like this:
```
Spring Integration global properties:

spring.integration.endpoints.noAutoStartup=fooService*
spring.integration.taskScheduler.poolSize=20
spring.integration.channels.maxUnicastSubscribers=0x7fffffff
spring.integration.channels.autoCreate=true
spring.integration.channels.maxBroadcastSubscribers=0x7fffffff
spring.integration.readOnly.headers=
spring.integration.messagingTemplate.throwExceptionOnLateReply=true
```

* Also register a `mergedIntegrationGlobalProperties` bean on a first
`IntegrationContextUtils.getIntegrationProperties()` call to avoid a
new `Properties` object on each call

* * Fix `TestUtils` to register a `BeanDefinition` instead of `registerSingleton()`
and an explicit `afterPropertiesSet()` call

* * Document mentioned changes
* Some polishing for `whats-new.adoc`
This commit is contained in:
Artem Bilan
2018-10-25 15:30:32 -04:00
committed by Gary Russell
parent 8b54277a34
commit 8305c6fec3
5 changed files with 89 additions and 54 deletions

View File

@@ -17,10 +17,13 @@
package org.springframework.integration.config;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
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;
@@ -29,6 +32,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
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.BeanFactoryPostProcessor;
@@ -80,7 +84,8 @@ import org.springframework.util.ClassUtils;
*
* @see IntegrationContextUtils
*/
class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProcessor, BeanClassLoaderAware {
class DefaultConfiguringBeanFactoryPostProcessor
implements BeanFactoryPostProcessor, BeanClassLoaderAware, SmartInitializingSingleton {
private static final Log logger = LogFactory.getLog(DefaultConfiguringBeanFactoryPostProcessor.class);
@@ -128,6 +133,18 @@ class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProce
}
}
@Override
public void afterSingletonsInstantiated() {
if (logger.isDebugEnabled()) {
Properties integrationProperties = IntegrationContextUtils.getIntegrationProperties(this.beanFactory);
StringWriter writer = new StringWriter();
integrationProperties.list(new PrintWriter(writer));
StringBuffer propertiesBuffer = writer.getBuffer()
.delete(0, "-- listing properties --".length());
logger.debug("\nSpring Integration global properties:\n" + propertiesBuffer);
}
}
/**
* Register a null channel in the application context.
@@ -135,7 +152,7 @@ class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProce
*/
private void registerNullChannel() {
if (this.beanFactory.containsBean(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) {
BeanDefinition nullChannelDefinition = null;
BeanDefinition nullChannelDefinition;
if (this.beanFactory.containsBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) {
nullChannelDefinition =
this.beanFactory.getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
@@ -319,7 +336,7 @@ class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProce
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: " +
"At least 2.4.0 is required; see version information at: " +
"https://github.com/jayway/JsonPath/releases", e);
}
@@ -482,7 +499,8 @@ class DefaultConfiguringBeanFactoryPostProcessor implements BeanFactoryPostProce
private BeanDefinition internalArgumentResolversBuilder(boolean listCapable) {
ManagedList<BeanDefinition> resolvers = new ManagedList<>();
resolvers.add(new RootBeanDefinition(PayloadExpressionArgumentResolver.class));
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(NullAwarePayloadArgumentResolver.class);
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(NullAwarePayloadArgumentResolver.class);
builder.addConstructorArgReference(IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME);
// TODO Validator ?
resolvers.add(builder.getBeanDefinition());

View File

@@ -19,6 +19,8 @@ package org.springframework.integration.context;
import java.util.Properties;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.integration.config.IntegrationConfigUtils;
@@ -57,6 +59,8 @@ public abstract class IntegrationContextUtils {
public static final String INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME = "integrationGlobalProperties";
public static final String MERGED_INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME = "mergedIntegrationGlobalProperties";
public static final String CHANNEL_INITIALIZER_BEAN_NAME = "channelInitializer";
public static final String AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME = "$autoCreateChannelCandidates";
@@ -176,15 +180,33 @@ public abstract class IntegrationContextUtils {
* provided {@code #beanFactory} or provided {@code #beanFactory} is null.
*/
public static Properties getIntegrationProperties(BeanFactory beanFactory) {
Properties properties = new Properties();
properties.putAll(IntegrationProperties.defaults());
Properties properties;
if (beanFactory != null) {
Properties userProperties =
getBeanOfType(beanFactory, INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME, Properties.class);
if (userProperties != null) {
properties.putAll(userProperties);
properties = getBeanOfType(beanFactory, MERGED_INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME, Properties.class);
if (properties == null) {
Properties propertiesToRegister = new Properties();
propertiesToRegister.putAll(IntegrationProperties.defaults());
Properties userProperties =
getBeanOfType(beanFactory, INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME, Properties.class);
if (userProperties != null) {
propertiesToRegister.putAll(userProperties);
}
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
RootBeanDefinition beanDefinition = new RootBeanDefinition(Properties.class);
beanDefinition.setInstanceSupplier(() -> propertiesToRegister);
registry.registerBeanDefinition(MERGED_INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME, beanDefinition);
}
properties = propertiesToRegister;
}
}
else {
properties = new Properties();
properties.putAll(IntegrationProperties.defaults());
}
return properties;
}