diff --git a/spring-integration-core/src/main/java/org/springframework/integration/expression/ExpressionEvalMap.java b/spring-integration-core/src/main/java/org/springframework/integration/expression/ExpressionEvalMap.java
index 1e726543a6..5777708b7c 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/expression/ExpressionEvalMap.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/expression/ExpressionEvalMap.java
@@ -23,10 +23,13 @@ import java.util.Set;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
+import org.springframework.expression.common.LiteralExpression;
+import org.springframework.util.Assert;
/**
*
- * An immutable {@link AbstractMap} implementation that wraps a Map
+ * An immutable {@link AbstractMap} implementation that wraps a {@code Map},
+ * where values must be instances of {@link String} or {@link Expression},
* and evaluates an {@code expression} for the provided {@code key} from the underlying
* {@code original} Map.
*
@@ -38,16 +41,18 @@ import org.springframework.expression.Expression;
*
* A {@link ExpressionEvalMapBuilder} must be used to instantiate this class
* via its {@link #from(Map)} method:
+ *
* {@code
- * ExpressionEvalMap evalMap = ExpressionEvalMap
- * .from(expressions)
- .usingCallback(new EvaluationCallback() {
- Object evaluate(Expression expression) {
- // return some expression evaluation
- }
- })
- .build();
- * }
+ *ExpressionEvalMap evalMap = ExpressionEvalMap
+ * .from(expressions)
+ * .usingCallback(new EvaluationCallback() {
+ * Object evaluate(Expression expression) {
+ * // return some expression evaluation
+ * }
+ * })
+ * .build();
+ *}
+ *
*
*
* Thread-safety depends on the original underlying Map.
@@ -68,11 +73,11 @@ public final class ExpressionEvalMap extends AbstractMap {
};
- private final Map original;
+ private final Map original;
private final EvaluationCallback evaluationCallback;
- private ExpressionEvalMap(Map original, EvaluationCallback evaluationCallback) {
+ private ExpressionEvalMap(Map original, EvaluationCallback evaluationCallback) {
this.original = original;
this.evaluationCallback = evaluationCallback;
}
@@ -83,8 +88,20 @@ public final class ExpressionEvalMap extends AbstractMap {
*/
@Override
public Object get(Object key) {
- Expression expression = original.get(key);
- if (expression != null) {
+ Object value = original.get(key);
+ if (value != null) {
+ Expression expression;
+ if (value instanceof Expression) {
+ expression = (Expression) value;
+ }
+ else if (value instanceof String) {
+ expression = new LiteralExpression((String) value);
+ }
+ else {
+ throw new IllegalArgumentException("Values must be "
+ + "'java.lang.String' or 'org.springframework.expression.Expression'; the value type for key "
+ + key + " is : " + value.getClass());
+ }
return this.evaluationCallback.evaluate(expression);
}
return null;
@@ -136,7 +153,7 @@ public final class ExpressionEvalMap extends AbstractMap {
}
@Override
- public void putAll(Map extends String, ? extends Object> m) {
+ public void putAll(Map extends String, ?> m) {
throw new UnsupportedOperationException();
}
@@ -155,7 +172,13 @@ public final class ExpressionEvalMap extends AbstractMap {
throw new UnsupportedOperationException();
}
- public static ExpressionEvalMapBuilder from(Map expressions) {
+ @Override
+ public String toString() {
+ return this.original.toString();
+ }
+
+ public static ExpressionEvalMapBuilder from(Map expressions) {
+ Assert.notNull(expressions, "'expressions' must not be null.");
return new ExpressionEvalMapBuilder(expressions);
}
@@ -205,7 +228,7 @@ public final class ExpressionEvalMap extends AbstractMap {
*/
public static final class ExpressionEvalMapBuilder {
- private final Map expressions;
+ private final Map expressions;
private EvaluationCallback evaluationCallback;
@@ -219,7 +242,7 @@ public final class ExpressionEvalMap extends AbstractMap {
private final ExpressionEvalMapFinalBuilder finalBuilder = new ExpressionEvalMapFinalBuilderImpl();
- private ExpressionEvalMapBuilder(Map expressions) {
+ private ExpressionEvalMapBuilder(Map expressions) {
this.expressions = expressions;
}
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java
index 93afd42e17..71eb760f69 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.util.xml.DomUtils;
* @author Oleg Zhurakousky
* @author Mark Fisher
* @author Gary Russell
+ * @author Artem Bilan
* @since 2.0.2
*/
abstract class HttpAdapterParsingUtils {
@@ -52,9 +53,23 @@ abstract class HttpAdapterParsingUtils {
}
}
- static void configureUriVariableExpressions(BeanDefinitionBuilder builder, Element element) {
+ static void configureUriVariableExpressions(BeanDefinitionBuilder builder, ParserContext parserContext, Element element) {
+ String uriVariablesExpression = element.getAttribute("uri-variables-expression");
+
List uriVariableElements = DomUtils.getChildElementsByTagName(element, "uri-variable");
- if (!CollectionUtils.isEmpty(uriVariableElements)) {
+ boolean hasUriVariableExpressions = !CollectionUtils.isEmpty(uriVariableElements);
+
+ if (StringUtils.hasText(uriVariablesExpression)) {
+ if (hasUriVariableExpressions) {
+ parserContext.getReaderContext().error("'uri-variables-expression' attribute " +
+ "and 'uri-variable' sub-elements are mutually exclusive.", element);
+ }
+ BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
+ .addConstructorArgValue(uriVariablesExpression);
+ builder.addPropertyValue("uriVariablesExpression", beanDefinitionBuilder.getBeanDefinition());
+ }
+
+ if (hasUriVariableExpressions) {
ManagedMap uriVariableExpressions = new ManagedMap();
for (Element uriVariableElement : uriVariableElements) {
String name = uriVariableElement.getAttribute("name");
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java
index d1a6c0ee44..ae0bcb993a 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java
@@ -77,7 +77,7 @@ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAda
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "charset");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload");
HttpAdapterParsingUtils.setExpectedResponseOrExpression(element, parserContext, builder);
- HttpAdapterParsingUtils.configureUriVariableExpressions(builder, element);
+ HttpAdapterParsingUtils.configureUriVariableExpressions(builder, parserContext, element);
return builder.getBeanDefinition();
}
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java
index df2ed76567..ebbccd5f20 100644
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java
@@ -87,7 +87,7 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
- HttpAdapterParsingUtils.configureUriVariableExpressions(builder, element);
+ HttpAdapterParsingUtils.configureUriVariableExpressions(builder, parserContext, element);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "transfer-cookies");
return builder;
}
diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java
index c83f7d45a7..ffa8772458 100755
--- a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java
+++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java
@@ -111,6 +111,10 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
private volatile HeaderMapper headerMapper = DefaultHttpHeaderMapper.outboundMapper();
+ private volatile Expression uriVariablesExpression;
+
+
+
/**
* Create a handler that will send requests to the provided URI.
*/
@@ -280,6 +284,15 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
}
+ /**
+ * Set the {@link Expression} to evaluate against the outbound message; the expression
+ * must evaluate to a Map of URI variable expressions to evaluate against the outbound message
+ * when replacing the variable placeholders in a URI template.
+ */
+ public void setUriVariablesExpression(Expression uriVariablesExpression) {
+ this.uriVariablesExpression = uriVariablesExpression;
+ }
+
/**
* Set to true if you wish 'Set-Cookie' headers in responses to be
* transferred as 'Cookie' headers in subsequent interactions for
@@ -314,6 +327,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
private class ClassToStringConverter implements Converter, String> {
+ @Override
public String convert(Class> source) {
return source.getName();
}
@@ -326,6 +340,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
*
*/
private class ObjectToStringConverter implements Converter {
+ @Override
public String convert(Object source) {
if (source instanceof Class) {
return ((Class>) source).getName();
@@ -351,11 +366,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
Class> expectedResponseType = this.determineExpectedResponseType(requestMessage);
HttpEntity> httpRequest = this.generateHttpRequest(requestMessage, httpMethod);
- Map uriVariables = ExpressionEvalMap
- .from(this.uriVariableExpressions)
- .usingEvaluationContext(this.evaluationContext)
- .withRoot(requestMessage)
- .build();
+ Map uriVariables = this.determineUriVariables(requestMessage);
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri).buildAndExpand(uriVariables);
URI realUri = this.encodeUri ? uriComponents.toUri() : new URI(uriComponents.toUriString());
ResponseEntity> httpResponse = this.restTemplate.exchange(realUri, httpMethod, httpRequest, expectedResponseType);
@@ -554,7 +565,6 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
return HttpMethod.valueOf(strHttpMethod);
}
-
private Class> determineExpectedResponseType(Message> requestMessage) throws Exception{
Class> expectedResponseType = null;
String expectedResponseTypeName = null;
@@ -568,4 +578,22 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
}
+ @SuppressWarnings("unchecked")
+ private Map determineUriVariables(Message> requestMessage) {
+ Map expressions;
+
+ if (this.uriVariablesExpression != null) {
+ expressions = this.uriVariablesExpression.getValue(this.evaluationContext, requestMessage, Map.class);
+ }
+ else {
+ expressions = this.uriVariableExpressions;
+ }
+
+ return ExpressionEvalMap.from(expressions)
+ .usingEvaluationContext(this.evaluationContext)
+ .withRoot(requestMessage)
+ .build();
+
+ }
+
}
diff --git a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd
index 9768ebac03..4df86f0919 100644
--- a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd
+++ b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-3.0.xsd
@@ -322,78 +322,14 @@
Specify an expression for URI variable placeholder within 'url'.
+ This element is mutually exclusive with 'uri-variables-expression' attribute.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- When set to "false", the real URI won't be encoded before the request is sent. This may be useful
- in some scenarios as it allows user control over the encoding, if needed,
- for example by using the "url-expression". Default is "true".
-
-
-
-
-
-
- The HTTP method to use when executing requests with this adapter Default is POST.
- This attribute cannot be provided if http-method-expression has a value.
-
-
-
-
-
-
-
-
-
- The SpEL expression to determine HTTP method, use when executing requests with this adapter,
- dynamically. This attribute cannot be provided if http-method has a value.
-
-
-
-
-
-
-
-
-
-
-
- The reference to org.springframework.web.client.RestTemplate bean to send the HTTP Request.
-
-
-
-
-
-
- Specify the charset name to use for converting String-typed payloads to bytes.
- The default is 'UTF-8'
-
-
-
+
@@ -404,93 +340,6 @@
-
-
-
- The expected type to which the response body should be converted.
- Default is 'org.springframework.http.ResponseEntity'.
- This attribute cannot be provided if expected-response-type-expression has a value
-
-
-
-
-
-
-
-
-
-
-
- SpEL expression to determine the type for the expected response to which the response body should be converted
- The returned value of the expression could be an instance of java.lang.Class or
- java.lang.String representing a fully qualified class name.
- This attribute cannot be provided if expected-response-type has a value
-
-
-
-
-
-
- Provide a reference to a list of HttpMessageConverter instances. If specified, these converters will replace
- all of the default converters that would normally be present on the underlying RestTemplate.
-
-
-
-
-
-
-
-
-
-
-
- Specify a reference to org.springframework.integration.mapping.HeaderMapper
- implementation bean. Only one of 'header-mapper' or 'mapped-request-headers' attributes
- can be provided.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -525,96 +374,6 @@
-
-
-
- URL to which the requests should be sent. It may include {placeholders} for
- evaluation against uri-variables.
-
-
-
-
-
-
-
-
-
-
-
-
- When set to "false", the real URI won't be encoded before the request is sent. This may be useful
- in some scenarios as it allows user control over the encoding, if needed,
- for example by using the "url-expression". Default is "true".
-
-
-
-
-
-
- The HTTP method to use when executing requests with this adapter. Default is POST.
- This attribute cannot be provided if http-method-expression has a value.
-
-
-
-
-
-
-
-
-
- The SpEL expression to determine HTTP method, use when executing requests with this gateway,
- dynamically. This attribute cannot be provided if http-method has a value.
-
-
-
-
-
-
- Provide a reference to a list of HttpMessageConverter instances. If specified, these converters will replace
- all of the default converters that would normally be present on the underlying RestTemplate.
-
-
-
-
-
-
-
-
-
-
-
- Specifies a reference to org.springframework.integration.mapping.HeaderMapper
- implementation bean. Only one of 'header-mapper' or 'mapped-request-headers'('mapped-response-headers')
- attributes
- can be provided.
-
-
-
-
-
-
-
-
-
-
- The reference to org.springframework.web.client.RestTemplate bean to send the HTTP Request.
-
-
-
-
-
-
-
-
-
-
-
- Specifies whether the outbound message's payload should be extracted
- when preparing the request body. Otherwise the Message instance itself
- will be serialized.
- The default value is 'true'.
-
-
-
-
- The expected type to which the response body should be converted.
- Default is 'org.springframework.http.ResponseEntity'.
- This attribute cannot be provided if expected-response-type-expression has a value
+ Specifies whether the outbound message's payload should be extracted
+ when preparing the request body. Otherwise the Message instance itself
+ will be serialized.
+ The default value is 'true'.
-
-
-
-
-
-
-
-
-
-
- SpEL expression to determine the type for the expected response to which the response body should be converted
- The returned value of the expression could be an instance of java.lang.Class or
- java.lang.String representing a fully qualified class name.
- This attribute cannot be provided if expected-response-type has a value
-
-
-
-
-
-
- Specify the charset name to use for converting String-typed payloads to bytes.
- The default is 'UTF-8'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -730,6 +426,7 @@
]]>
+
@@ -873,4 +570,168 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ When set to "false", the real URI won't be encoded before the request is sent. This may be useful
+ in some scenarios as it allows user control over the encoding, if needed,
+ for example by using the "url-expression". Default is "true".
+
+
+
+
+
+
+ The HTTP method to use when executing requests with this adapter Default is POST.
+ This attribute cannot be provided if http-method-expression has a value.
+
+
+
+
+
+
+
+
+
+ The SpEL expression to determine HTTP method, use when executing requests with this adapter,
+ dynamically. This attribute cannot be provided if http-method has a value.
+
+
+
+
+
+
+
+
+
+
+
+ The reference to org.springframework.web.client.RestTemplate bean to send the HTTP Request.
+
+
+
+
+
+
+ Specify the charset name to use for converting String-typed payloads to bytes.
+ The default is 'UTF-8'
+
+
+
+
+
+
+ The expected type to which the response body should be converted.
+ Default is 'org.springframework.http.ResponseEntity'.
+ This attribute cannot be provided if expected-response-type-expression has a value
+
+
+
+
+
+
+
+
+
+
+
+ SpEL expression to determine the type for the expected response to which the response body should be converted
+ The returned value of the expression could be an instance of java.lang.Class or
+ java.lang.String representing a fully qualified class name.
+ This attribute cannot be provided if expected-response-type has a value
+
+
+
+
+
+
+ Provide a reference to a list of HttpMessageConverter instances. If specified, these converters will replace
+ all of the default converters that would normally be present on the underlying RestTemplate.
+
+
+
+
+
+
+
+
+
+
+
+ Specify a reference to org.springframework.integration.mapping.HeaderMapper
+ implementation bean. Only one of 'header-mapper' or 'mapped-request-headers' attributes
+ can be provided.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml
index 08e59d432d..17f4fcb0e5 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml
@@ -13,9 +13,9 @@
-
+
-
+
+
+
+
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java
index 19ea89efd6..4fa7a4affc 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java
@@ -57,6 +57,7 @@ import org.springframework.web.client.RestTemplate;
* @author Mark Fisher
* @author Gary Russell
* @author Gunnar Hillert
+ * @author Artem Bilan
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@@ -166,6 +167,7 @@ public class HttpOutboundChannelAdapterParserTests {
}
@Test
+ @SuppressWarnings("uchecked")
public void withUrlAndTemplate() {
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.withUrlAndTemplate);
RestTemplate restTemplate =
@@ -185,6 +187,14 @@ public class HttpOutboundChannelAdapterParserTests {
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
+
+ //INT-3055
+ Object uriVariablesExpression = handlerAccessor.getPropertyValue("uriVariablesExpression");
+ assertNotNull(uriVariablesExpression);
+ assertEquals("@uriVariables", ((Expression) uriVariablesExpression).getExpressionString());
+ Object uriVariableExpressions = handlerAccessor.getPropertyValue("uriVariableExpressions");
+ assertNotNull(uriVariableExpressions);
+ assertTrue(((Map, ?>) uriVariableExpressions).isEmpty());
}
@Test
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml
index 57fbdd3f8b..f2abb0d2d3 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests-context.xml
@@ -40,7 +40,13 @@
-
+
+
+
+
+
+
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java
index ffbe90640a..66358730d4 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -170,6 +170,14 @@ public class HttpOutboundGatewayParserTests {
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
assertEquals(false, handlerAccessor.getPropertyValue("transferCookies"));
+
+ //INT-3055
+ Object uriVariablesExpression = handlerAccessor.getPropertyValue("uriVariablesExpression");
+ assertNotNull(uriVariablesExpression);
+ assertEquals("@uriVariables", ((Expression) uriVariablesExpression).getExpressionString());
+ Object uriVariableExpressions = handlerAccessor.getPropertyValue("uriVariableExpressions");
+ assertNotNull(uriVariableExpressions);
+ assertTrue(((Map, ?>) uriVariableExpressions).isEmpty());
}
@Test
diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java
index d4c978174c..f646a90e1a 100644
--- a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java
+++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java
@@ -17,6 +17,7 @@
package org.springframework.integration.http.outbound;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.io.IOException;
@@ -35,7 +36,9 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.integration.Message;
+import org.springframework.integration.expression.ExpressionEvalMap;
import org.springframework.integration.message.GenericMessage;
+import org.springframework.integration.support.MessageBuilder;
/**
* @author Dave Syer
@@ -62,14 +65,13 @@ public class UriVariableExpressionTests {
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
Message> message = new GenericMessage("bar");
- Exception exception = null;
try {
handler.handleMessage(message);
+ fail("Exception expected.");
}
catch (Exception e) {
- exception = e;
+ assertEquals("intentional", e.getCause().getMessage());
}
- assertEquals("intentional", exception.getCause().getMessage());
assertEquals("http://test/bar", uriHolder.get().toString());
}
@@ -92,15 +94,45 @@ public class UriVariableExpressionTests {
});
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
- Message> message = new GenericMessage("bar");
- Exception exception = null;
try {
- handler.handleMessage(message);
+ handler.handleMessage(new GenericMessage("bar"));
+ fail("Exception expected.");
}
catch (Exception e) {
- exception = e;
+ assertEquals("intentional", e.getCause().getMessage());
}
- assertEquals("intentional", exception.getCause().getMessage());
+ assertEquals("http://test/bar", uriHolder.get().toString());
+ }
+
+ @Test
+ public void testInt3055UriVariablesExpression() throws Exception {
+ final AtomicReference uriHolder = new AtomicReference();
+ HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("http://test/{foo}");
+
+ handler.setRequestFactory(new SimpleClientHttpRequestFactory() {
+ @Override
+ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
+ uriHolder.set(uri);
+ throw new RuntimeException("intentional");
+ }
+ });
+ handler.setBeanFactory(mock(BeanFactory.class));
+ handler.setUriVariablesExpression(new SpelExpressionParser().parseExpression("headers.uriVariables"));
+ handler.afterPropertiesSet();
+
+ Map expressions = new HashMap();
+ expressions.put("foo", "bar");
+
+ Map expressionsMap = ExpressionEvalMap.from(expressions).usingSimpleCallback().build();
+
+ try {
+ handler.handleMessage(MessageBuilder.withPayload("test").setHeader("uriVariables", expressionsMap).build());
+ fail("Exception expected.");
+ }
+ catch (Exception e) {
+ assertEquals("intentional", e.getCause().getMessage());
+ }
+
assertEquals("http://test/bar", uriHolder.get().toString());
}
diff --git a/src/reference/docbook/http.xml b/src/reference/docbook/http.xml
index 8ef55aeb5e..e1d3e8b2fc 100644
--- a/src/reference/docbook/http.xml
+++ b/src/reference/docbook/http.xml
@@ -520,6 +520,43 @@ By default the HTTP request will be generated using an instance of Si
method will be invoked on the payload object of the Message and the result
of that method will be used as the value for the URI variable named 'zipCode'.
+
+ Since Spring Integration 3.0 , HTTP Outbound Endpoints support the
+ uri-variables-expression attribute to specify an Expression
+ which should be evaluated, resulting in a
+ Map for all URI variable placeholders within the URL template. It provides
+ a mechanism whereby different variable expressions can be used, based on the outbound message.
+ This attribute is mutually exclusive with the <uri-variable/> sub-element:
+ ]]>
+where uriVariablesBean might be:
+ populate(Object payload) {
+ Map variables = new HashMap();
+ if (payload instanceOf String.class)) {
+ variables.put("foo", "foo"));
+ }
+ else {
+ variables.put("foo", EXPRESSION_PARSER.parseExpression("headers.bar"));
+ }
+ return variables;
+ }
+
+}]]>
+
+
+ The uri-variables-expression must evaluate to a Map .
+ The values of the Map must be instances of
+ String or Expression .
+ This Map is provided to an ExpressionEvalMap for further resolution of URI variable placeholders
+ using those expressions in the context of the outbound Message .
+
Controlling URI Encoding
diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml
index 520b7c76c0..3f32602196 100644
--- a/src/reference/docbook/whats-new.xml
+++ b/src/reference/docbook/whats-new.xml
@@ -431,6 +431,13 @@
#requestHeaders and #cookies . These variables are available in
both payload and header expressions.
+
+ Outbound Endpoint 'uri-variables-expression' - HTTP Outbound Endpoints
+ now support the uri-variables-expression attribute to specify
+ an Expression to evaluate a Map
+ for all URI variable placeholders within URL template. This allows selection of a different
+ map of expressions based on the outgoing message.
+