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:
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* <inbound-channel-adapter> or <inbound-gateway> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user