INT-1362 HTTP Inbound: Additional EvalCtx Vars.

JIRA: https://jira.springsource.org/browse/INT-1362, https://jira.springsource.org/browse/INT-2469

* Add to the `EvaluationContext` of HTTP Inbound Endpoints additional request variables
* Tests and documentation

INT-2669: Mention SpEL variables in JavaDocs

JIRA: https://jira.springsource.org/browse/INT-2669

INT-1362 Doc Polishing
This commit is contained in:
Artem Bilan
2013-10-08 15:44:00 +03:00
committed by Gary Russell
parent d06c1c269d
commit d5e8e352b6
8 changed files with 175 additions and 15 deletions

View File

@@ -19,10 +19,12 @@ package org.springframework.integration.http.inbound;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -65,6 +67,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.DispatcherServlet;
@@ -210,8 +213,15 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
/**
* Specifies a SpEL expression to evaluate in order to generate the Message payload.
* The EvaluationContext will be populated with an HttpEntity instance as the root object,
* and it may contain one or both of the <code>#pathVariables</code> and
* <code>#queryParameters</code> variables if present. Those variables' values are Maps.
* and it may contain variables:
* <ul>
* <li><code>#pathVariables</code></li>
* <li><code>#requestParams</code></li>
* <li><code>#requestAttributes</code></li>
* <li><code>#requestHeaders</code></li>
* <li><code>#matrixVariables</code></li>
* <li><code>#cookies</code>
* </ul>
*/
public void setPayloadExpression(Expression payloadExpression) {
this.payloadExpression = payloadExpression;
@@ -221,8 +231,15 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
* Specifies a Map of SpEL expressions to evaluate in order to generate the Message headers.
* The keys in the map will be used as the header names. When evaluating the expression,
* the EvaluationContext will be populated with an HttpEntity instance as the root object,
* and it may contain one or both of the <code>#pathVariables</code> and
* <code>#queryParameters</code> variables if present. Those variables' values are Maps.
* and it may contain variables:
* <ul>
* <li><code>#pathVariables</code></li>
* <li><code>#requestParams</code></li>
* <li><code>#requestAttributes</code></li>
* <li><code>#requestHeaders</code></li>
* <li><code>#matrixVariables</code></li>
* <li><code>#cookies</code>
* </ul>
*/
public void setHeaderExpressions(Map<String, Expression> headerExpressions) {
this.headerExpressions = headerExpressions;
@@ -379,9 +396,22 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
StandardEvaluationContext evaluationContext = this.createEvaluationContext();
evaluationContext.setRootObject(httpEntity);
evaluationContext.setVariable("requestAttributes", RequestContextHolder.currentRequestAttributes());
MultiValueMap<String, String> requestParams = this.convertParameterMap(servletRequest.getParameterMap());
evaluationContext.setVariable("requestParams", requestParams);
evaluationContext.setVariable("requestHeaders", new ServletServerHttpRequest(servletRequest).getHeaders());
Cookie[] requestCookies = servletRequest.getCookies();
if (!ObjectUtils.isEmpty(requestCookies)) {
Map<String, Cookie> cookies = new HashMap<String, Cookie>(requestCookies.length);
for (Cookie requestCookie : requestCookies) {
cookies.put(requestCookie.getName(), requestCookie);
}
evaluationContext.setVariable("cookies", cookies);
}
Map<String, String> pathVariables =
(Map<String, String>) servletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
@@ -392,6 +422,17 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
evaluationContext.setVariable("pathVariables", pathVariables);
}
//TODO change it to HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE after upgrade to Spring 4.0
Map<String, MultiValueMap<String, String>> matrixVariables =
(Map<String, MultiValueMap<String, String>>) servletRequest.getAttribute(HandlerMapping.class.getName() + ".matrixVariables");
if (!CollectionUtils.isEmpty(matrixVariables)) {
if (logger.isDebugEnabled()) {
logger.debug("Mapped matrix variables: " + matrixVariables);
}
evaluationContext.setVariable("matrixVariables", matrixVariables);
}
Map<String, Object> headers = this.headerMapper.toHeaders(request.getHeaders());
Object payload = null;
if (this.payloadExpression != null) {

View File

@@ -26,8 +26,16 @@
request-channel="toLowerCaseChannel"
payload-expression="#pathVariables.value">
<int-http:request-mapping headers="toLowerCase"/>
<int-http:header name="requestAttributes" expression="#requestAttributes"/>
<int-http:header name="requestParams" expression="#requestParams"/>
<int-http:header name="requestHeaders" expression="#requestHeaders"/>
<int-http:header name="matrixVariables" expression="#matrixVariables"/>
<int-http:header name="cookies" expression="#cookies"/>
</int-http:inbound-gateway>
<int:publish-subscribe-channel id="toLowerCaseChannel"/>
<int:transformer input-channel="toLowerCaseChannel" expression="payload.toLowerCase()"/>
<int-http:inbound-gateway path="#{TEST_PATH}"

View File

@@ -17,22 +17,36 @@
package org.springframework.integration.http.inbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.integration.Message;
import org.springframework.integration.MessageHeaders;
import org.springframework.integration.MessagingException;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.core.SubscribableChannel;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
@@ -53,6 +67,9 @@ public class Int2312RequestMappingIntegrationTests {
@Autowired
private HandlerMapping handlerMapping;
@Autowired
private SubscribableChannel toLowerCaseChannel;
private HandlerAdapter handlerAdapter = new HttpRequestHandlerAdapter();
@Test
@@ -77,22 +94,57 @@ public class Int2312RequestMappingIntegrationTests {
@Test
@SuppressWarnings("unchecked")
//INT-1362
public void testURIVariablesAndHeaders() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
String testRequest = "aBc";
// TODO test it after upgrade to Spring 4.0
// String testRequest = "aBc;q1=1;q2=2";
String requestURI = "/test/" + testRequest;
request.setRequestURI(requestURI);
request.setContentType("text/plain");
final Map<String, String> params = new HashMap<String, String>();
params.put("foo", "bar");
request.setParameters(params);
request.setContent("hello".getBytes());
final Cookie cookie = new Cookie("foo", "bar");
request.setCookies(cookie);
request.addHeader("toLowerCase", true);
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
Map<String, String> uriTemplateVariables =
new AntPathMatcher().extractUriTemplateVariables(TEST_PATH, requestURI);
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
//See org.springframework.web.servlet.FrameworkServlet#initContextHolders
final RequestAttributes attributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(attributes);
this.toLowerCaseChannel.subscribe(new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
MessageHeaders headers = message.getHeaders();
assertEquals(attributes, headers.get("requestAttributes"));
Object requestParams = headers.get("requestParams");
assertNotNull(requestParams);
assertEquals(params, ((MultiValueMap<String, String>) requestParams).toSingleValueMap());
// TODO test it after upgrade to Spring 4.0
// assertEquals(matrixVariables, headers.get("matrixVariables"));
Object requestHeaders = headers.get("requestHeaders");
assertNotNull(requestParams);
assertEquals(MediaType.TEXT_PLAIN, ((HttpHeaders) requestHeaders).getContentType());
Map<String, Cookie> cookies = (Map<String, Cookie>) headers.get("cookies");
assertEquals(1, cookies.size());
Cookie foo = cookies.get("foo");
assertNotNull(foo);
assertEquals(cookie, foo);
}
});
MockHttpServletResponse response = new MockHttpServletResponse();
request.addHeader("toLowerCase", true);
Object handler = this.handlerMapping.getHandler(request).getHandler();
this.handlerAdapter.handle(request, response, handler);
final String testResponse = response.getContentAsString();