Merge pull request #53 from olegz/INT-1677

refactored the UriPathHandlerMapping to only provide an implementation of the abstract method
  changed uriVariables to pathVariables
  added pathVariables and requestParams as variables to the EvaluationContext
  setting the HttpEntity as the rootObject of the EvauationContext (it includes the converted 'body' if present and 'headers')
  removed requirement for an ID, polished schema, added more tests, and tested with server
  finished the namespace support for payload-expression attribute and header sub-element, added parser test
  updated 2.1 schema with new 'payload-expression' attribute as well as 'header' elements
  polished UriPathHandlerMapping to address comments from the review
  added UriPathHandlerMapping to aid in support of the 'path' attribute
  fixed thread safety for EvaluationContext since it has to be created per request due to the fact that we are adding request data to it
  added support for SpEL expressions
This commit is contained in:
Mark Fisher
2011-09-02 16:02:59 -04:00
8 changed files with 506 additions and 21 deletions

View File

@@ -33,6 +33,6 @@ public interface HeaderMapper<T> {
void fromHeaders(MessageHeaders headers, T target);
Map<String, ?> toHeaders(T source);
<V> Map<String, V> toHeaders(T source);
}

View File

@@ -16,14 +16,21 @@
package org.springframework.integration.http.config;
import java.util.List;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.ExpressionFactoryBean;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
@@ -60,8 +67,9 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
id = element.getAttribute("name");
}
if (!StringUtils.hasText(id)) {
parserContext.getReaderContext().error("The 'id' or 'name' is required.", element);
id = BeanDefinitionReaderUtils.generateBeanName(definition, parserContext.getRegistry());
}
return id;
}
@@ -76,6 +84,32 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
}
builder.addPropertyReference("requestChannel", inputChannelRef);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "path");
String payloadExpression = element.getAttribute("payload-expression");
if (StringUtils.hasText(payloadExpression)){
RootBeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(payloadExpression);
builder.addPropertyValue("payloadExpression", expressionDef);
}
List<Element> headerElements = DomUtils.getChildElementsByTagName(element, "header");
if (!CollectionUtils.isEmpty(headerElements)) {
ManagedMap<String, Object> headerElementsMap = new ManagedMap<String, Object>();
for (Element headerElement : headerElements) {
String name = headerElement.getAttribute("name");
String expression = headerElement.getAttribute("expression");
if (StringUtils.hasText(expression)){
RootBeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expression);
headerElementsMap.put(name, expressionDef);
}
}
builder.addPropertyValue("headerExpressions", headerElementsMap);
}
if (this.expectReply) {
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-timeout");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -27,6 +27,13 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.MapAccessor;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
@@ -50,13 +57,18 @@ import org.springframework.integration.http.multipart.MultipartHttpInputMessage;
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
import org.springframework.integration.mapping.HeaderMapper;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.util.UrlPathHelper;
/**
* Base class for HTTP request handling endpoints.
@@ -79,10 +91,11 @@ import org.springframework.web.servlet.DispatcherServlet;
* <code>false</code>.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
* @since 2.0
*/
abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySupport {
private static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder",
HttpRequestHandlingEndpointSupport.class.getClassLoader());
@@ -104,9 +117,19 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
private final boolean expectReply;
private volatile String path;
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
private final PathMatcher pathMatcher = new AntPathMatcher();
private volatile boolean extractReplyPayload = true;
private volatile MultipartResolver multipartResolver;
private volatile Expression payloadExpression;
private volatile Map<String, Expression> headerExpressions;
public HttpRequestHandlingEndpointSupport() {
this(true);
@@ -141,6 +164,39 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
return expectReply;
}
/**
* Set the path template for which this endpoint expects requests.
* May include path variable {keys} to match against.
*/
public void setPath(String path) {
this.path = path;
}
String getPath() {
return path;
}
/**
* 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.
*/
public void setPayloadExpression(Expression payloadExpression) {
this.payloadExpression = payloadExpression;
}
/**
* 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.
*/
public void setHeaderExpressions(Map<String, Expression> headerExpressions) {
this.headerExpressions = headerExpressions;
}
/**
* Set the message body converters to use. These converters are used to convert from and to HTTP requests and
* responses.
@@ -244,28 +300,71 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
* Handles the HTTP request by generating a Message and sending it to the request channel. If this gateway's
* 'expectReply' property is true, it will also generate a response from the reply Message once received.
*/
protected final Object doHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
throws IOException {
@SuppressWarnings({ "rawtypes", "unchecked" })
protected final Object doHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
try {
ServletServerHttpRequest request = this.prepareRequest(servletRequest);
if (!this.supportedMethods.contains(request.getMethod())) {
servletResponse.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return null;
}
Object payload = null;
Object requestBody = null;
if (this.isReadable(request)) {
payload = this.generatePayloadFromRequestBody(request);
requestBody = this.extractRequestBody(request);
}
else {
payload = this.convertParameterMap(servletRequest.getParameterMap());
HttpEntity httpEntity = new HttpEntity(requestBody, request.getHeaders());
StandardEvaluationContext evaluationContext = this.createEvaluationContext();
evaluationContext.setRootObject(httpEntity);
LinkedMultiValueMap<String, String> requestParams = this.convertParameterMap(servletRequest.getParameterMap());
evaluationContext.setVariable("requestParams", requestParams);
if (StringUtils.hasText(this.path)) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(servletRequest);
Map pathVariables = this.pathMatcher.extractUriTemplateVariables(this.path, lookupPath);
if (!pathVariables.isEmpty()) {
if (logger.isDebugEnabled()) {
logger.debug("Mapped path variables: " + pathVariables);
}
evaluationContext.setVariable("pathVariables", pathVariables);
}
}
Map<String, ?> headers = this.headerMapper.toHeaders(request.getHeaders());
Message<?> message = MessageBuilder.withPayload(payload).copyHeaders(headers).setHeader(
org.springframework.integration.http.HttpHeaders.REQUEST_URL, request.getURI().toString())
Map<String, Object> headers = this.headerMapper.toHeaders(request.getHeaders());
Object payload = null;
if (this.payloadExpression != null) {
// create payload based on SpEL
payload = this.payloadExpression.getValue(evaluationContext);
}
if (!CollectionUtils.isEmpty(this.headerExpressions)) {
for (String headerName : this.headerExpressions.keySet()) {
Expression headerExpression = this.headerExpressions.get(headerName);
Object headerValue = headerExpression.getValue(evaluationContext);
if (headerValue != null) {
headers.put(headerName, headerValue);
}
}
}
if (payload == null) {
if (requestBody != null) {
payload = requestBody;
}
else {
payload = requestParams;
}
}
Message<?> message = MessageBuilder.withPayload(payload).copyHeaders(headers)
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_URL,
request.getURI().toString())
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_METHOD,
request.getMethod().toString()).setHeader(
org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL,
request.getMethod().toString())
.setHeader(org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL,
servletRequest.getUserPrincipal()).build();
Object reply = null;
if (this.expectReply) {
reply = this.sendAndReceiveMessage(message);
@@ -273,7 +372,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
this.headerMapper.fromHeaders(((Message<?>) reply).getHeaders(), response.getHeaders());
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(((Message<?>) reply).getHeaders());
if (httpStatus != null){
if (httpStatus != null) {
response.setStatusCode(httpStatus);
}
response.close();
@@ -348,7 +447,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
}
@SuppressWarnings({"unchecked", "rawtypes"})
private Object generatePayloadFromRequestBody(ServletServerHttpRequest request) throws IOException {
private Object extractRequestBody(ServletServerHttpRequest request) throws IOException {
MediaType contentType = request.getHeaders().getContentType();
Class<?> expectedType = this.requestPayloadType;
if (expectedType == null) {
@@ -378,5 +477,18 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
}
return httpStatus;
}
private StandardEvaluationContext createEvaluationContext(){
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
evaluationContext.addPropertyAccessor(new MapAccessor());
BeanFactory beanFactory = this.getBeanFactory();
if (beanFactory != null) {
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
ConversionService conversionService = this.getConversionService();
if (conversionService != null) {
evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService));
}
return evaluationContext;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2011 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
*
* http://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.inbound;
import org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping;
/**
* A {@link org.springframework.web.servlet.HandlerMapping} implementation that matches
* against the value of the 'path' attribute, if present, on a Spring Integration HTTP
* &lt;inbound-channel-adapter&gt; or &lt;inbound-gateway&gt; element.
*
* @author Oleg Zhurakousky
* @author Mark Fisher
* @since 2.1
*/
public class UriPathHandlerMapping extends AbstractDetectingUrlHandlerMapping {
@Override
protected String[] determineUrlsForHandler(String beanName) {
String[] urls = null;
Class<?> beanClass = getApplicationContext().getType(beanName);
if (HttpRequestHandlingEndpointSupport.class.isAssignableFrom(beanClass)) {
HttpRequestHandlingEndpointSupport endpoint = getApplicationContext().getBean(beanName, HttpRequestHandlingEndpointSupport.class);
String path = endpoint.getPath();
if (path != null) {
urls = new String[]{path};
}
}
return urls;
}
}

View File

@@ -20,8 +20,18 @@
Defines an inbound HTTP-based Channel Adapter.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="header" type="headerType" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
[DEPRECATED since v2.1] Use 'path' attribute if you want to specify the path or
'id' attribute if you simply want to identify this component
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string" use="required">
<xsd:annotation>
<xsd:appinfo>
@@ -57,6 +67,20 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="payload-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to specify SpEL expression to construct a Message payload
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to specify URI path (e.g., /orderId/{order})
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="error-code" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
@@ -116,6 +140,9 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="gatewayType">
<xsd:sequence>
<xsd:element name="header" type="headerType" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="extract-reply-payload" type="xsd:string" default="true" />
<xsd:attribute name="supported-methods" type="xsd:string" />
@@ -135,6 +162,20 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="payload-expression" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to specify SpEL expression to construct a Message payload
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="path" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Allows you to specify URI path (e.g., /orderId/{order})
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="error-code" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
@@ -493,6 +534,28 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="headerType">
<xsd:annotation>
<xsd:documentation><![CDATA[
Expression to be evaluated against the ServletRequest(makes BODY and Headers available) as well as URI Variables (e.g., foo/bar/{id}).
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="name" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
Name of the Message Header
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="expression" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
Expression to be evaluated to determine the value of the header.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:simpleType name="httpMethodEnumeration">
<xsd:restriction base="xsd:token">

View File

@@ -26,5 +26,28 @@
<inbound-channel-adapter id="withMappedHeaders" channel="requests"
mapped-request-headers="foo,bar"/>
<inbound-channel-adapter id="inboundAdapterWithExpressions"
path="/fname/{f}/lname/{l}"
channel="requests"
mapped-request-headers="foo,bar"
payload-expression="#pathVariables.f">
<header name="lname" expression="#pathVariables.l"/>
</inbound-channel-adapter>
<inbound-channel-adapter name="/fname/{blah}/lname/{boo}"
path="/fname/{f}/lname/{l}"
channel="requests"
mapped-request-headers="foo,bar"
payload-expression="#pathVariables.f">
<header name="lname" expression="#pathVariables.l"/>
</inbound-channel-adapter>
<inbound-channel-adapter name="/fname/{f}/lname/{l}"
channel="requests"
mapped-request-headers="foo,bar"
payload-expression="#pathVariables.f">
<header name="lname" expression="#pathVariables.l"/>
</inbound-channel-adapter>
</beans:beans>

View File

@@ -35,6 +35,8 @@ import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.integration.Message;
@@ -46,6 +48,7 @@ import org.springframework.integration.http.inbound.HttpRequestHandlingMessaging
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.annotation.ExpectedException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.MultiValueMap;
@@ -72,7 +75,18 @@ public class HttpInboundChannelAdapterParserTests {
@Autowired
private HttpRequestHandlingMessagingGateway withMappedHeaders;
@Autowired
private HttpRequestHandlingMessagingGateway inboundAdapterWithExpressions;
@Autowired
@Qualifier("/fname/{blah}/lname/{boo}")
private HttpRequestHandlingMessagingGateway inboundAdapterWithNameAndExpressions;
@Autowired
@Qualifier("/fname/{f}/lname/{l}")
private HttpRequestHandlingMessagingGateway inboundAdapterWithNameNoPath;
@Autowired
private HttpRequestHandlingController inboundController;
@@ -113,6 +127,72 @@ public class HttpInboundChannelAdapterParserTests {
assertEquals("foo", map.get("foo"));
assertEquals("bar", map.get("bar"));
}
@Test
// INT-1677
public void withExpressions() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("text/plain");
request.setParameter("foo", "bar");
request.setContent("hello".getBytes());
request.setRequestURI("/fname/bill/lname/clinton");
MockHttpServletResponse response = new MockHttpServletResponse();
inboundAdapterWithExpressions.handleRequest(request, response);
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Message<?> message = requests.receive(0);
assertNotNull(message);
Object payload = message.getPayload();
assertTrue(payload instanceof String);
assertEquals("bill", payload);
assertEquals("clinton", message.getHeaders().get("lname"));
}
@Test // ensure that 'path' takes priority over name
// INT-1677
public void withNameAndExpressionsAndPath() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("text/plain");
request.setParameter("foo", "bar");
request.setContent("hello".getBytes());
request.setRequestURI("/fname/bill/lname/clinton");
MockHttpServletResponse response = new MockHttpServletResponse();
inboundAdapterWithNameAndExpressions.handleRequest(request, response);
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Message<?> message = requests.receive(0);
assertNotNull(message);
Object payload = message.getPayload();
assertTrue(payload instanceof String);
assertEquals("bill", payload);
assertEquals("clinton", message.getHeaders().get("lname"));
}
@Test
// INT-1677
@ExpectedException(SpelEvaluationException.class)
public void withNameAndExpressionsNoPath() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("text/plain");
request.setParameter("foo", "bar");
request.setContent("hello".getBytes());
request.setRequestURI("/fname/bill/lname/clinton");
MockHttpServletResponse response = new MockHttpServletResponse();
inboundAdapterWithNameNoPath.handleRequest(request, response);
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Message<?> message = requests.receive(0);
assertNotNull(message);
Object payload = message.getPayload();
assertTrue(payload instanceof String);
assertEquals("hello", payload); // default payload
assertNull(message.getHeaders().get("lname"));
}
@Test
public void getRequestNotAllowed() throws Exception {

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2002-2011 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
*
* http://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.inbound;
import java.util.Map;
import org.junit.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessagingException;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.http.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import static org.junit.Assert.assertEquals;
/**
* @author Oleg Zhurakousky
*/
public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
private static ExpressionParser PARSER = new SpelExpressionParser();
@Test
public void withoutExpression() throws Exception {
DirectChannel echoChannel = new DirectChannel();
echoChannel.subscribe(new MessageHandler() {
public void handleMessage(Message<?> message) throws MessagingException {
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
replyChannel.send(message);
}
});
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setContentType("text/plain");
request.setParameter("foo", "bar");
request.setContent("hello".getBytes());
request.setRequestURI("/fname/bill/lname/clinton");
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
gateway.setPath("/fname/{f}/lname/{l}");
gateway.setRequestChannel(echoChannel);
MockHttpServletResponse response = new MockHttpServletResponse();
Object result = gateway.doHandleRequest(request, response);
assertEquals("hello", result);
}
@Test
public void withPayloadExpressionPointingToPathVariable() throws Exception {
DirectChannel echoChannel = new DirectChannel();
echoChannel.subscribe(new MessageHandler() {
public void handleMessage(Message<?> message) throws MessagingException {
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
replyChannel.send(message);
}
});
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.setMethod("POST");
request.setContentType("text/plain");
request.setParameter("foo", "bar");
request.setContent("hello".getBytes());
request.setRequestURI("/fname/bill/lname/clinton");
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
gateway.setPath("/fname/{f}/lname/{l}");
gateway.setRequestChannel(echoChannel);
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables.f"));
Object result = gateway.doHandleRequest(request, response);
assertEquals("bill", result);
}
@SuppressWarnings("unchecked")
@Test
public void withoutPayloadExpressionPointingToUriVariables() throws Exception {
DirectChannel echoChannel = new DirectChannel();
echoChannel.subscribe(new MessageHandler() {
public void handleMessage(Message<?> message) throws MessagingException {
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
replyChannel.send(message);
}
});
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.setMethod("POST");
request.setContentType("text/plain");
request.setParameter("foo", "bar");
request.setContent("hello".getBytes());
request.setRequestURI("/fname/bill/lname/clinton");
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
gateway.setPath("/fname/{f}/lname/{l}");
gateway.setRequestChannel(echoChannel);
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables"));
Object result = gateway.doHandleRequest(request, response);
assertEquals("bill", ((Map<String, Object>)result).get("f"));
}
}