INT-4284: Exception to overwrite id or timestamp
JIRA: https://jira.spring.io/browse/INT-4284
To inform end-user that he/she can't override `id` and `timestamp` headers
throw a `BeanInitializationException` from the `gateway`, `header-enricher`,
`enricher` and `header-filter` configuration when `id` and `timestamp` are
explicitly provided
(cherry picked from commit 4a47a7c)
This commit is contained in:
@@ -47,6 +47,7 @@ import org.springframework.integration.support.MessageBuilderFactory;
|
||||
import org.springframework.integration.util.MessagingAnnotationUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.core.GenericMessagingTemplate;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.messaging.handler.annotation.Headers;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
@@ -77,11 +78,12 @@ import org.springframework.util.StringUtils;
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]>, BeanFactoryAware {
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
private final static Log logger = LogFactory.getLog(GatewayMethodInboundMessageMapper.class);
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
@@ -91,10 +93,14 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
|
||||
private final Map<String, Expression> globalHeaderExpressions;
|
||||
|
||||
private final Map<String, Object> headers;
|
||||
|
||||
private final List<MethodParameter> parameterList;
|
||||
|
||||
private final MethodArgsMessageMapper argsMapper;
|
||||
|
||||
private final MessageBuilderFactory messageBuilderFactory;
|
||||
|
||||
private volatile Expression payloadExpression;
|
||||
|
||||
private final Map<String, Expression> parameterPayloadExpressions = new HashMap<String, Expression>();
|
||||
@@ -103,8 +109,6 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
|
||||
private volatile BeanFactory beanFactory;
|
||||
|
||||
private final MessageBuilderFactory messageBuilderFactory;
|
||||
|
||||
GatewayMethodInboundMessageMapper(Method method) {
|
||||
this(method, null);
|
||||
}
|
||||
@@ -116,9 +120,17 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
GatewayMethodInboundMessageMapper(Method method, Map<String, Expression> headerExpressions,
|
||||
Map<String, Expression> globalHeaderExpressions, MethodArgsMessageMapper mapper,
|
||||
MessageBuilderFactory messageBuilderFactory) {
|
||||
this(method, headerExpressions, globalHeaderExpressions, null, mapper, messageBuilderFactory);
|
||||
}
|
||||
|
||||
GatewayMethodInboundMessageMapper(Method method, Map<String, Expression> headerExpressions,
|
||||
Map<String, Expression> globalHeaderExpressions, Map<String, Object> headers,
|
||||
MethodArgsMessageMapper mapper,
|
||||
MessageBuilderFactory messageBuilderFactory) {
|
||||
Assert.notNull(method, "method must not be null");
|
||||
this.method = method;
|
||||
this.headerExpressions = headerExpressions;
|
||||
this.headers = headers;
|
||||
this.globalHeaderExpressions = globalHeaderExpressions;
|
||||
this.parameterList = getMethodParameterList(method);
|
||||
this.payloadExpression = parsePayloadExpression(method);
|
||||
@@ -142,11 +154,9 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(final BeanFactory beanFactory) {
|
||||
if (beanFactory != null) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.payloadExpressionEvaluationContext = ExpressionUtils.createStandardEvaluationContext(beanFactory);
|
||||
}
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.payloadExpressionEvaluationContext = ExpressionUtils.createStandardEvaluationContext(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -179,9 +189,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
Map<String, Object> evaluatedHeaders = new HashMap<String, Object>();
|
||||
for (Map.Entry<String, Expression> entry : headerExpressions.entrySet()) {
|
||||
Object value = entry.getValue().getValue(methodInvocationEvaluationContext);
|
||||
if (value != null) {
|
||||
evaluatedHeaders.put(entry.getKey(), value);
|
||||
}
|
||||
evaluatedHeaders.put(entry.getKey(), value);
|
||||
}
|
||||
return evaluatedHeaders;
|
||||
}
|
||||
@@ -208,8 +216,8 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
for (Entry<?, ?> entry : argumentValue.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
if (!(key instanceof String)) {
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn("Invalid header name [" + key +
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Invalid header name [" + key +
|
||||
"], name type must be String. Skipping mapping of this header to MessageHeaders.");
|
||||
}
|
||||
}
|
||||
@@ -222,10 +230,10 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
private void throwExceptionForMultipleMessageOrPayloadParameters(MethodParameter methodParameter) {
|
||||
throw new MessagingException(
|
||||
"At most one parameter (or expression via method-level @Payload) may be mapped to the " +
|
||||
"payload or Message. Found more than one on method [" + methodParameter.getMethod() + "]");
|
||||
"payload or Message. Found more than one on method [" + methodParameter.getMethod() + "]");
|
||||
}
|
||||
|
||||
private String determineHeaderName(Annotation headerAnnotation, MethodParameter methodParameter) {
|
||||
static String determineHeaderName(Annotation headerAnnotation, MethodParameter methodParameter) {
|
||||
String valueAttribute = (String) AnnotationUtils.getValue(headerAnnotation);
|
||||
String headerName = StringUtils.hasText(valueAttribute) ? valueAttribute : methodParameter.getParameterName();
|
||||
Assert.notNull(headerName, "Cannot determine header name. Possible reasons: -debug is " +
|
||||
@@ -233,7 +241,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
return headerName;
|
||||
}
|
||||
|
||||
private static List<MethodParameter> getMethodParameterList(Method method) {
|
||||
static List<MethodParameter> getMethodParameterList(Method method) {
|
||||
List<MethodParameter> parameterList = new LinkedList<MethodParameter>();
|
||||
ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
int parameterCount = method.getParameterTypes().length;
|
||||
@@ -291,15 +299,13 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
messageOrPayload = argumentValue;
|
||||
}
|
||||
else {
|
||||
messageOrPayload =
|
||||
GatewayMethodInboundMessageMapper.this.evaluatePayloadExpression(expression, argumentValue);
|
||||
messageOrPayload = evaluatePayloadExpression(expression, argumentValue);
|
||||
}
|
||||
foundPayloadAnnotation = true;
|
||||
}
|
||||
else if (annotation.annotationType().equals(org.springframework.integration.annotation.Header.class)
|
||||
|| annotation.annotationType().equals(Header.class)) {
|
||||
String headerName =
|
||||
GatewayMethodInboundMessageMapper.this.determineHeaderName(annotation, methodParameter);
|
||||
String headerName = determineHeaderName(annotation, methodParameter);
|
||||
if ((Boolean) AnnotationUtils.getValue(annotation, "required") && argumentValue == null) {
|
||||
throw new IllegalArgumentException("Received null argument value for required header: '"
|
||||
+ headerName + "'");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,10 @@ import java.lang.reflect.Type;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -37,7 +40,9 @@ import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
@@ -50,13 +55,16 @@ import org.springframework.integration.annotation.Gateway;
|
||||
import org.springframework.integration.annotation.GatewayHeader;
|
||||
import org.springframework.integration.context.IntegrationProperties;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.integration.support.management.TrackableComponent;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.core.DestinationResolver;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -85,8 +93,6 @@ import reactor.rx.Promises;
|
||||
public class GatewayProxyFactoryBean extends AbstractEndpoint
|
||||
implements TrackableComponent, FactoryBean<Object>, MethodInterceptor, BeanClassLoaderAware {
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
private static final boolean reactorPresent = ClassUtils.isPresent("reactor.rx.Promise",
|
||||
GatewayProxyFactoryBean.class.getClassLoader());
|
||||
|
||||
@@ -544,7 +550,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint
|
||||
}
|
||||
headerExpressions.put(name, hasValue
|
||||
? new LiteralExpression(value)
|
||||
: PARSER.parseExpression(expression));
|
||||
: EXPRESSION_PARSER.parseExpression(expression));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +576,32 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getMessageBuilderFactory() instanceof DefaultMessageBuilderFactory) {
|
||||
Set<String> headerNames = new HashSet<String>(headerExpressions.keySet());
|
||||
|
||||
if (this.globalMethodMetadata != null) {
|
||||
headerNames.addAll(this.globalMethodMetadata.getHeaderExpressions().keySet());
|
||||
}
|
||||
|
||||
List<MethodParameter> methodParameters = GatewayMethodInboundMessageMapper.getMethodParameterList(method);
|
||||
|
||||
for (MethodParameter methodParameter : methodParameters) {
|
||||
Header header = methodParameter.getParameterAnnotation(Header.class);
|
||||
if (header != null) {
|
||||
String headerName = GatewayMethodInboundMessageMapper.determineHeaderName(header, methodParameter);
|
||||
headerNames.add(headerName);
|
||||
}
|
||||
}
|
||||
|
||||
for (String header : headerNames) {
|
||||
if ((MessageHeaders.ID.equals(header) || MessageHeaders.TIMESTAMP.equals(header))) {
|
||||
logger.warn("Messaging Gateway cannot override 'id' and 'timestamp' read-only headers.\n" +
|
||||
"Wrong headers configuration for " + getComponentName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GatewayMethodInboundMessageMapper messageMapper = new GatewayMethodInboundMessageMapper(method,
|
||||
headerExpressions,
|
||||
this.globalMethodMetadata != null ? this.globalMethodMetadata.getHeaderExpressions() : null,
|
||||
@@ -715,7 +747,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint
|
||||
if (t instanceof RuntimeException) {
|
||||
throw (RuntimeException) t;
|
||||
}
|
||||
throw new MessagingException("asynchronous gateway invocation failed", t);
|
||||
throw new MessagingException("Asynchronous gateway invocation failed", t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,12 @@ public final class MessageBuilder<T> extends AbstractIntegrationMessageBuilder<T
|
||||
*/
|
||||
@Override
|
||||
public MessageBuilder<T> removeHeader(String headerName) {
|
||||
this.headerAccessor.removeHeader(headerName);
|
||||
if (!this.headerAccessor.isReadOnly(headerName)) {
|
||||
this.headerAccessor.removeHeader(headerName);
|
||||
}
|
||||
else if (logger.isInfoEnabled()) {
|
||||
logger.info("The header [" + headerName + "] is ignored for removal because it is is readOnly.");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
@@ -30,10 +31,12 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
import org.springframework.integration.gateway.MessagingGatewaySupport;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.transformer.support.HeaderValueMessageProcessor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -49,11 +52,14 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Artem Bilan
|
||||
* @author Liujiong
|
||||
* @author Kris Jacyna
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
implements Lifecycle {
|
||||
public class ContentEnricher extends AbstractReplyProducingMessageHandler implements Lifecycle {
|
||||
|
||||
/**
|
||||
* Customized SpelExpressionParser to allow to specify nested properties when paren is null
|
||||
*/
|
||||
private final SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
private volatile Map<Expression, Expression> nullResultPropertyExpressions = new HashMap<Expression, Expression>();
|
||||
@@ -103,8 +109,7 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
}
|
||||
|
||||
public void setNullResultHeaderExpressions(Map<String, HeaderValueMessageProcessor<?>> nullResultHeaderExpressions) {
|
||||
this.nullResultHeaderExpressions = new HashMap<String, HeaderValueMessageProcessor<?>>(
|
||||
nullResultHeaderExpressions);
|
||||
this.nullResultHeaderExpressions = new HashMap<String, HeaderValueMessageProcessor<?>>(nullResultHeaderExpressions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,19 +321,33 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler
|
||||
targetContext.setBeanResolver(null);
|
||||
this.targetEvaluationContext = targetContext;
|
||||
|
||||
if (this.getBeanFactory() != null) {
|
||||
for (HeaderValueMessageProcessor<?> headerValueMessageProcessor : this.headerExpressions.values()) {
|
||||
if (headerValueMessageProcessor instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) headerValueMessageProcessor).setBeanFactory(getBeanFactory());
|
||||
if (getBeanFactory() != null) {
|
||||
boolean checkReadOnlyHeaders = getMessageBuilderFactory() instanceof DefaultMessageBuilderFactory;
|
||||
|
||||
for (Map.Entry<String, HeaderValueMessageProcessor<?>> entry : this.headerExpressions.entrySet()) {
|
||||
if (checkReadOnlyHeaders &&
|
||||
(MessageHeaders.ID.equals(entry.getKey()) || MessageHeaders.TIMESTAMP.equals(entry.getKey()))) {
|
||||
this.logger.warn("ContentEnricher cannot override 'id' and 'timestamp' read-only headers.\n" +
|
||||
"Wrong 'headerExpressions' [" + this.headerExpressions
|
||||
+ "] configuration for " + getComponentName());
|
||||
}
|
||||
if (entry.getValue() instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) entry.getValue()).setBeanFactory(getBeanFactory());
|
||||
}
|
||||
}
|
||||
for (HeaderValueMessageProcessor<?> headerValueMessageProcessor : this.nullResultHeaderExpressions.values()) {
|
||||
if (headerValueMessageProcessor instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) headerValueMessageProcessor).setBeanFactory(getBeanFactory());
|
||||
|
||||
for (Map.Entry<String, HeaderValueMessageProcessor<?>> entry : this.nullResultHeaderExpressions.entrySet()) {
|
||||
if (checkReadOnlyHeaders &&
|
||||
(MessageHeaders.ID.equals(entry.getKey()) || MessageHeaders.TIMESTAMP.equals(entry.getKey()))) {
|
||||
this.logger.warn("ContentEnricher cannot override 'id' and 'timestamp' read-only headers.\n" +
|
||||
"Wrong 'nullResultHeaderExpressions' [" + this.nullResultHeaderExpressions
|
||||
+ "] configuration for " + getComponentName());
|
||||
}
|
||||
if (entry.getValue() instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) entry.getValue()).setBeanFactory(getBeanFactory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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,12 +24,15 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.context.IntegrationObjectSupport;
|
||||
import org.springframework.integration.handler.MessageProcessor;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.transformer.support.HeaderValueMessageProcessor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
|
||||
/**
|
||||
@@ -45,8 +48,6 @@ import org.springframework.messaging.MessagingException;
|
||||
*/
|
||||
public class HeaderEnricher extends IntegrationObjectSupport implements Transformer, BeanNameAware, InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(HeaderEnricher.class);
|
||||
|
||||
private final Map<String, ? extends HeaderValueMessageProcessor<?>> headersToAdd;
|
||||
|
||||
private volatile MessageProcessor<?> messageProcessor;
|
||||
@@ -112,7 +113,7 @@ public class HeaderEnricher extends IntegrationObjectSupport implements Transfor
|
||||
|
||||
boolean headerDoesNotExist = headerMap.get(key) == null;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Only evaluate value expression if necessary
|
||||
*/
|
||||
if (headerDoesNotExist || shouldOverwrite) {
|
||||
@@ -141,13 +142,13 @@ public class HeaderEnricher extends IntegrationObjectSupport implements Transfor
|
||||
headerMap.put((String) key, entry.getValue());
|
||||
}
|
||||
}
|
||||
else if (logger.isDebugEnabled()) {
|
||||
logger.debug("ignoring value for non-String key: " + key);
|
||||
else if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("ignoring value for non-String key: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (logger.isDebugEnabled()) {
|
||||
logger.debug("expected a Map result from processor, but received: " + result);
|
||||
else if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("expected a Map result from processor, but received: " + result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,23 +156,35 @@ public class HeaderEnricher extends IntegrationObjectSupport implements Transfor
|
||||
@Override
|
||||
public void onInit() throws Exception {
|
||||
boolean shouldOverwrite = this.defaultOverwrite;
|
||||
for (HeaderValueMessageProcessor<?> processor : this.headersToAdd.values()) {
|
||||
if (processor instanceof BeanFactoryAware && this.getBeanFactory() != null) {
|
||||
((BeanFactoryAware) processor).setBeanFactory(this.getBeanFactory());
|
||||
boolean checkReadOnlyHeaders = getMessageBuilderFactory() instanceof DefaultMessageBuilderFactory;
|
||||
|
||||
for (Entry<String, ? extends HeaderValueMessageProcessor<?>> entry : this.headersToAdd.entrySet()) {
|
||||
if (checkReadOnlyHeaders &&
|
||||
(MessageHeaders.ID.equals(entry.getKey()) || MessageHeaders.TIMESTAMP.equals(entry.getKey()))) {
|
||||
this.logger.warn("HeaderEnricher cannot override 'id' and 'timestamp' read-only headers.\n" +
|
||||
"Wrong 'headersToAdd' [" + this.headersToAdd
|
||||
+ "] configuration for " + getComponentName());
|
||||
}
|
||||
|
||||
HeaderValueMessageProcessor<?> processor = entry.getValue();
|
||||
if (processor instanceof BeanFactoryAware && getBeanFactory() != null) {
|
||||
((BeanFactoryAware) processor).setBeanFactory(getBeanFactory());
|
||||
}
|
||||
Boolean processorOverwrite = processor.isOverwrite();
|
||||
if (processorOverwrite != null) {
|
||||
shouldOverwrite |= processorOverwrite;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.messageProcessor != null
|
||||
&& this.messageProcessor instanceof BeanFactoryAware
|
||||
&& this.getBeanFactory() != null) {
|
||||
((BeanFactoryAware) this.messageProcessor).setBeanFactory(this.getBeanFactory());
|
||||
&& getBeanFactory() != null) {
|
||||
((BeanFactoryAware) this.messageProcessor).setBeanFactory(getBeanFactory());
|
||||
}
|
||||
if (!shouldOverwrite && !this.shouldSkipNulls) {
|
||||
logger.warn(this.getComponentName()
|
||||
+ " is configured to not overwrite existing headers. 'shouldSkipNulls = false' will have no effect");
|
||||
|
||||
if (!shouldOverwrite && !this.shouldSkipNulls && this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(getComponentName() +
|
||||
" is configured to not overwrite existing headers. 'shouldSkipNulls = false' will have no effect");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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,9 +16,14 @@
|
||||
|
||||
package org.springframework.integration.transformer;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.integration.context.IntegrationObjectSupport;
|
||||
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -27,6 +32,8 @@ import org.springframework.util.Assert;
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class HeaderFilter extends IntegrationObjectSupport implements Transformer {
|
||||
@@ -50,6 +57,21 @@ public class HeaderFilter extends IntegrationObjectSupport implements Transforme
|
||||
return "header-filter";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
super.onInit();
|
||||
if (getMessageBuilderFactory() instanceof DefaultMessageBuilderFactory) {
|
||||
for (String header : this.headersToRemove) {
|
||||
if (!header.contains("*")
|
||||
&& (MessageHeaders.ID.equals(header) || MessageHeaders.TIMESTAMP.equals(header))) {
|
||||
this.logger.warn("HeaderFilter cannot remove 'id' and 'timestamp' read-only headers.\n" +
|
||||
"Wrong 'headersToRemove' [" + Arrays.toString(this.headersToRemove)
|
||||
+ "] configuration for " + getComponentName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message<?> transform(Message<?> message) {
|
||||
AbstractIntegrationMessageBuilder<?> builder = this.getMessageBuilderFactory().fromMessage(message);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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,20 +16,30 @@
|
||||
|
||||
package org.springframework.integration.handler;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.transformer.HeaderEnricher;
|
||||
import org.springframework.integration.transformer.support.StaticHeaderValueMessageProcessor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MethodInvokingHeaderEnricherTests {
|
||||
@@ -89,7 +99,6 @@ public class MethodInvokingHeaderEnricherTests {
|
||||
assertEquals("ABC", result.getHeaders().get("bar"));
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean {
|
||||
|
||||
public Map<String, Object> process(@Payload("toUpperCase()") String s) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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 @@ package org.springframework.integration.transformer;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
@@ -27,6 +28,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -34,6 +36,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
@@ -47,9 +50,11 @@ import org.springframework.integration.endpoint.PollingConsumer;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.handler.ReplyRequiredException;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.transformer.support.StaticHeaderValueMessageProcessor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageDeliveryException;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
|
||||
@@ -87,7 +92,7 @@ public class ContentEnricherTests {
|
||||
public void replyChannelReplyTimingOut() throws Exception {
|
||||
|
||||
final long requestTimeout = 500L;
|
||||
final long replyTimeout = 700L;
|
||||
final long replyTimeout = 100L;
|
||||
|
||||
final DirectChannel replyChannel = new DirectChannel();
|
||||
final QueueChannel requestChannel = new QueueChannel(1);
|
||||
@@ -521,6 +526,7 @@ public class ContentEnricherTests {
|
||||
assertEquals("failed target", result.getName());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final class Source {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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,24 +16,35 @@
|
||||
|
||||
package org.springframework.integration.transformer;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.integration.test.matcher.HeaderMatcher.hasHeaderKey;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class HeaderFilterTests {
|
||||
@@ -76,4 +87,20 @@ public class HeaderFilterTests {
|
||||
assertEquals(correlationId, new IntegrationMessageHeaderAccessor(result).getCorrelationId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatternRemoval() {
|
||||
HeaderFilter filter = new HeaderFilter("time*");
|
||||
filter.setPatternMatch(true);
|
||||
|
||||
filter.afterPropertiesSet();
|
||||
Message<String> message = MessageBuilder.withPayload("test")
|
||||
.setHeader("time", new Date())
|
||||
.build();
|
||||
|
||||
Message<?> result = filter.transform(message);
|
||||
|
||||
assertThat(result, hasHeaderKey(MessageHeaders.TIMESTAMP));
|
||||
assertThat(result, not(hasHeaderKey("time")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user