INT-2312 Add HTTP RequestMapping support
The general idea is to use Spring-MVC as much as possible. * Introduce `RequestMapping`, `IntegrationRequestMappingHandlerMapping` * Introduce XSD nested element `<request-mapping>` for HTTP Inbound Endpoints * Introduce `inboundCommonAttributes` XSD attributeGroup for HTTP Inbound Endpoints * Introduce `IntegrationNamespaceUtils#createExpressionDefIfAttributeDefined` & `IntegrationNamespaceUtils#createDirectChannel` * Remove deprecated `name` attribute * Remove `UriPathHandlerMapping` as superseded by `IntegrationRequestMappingHandlerMapping` * Add documentation for `<request-mapping>` - Add description to Reference Manual about `<request-mapping>` * Add documentation to section 'What's new' * Add additional test for `<request-mapping>` JIRA: https://jira.springsource.org/browse/INT-2312, https://jira.springsource.org/browse/INT-2619 Additional changes: * INT-2528 Remove deprecations in HTTP module - JIRA: https://jira.springsource.org/browse/INT-2528 * Add Jackson 2 support for HTTP-inbound * Using Jackson 2 HttpMessageConverter if Jackson 2 is available in classpath * Make `RequestMapping` public * Introduce `HttpContextUtils` and move `HANDLER_MAPPING_BEAN_NAME` to it * Revert and deprecate public API * Improve JavaDocs * Improve Reference Manual Thanks also to Biju Kunjummen for his incorporated commit.
This commit is contained in:
committed by
Gunnar Hillert
parent
28131aab32
commit
6a9cb75668
@@ -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.
|
||||
@@ -17,48 +17,51 @@
|
||||
package org.springframework.integration.http.config;
|
||||
|
||||
import java.util.List;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
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.expression.common.LiteralExpression;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.config.ExpressionFactoryBean;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.http.inbound.HttpRequestHandlingController;
|
||||
import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway;
|
||||
import org.springframework.integration.http.inbound.IntegrationRequestMappingHandlerMapping;
|
||||
import org.springframework.integration.http.inbound.RequestMapping;
|
||||
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
|
||||
import org.springframework.integration.http.support.HttpContextUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for the 'inbound-channel-adapter' and 'inbound-gateway' elements
|
||||
* of the 'http' namespace. The constructor's boolean value specifies whether
|
||||
* a reply is to be expected. This value should be 'false' for the
|
||||
* 'inbound-channel-adapter' and 'true' for the 'inbound-gateway'.
|
||||
* This parser also registers a global Spring-MVC infrastructure bean for
|
||||
* {@link IntegrationRequestMappingHandlerMapping};
|
||||
* see {@link #registerRequestMappingHandlerMappingIfNecessary}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Biju Kunjummen
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private final boolean expectReply;
|
||||
|
||||
|
||||
public HttpInboundEndpointParser(boolean expectReply) {
|
||||
this.expectReply = expectReply;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return element.hasAttribute("view-name") || element.hasAttribute("view-expression")
|
||||
@@ -70,13 +73,10 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = element.getAttribute("name");
|
||||
} else {
|
||||
if (!element.hasAttribute(getInputChannelAttributeName())) {
|
||||
// the created channel will get the 'id', so the adapter's bean name includes a suffix
|
||||
id = id + ".adapter";
|
||||
}
|
||||
|
||||
if (!element.hasAttribute(getInputChannelAttributeName())) {
|
||||
// the created channel will get the 'id', so the adapter's bean name includes a suffix
|
||||
id = id + ".adapter";
|
||||
}
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = BeanDefinitionReaderUtils.generateBeanName(definition, parserContext.getRegistry());
|
||||
@@ -94,20 +94,18 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
if (this.expectReply) {
|
||||
parserContext.getReaderContext().error(
|
||||
"a '" + inputChannelAttributeName + "' reference is required", element);
|
||||
} else {
|
||||
inputChannelRef = createDirectChannel(element, parserContext);
|
||||
}
|
||||
else {
|
||||
inputChannelRef = IntegrationNamespaceUtils.createDirectChannel(element, parserContext);
|
||||
}
|
||||
}
|
||||
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);
|
||||
BeanDefinition payloadExpressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefIfAttributeDefined("payload-expression", element);
|
||||
if (payloadExpressionDef != null) {
|
||||
builder.addPropertyValue("payloadExpression", payloadExpressionDef);
|
||||
}
|
||||
|
||||
List<Element> headerElements = DomUtils.getChildElementsByTagName(element, "header");
|
||||
@@ -115,12 +113,12 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
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);
|
||||
String name = headerElement.getAttribute(NAME_ATTRIBUTE);
|
||||
BeanDefinition headerExpressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefIfAttributeDefined(IntegrationNamespaceUtils.EXPRESSION_ATTRIBUTE,
|
||||
headerElement);
|
||||
if (headerExpressionDef != null) {
|
||||
headerElementsMap.put(name, headerExpressionDef);
|
||||
}
|
||||
}
|
||||
builder.addPropertyValue("headerExpressions", headerElementsMap);
|
||||
@@ -135,71 +133,100 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "convert-exceptions");
|
||||
}
|
||||
else {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(
|
||||
builder, element, "send-timeout", "requestTimeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout", "requestTimeout");
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "supported-methods", "supportedMethodNames");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-payload-type");
|
||||
String viewName = element.getAttribute("view-name");
|
||||
String viewExpression = element.getAttribute("view-expression");
|
||||
boolean hasViewName = StringUtils.hasText(viewName);
|
||||
boolean hasViewExpression = StringUtils.hasText(viewExpression);
|
||||
if (hasViewName ? hasViewExpression : false) {
|
||||
parserContext.getReaderContext().error("Only one of 'view' or 'view-expression' is allowed", element);
|
||||
}
|
||||
if (hasViewName) {
|
||||
RootBeanDefinition expressionDef = new RootBeanDefinition(LiteralExpression.class);
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(viewName);
|
||||
builder.addPropertyValue("viewExpression", expressionDef);
|
||||
}
|
||||
else if (hasViewExpression) {
|
||||
RootBeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(viewExpression);
|
||||
|
||||
BeanDefinition expressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("view-name", "view-expression",
|
||||
parserContext, element, false);
|
||||
if (expressionDef != null) {
|
||||
builder.addPropertyValue("viewExpression", expressionDef);
|
||||
}
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "errors-key");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "error-code");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-converters");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "merge-with-default-converters");
|
||||
|
||||
|
||||
//IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "header-mapper");
|
||||
String headerMapper = element.getAttribute("header-mapper");
|
||||
|
||||
String mappedRequestHeaders = element.getAttribute("mapped-request-headers");
|
||||
String mappedResponseHeaders = element.getAttribute("mapped-response-headers");
|
||||
|
||||
boolean hasMappedRequestHeaders = StringUtils.hasText(mappedRequestHeaders);
|
||||
boolean hasMappedResponseHeaders = StringUtils.hasText(mappedResponseHeaders);
|
||||
|
||||
if (StringUtils.hasText(headerMapper)) {
|
||||
if (StringUtils.hasText(mappedRequestHeaders) || StringUtils.hasText(mappedResponseHeaders)) {
|
||||
if (hasMappedRequestHeaders || hasMappedResponseHeaders) {
|
||||
parserContext.getReaderContext().error("Neither 'mappped-request-headers' or 'mapped-response-headers' " +
|
||||
"attributes are allowed when a 'header-mapper' has been specified.", parserContext.extractSource(element));
|
||||
}
|
||||
builder.addPropertyReference("headerMapper", headerMapper);
|
||||
}
|
||||
else {
|
||||
BeanDefinitionBuilder headerMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.http.support.DefaultHttpHeaderMapper");
|
||||
BeanDefinitionBuilder headerMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition(DefaultHttpHeaderMapper.class);
|
||||
headerMapperBuilder.setFactoryMethod("inboundMapper");
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(headerMapperBuilder, element, "mapped-request-headers", "inboundHeaderNames");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(headerMapperBuilder, element, "mapped-response-headers", "outboundHeaderNames");
|
||||
if (hasMappedRequestHeaders) {
|
||||
headerMapperBuilder.addPropertyValue("inboundHeaderNames", mappedRequestHeaders);
|
||||
}
|
||||
if (hasMappedResponseHeaders) {
|
||||
headerMapperBuilder.addPropertyValue("outboundHeaderNames", mappedResponseHeaders);
|
||||
}
|
||||
|
||||
builder.addPropertyValue("headerMapper", headerMapperBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
BeanDefinition requestMappingDef = this.createRequestMapping(element);
|
||||
builder.addPropertyValue("requestMapping", requestMappingDef);
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-payload-type", "requestPayloadType");
|
||||
|
||||
this.registerRequestMappingHandlerMappingIfNecessary(parserContext);
|
||||
}
|
||||
|
||||
private String getInputChannelAttributeName() {
|
||||
return this.expectReply ? "request-channel" : "channel";
|
||||
}
|
||||
|
||||
private String createDirectChannel(Element element, ParserContext parserContext) {
|
||||
String channelId = element.getAttribute("id");
|
||||
if (!StringUtils.hasText(channelId)) {
|
||||
parserContext.getReaderContext().error("The channel-adapter's 'id' attribute is required when no 'channel' "
|
||||
+ "reference has been provided, because that 'id' would be used for the created channel.", element);
|
||||
private BeanDefinition createRequestMapping(Element element) {
|
||||
BeanDefinitionBuilder requestMappingDefBuilder = BeanDefinitionBuilder.genericBeanDefinition(RequestMapping.class);
|
||||
|
||||
String methods = element.getAttribute("supported-methods");
|
||||
if (StringUtils.hasText(methods)) {
|
||||
requestMappingDefBuilder.addPropertyValue("methods", methods.toUpperCase());
|
||||
}
|
||||
BeanDefinitionBuilder channelBuilder = BeanDefinitionBuilder.genericBeanDefinition(DirectChannel.class);
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(channelBuilder.getBeanDefinition(), channelId);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
|
||||
return channelId;
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(requestMappingDefBuilder, element, "path", "pathPatterns");
|
||||
|
||||
Element requestMappingElement = DomUtils.getChildElementByTagName(element, "request-mapping");
|
||||
|
||||
if (requestMappingElement != null) {
|
||||
for (String requestMappingAttribute : new String[]{"params", "headers", "consumes", "produces"}) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(requestMappingDefBuilder, requestMappingElement,
|
||||
requestMappingAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
return requestMappingDefBuilder.getRawBeanDefinition();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will auto-register an {@link IntegrationRequestMappingHandlerMapping}
|
||||
* which could also be overridden by the user by simply registering
|
||||
* a {@link IntegrationRequestMappingHandlerMapping} {@code <bean>} with 'id'
|
||||
* {@link HttpContextUtils#HANDLER_MAPPING_BEAN_NAME}.
|
||||
*/
|
||||
private void registerRequestMappingHandlerMappingIfNecessary(ParserContext parserContext) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(HttpContextUtils.HANDLER_MAPPING_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder requestMappingBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationRequestMappingHandlerMapping.class);
|
||||
requestMappingBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
requestMappingBuilder.addPropertyValue(IntegrationNamespaceUtils.ORDER, 0);
|
||||
BeanComponentDefinition requestMappingComponent =
|
||||
new BeanComponentDefinition(requestMappingBuilder.getBeanDefinition(), HttpContextUtils.HANDLER_MAPPING_BEAN_NAME);
|
||||
parserContext.registerBeanComponent(requestMappingComponent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa
|
||||
|
||||
/**
|
||||
* Namespace handler for Spring Integration's <em>http</em> namespace.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.2
|
||||
*/
|
||||
|
||||
@@ -59,24 +59,22 @@ import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.json.JacksonJsonUtils;
|
||||
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.util.ObjectUtils;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.MultipartResolver;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* Base class for HTTP request handling endpoints.
|
||||
* <p>
|
||||
* By default GET and POST requests are accepted, but the 'supportedMethods' property may be set to include others or
|
||||
* limit the options (e.g. POST only). A GET request will generate a payload containing its 'parameterMap' while a POST
|
||||
* By default GET and POST requests are accepted via a supplied default instance of {@link RequestMapping}.
|
||||
* A GET request will generate a payload containing its 'parameterMap' while a POST
|
||||
* request will be converted to a Message payload according to the registered {@link HttpMessageConverter}s. Several are
|
||||
* registered by default, but the list can be explicitly set via {@link #setMessageConverters(List)}.
|
||||
* <p>
|
||||
@@ -84,14 +82,14 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* reference to a {@code HeaderMapper<HttpHeaders>} implementation
|
||||
* to the {@link #setHeaderMapper(HeaderMapper)} method.
|
||||
* <p>
|
||||
* The behavior is "request/reply" by default. Pass <code>false</code> to the constructor to force send-only as opposed
|
||||
* The behavior is "request/reply" by default. Pass {@code false} to the constructor to force send-only as opposed
|
||||
* to sendAndReceive. Send-only means that as soon as the Message is created and passed to the
|
||||
* {@link #setRequestChannel(org.springframework.integration.MessageChannel) request channel}, a response will be
|
||||
* generated. Subclasses determine how that response is generated (e.g. simple status response or rendering a View).
|
||||
* <p>
|
||||
* In a request-reply scenario, the reply Message's payload will be extracted prior to generating a response by default.
|
||||
* To have the entire serialized Message available for the response, switch the {@link #extractReplyPayload} value to
|
||||
* <code>false</code>.
|
||||
* {@code false}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -101,20 +99,22 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySupport
|
||||
implements OrderlyShutdownCapable {
|
||||
implements OrderlyShutdownCapable {
|
||||
|
||||
private static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder",
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader());
|
||||
|
||||
|
||||
private static boolean romePresent = ClassUtils.isPresent("com.sun.syndication.feed.WireFeed",
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader());
|
||||
|
||||
private static final List<HttpMethod> nonReadableBodyHttpMethods =
|
||||
Arrays.asList(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS);
|
||||
|
||||
private final List<HttpMessageConverter<?>> defaultMessageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
|
||||
private volatile List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
|
||||
private volatile List<HttpMethod> supportedMethods = Arrays.asList(HttpMethod.GET, HttpMethod.POST);
|
||||
private volatile RequestMapping requestMapping = new RequestMapping();
|
||||
|
||||
private volatile Class<?> requestPayloadType = null;
|
||||
|
||||
@@ -126,12 +126,6 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
|
||||
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;
|
||||
@@ -162,27 +156,27 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
if (jaxb2Present) {
|
||||
this.defaultMessageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'Jaxb2RootElementHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
logger.debug("'Jaxb2RootElementHttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
}
|
||||
}
|
||||
if (JacksonJsonUtils.isJackson2Present()) {
|
||||
this.defaultMessageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'MappingJackson2HttpMessageConverter' was added to the 'messageConverters'.");
|
||||
logger.debug("'MappingJackson2HttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
}
|
||||
}
|
||||
else if (JacksonJsonUtils.isJacksonPresent()) {
|
||||
this.defaultMessageConverters.add(new MappingJacksonHttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'MappingJacksonHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
logger.debug("'MappingJacksonHttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
}
|
||||
}
|
||||
if (romePresent) {
|
||||
this.defaultMessageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.defaultMessageConverters.add(new RssChannelHttpMessageConverter());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("'AtomFeedHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
logger.debug("'RssChannelHttpMessageConverter' was added to the 'messageConverters'.");
|
||||
logger.debug("'AtomFeedHttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
logger.debug("'RssChannelHttpMessageConverter' was added to the 'defaultMessageConverters'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,13 +191,20 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
/**
|
||||
* Set the path template for which this endpoint expects requests.
|
||||
* May include path variable {keys} to match against.
|
||||
* @deprecated since 3.0 in favor of {@linkplain #requestMapping}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
this.requestMapping.setPathPatterns(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 3.0 in favor of {@linkplain #requestMapping}
|
||||
*/
|
||||
@Deprecated
|
||||
String getPath() {
|
||||
return path;
|
||||
String[] pathPatterns = this.requestMapping.getPathPatterns();
|
||||
return !ObjectUtils.isEmpty(pathPatterns) ? pathPatterns[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,23 +264,25 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the supported request method names for this gateway. By default, only GET and POST are supported.
|
||||
* Set the {@link RequestMapping} which allows you to specify a flexible RESTFul-mapping for this endpoint.
|
||||
*/
|
||||
public void setSupportedMethodNames(String... supportedMethods) {
|
||||
Assert.notEmpty(supportedMethods, "at least one supported method is required");
|
||||
HttpMethod[] methodArray = new HttpMethod[supportedMethods.length];
|
||||
for (int i = 0; i < methodArray.length; i++) {
|
||||
methodArray[i] = HttpMethod.valueOf(supportedMethods[i].toUpperCase());
|
||||
}
|
||||
this.supportedMethods = Arrays.asList(methodArray);
|
||||
public void setRequestMapping(RequestMapping requestMapping) {
|
||||
Assert.notNull(requestMapping, "requestMapping must not be null");
|
||||
this.requestMapping = requestMapping;
|
||||
}
|
||||
|
||||
public RequestMapping getRequestMapping() {
|
||||
return requestMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the supported request methods for this gateway. By default, only GET and POST are supported.
|
||||
* @deprecated since 3.0 in favor to {@linkplain #requestMapping}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setSupportedMethods(HttpMethod... supportedMethods) {
|
||||
Assert.notEmpty(supportedMethods, "at least one supported method is required");
|
||||
this.supportedMethods = Arrays.asList(supportedMethods);
|
||||
this.requestMapping.setMethods(supportedMethods);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,10 +311,6 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
this.multipartResolver = multipartResolver;
|
||||
}
|
||||
|
||||
protected boolean isShuttingDown() {
|
||||
return this.shuttingDown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return (this.expectReply) ? "http:inbound-gateway" : "http:inbound-channel-adapter";
|
||||
@@ -329,7 +328,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
BeanFactory beanFactory = this.getBeanFactory();
|
||||
if (this.multipartResolver == null && beanFactory != null) {
|
||||
try {
|
||||
MultipartResolver multipartResolver = this.getBeanFactory().getBean(
|
||||
MultipartResolver multipartResolver = beanFactory.getBean(
|
||||
DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using MultipartResolver [" + multipartResolver + "]");
|
||||
@@ -350,15 +349,10 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
this.validateSupportedMethods();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.shuttingDown = false;
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return a the response Message
|
||||
*/
|
||||
protected final Message<?> doHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
|
||||
@@ -370,15 +364,11 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private Message<?> actualDoHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
|
||||
this.activeCount.incrementAndGet();
|
||||
try {
|
||||
ServletServerHttpRequest request = this.prepareRequest(servletRequest);
|
||||
if (!this.supportedMethods.contains(request.getMethod())) {
|
||||
servletResponse.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
|
||||
return null;
|
||||
}
|
||||
|
||||
Object requestBody = null;
|
||||
if (this.isReadable(request)) {
|
||||
@@ -389,18 +379,17 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
StandardEvaluationContext evaluationContext = this.createEvaluationContext();
|
||||
evaluationContext.setRootObject(httpEntity);
|
||||
|
||||
LinkedMultiValueMap<String, String> requestParams = this.convertParameterMap(servletRequest.getParameterMap());
|
||||
MultiValueMap<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, String> pathVariables =
|
||||
(Map<String, String>) servletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
|
||||
if (!CollectionUtils.isEmpty(pathVariables)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapped path variables: " + pathVariables);
|
||||
}
|
||||
evaluationContext.setVariable("pathVariables", pathVariables);
|
||||
}
|
||||
|
||||
Map<String, Object> headers = this.headerMapper.toHeaders(request.getHeaders());
|
||||
@@ -430,7 +419,7 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
|
||||
MessageBuilder<?> messageBuilder = null;
|
||||
|
||||
if (payload instanceof Message<?>){
|
||||
if (payload instanceof Message<?>) {
|
||||
messageBuilder = MessageBuilder.fromMessage((Message<?>) payload).copyHeadersIfAbsent(headers);
|
||||
}
|
||||
else {
|
||||
@@ -471,15 +460,14 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
* Converts the reply message to the appropriate HTTP reply object and
|
||||
* sets up the {@link ServletServerHttpResponse}.
|
||||
*
|
||||
* @param response The ServletServerHttpResponse.
|
||||
* @param response The ServletServerHttpResponse.
|
||||
* @param replyMessage The reply message.
|
||||
* @return The message payload (if {@link #extractReplyPayload}) otherwise the
|
||||
* message.
|
||||
* @return The message payload (if {@link #extractReplyPayload}) otherwise the message.
|
||||
*/
|
||||
protected final Object setupResponseAndConvertReply(ServletServerHttpResponse response, Message<?> replyMessage) {
|
||||
|
||||
this.headerMapper.fromHeaders(replyMessage.getHeaders(), response.getHeaders());
|
||||
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(((Message<?>) replyMessage).getHeaders());
|
||||
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(replyMessage.getHeaders());
|
||||
if (httpStatus != null) {
|
||||
response.setStatusCode(httpStatus);
|
||||
}
|
||||
@@ -492,17 +480,6 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated As of release 2.2, please use {@link #setupResponseAndConvertReply(ServletServerHttpResponse, Message)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final Object setupResponseAndConvertReply(HttpServletResponse servletResponse, Message<?> replyMessage) {
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
Object reply = setupResponseAndConvertReply(response, replyMessage);
|
||||
response.close();
|
||||
return reply;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an instance of {@link ServletServerHttpRequest} from the raw {@link HttpServletRequest}. Also converts
|
||||
* the request into a multipart request to make multiparts available if necessary. If no multipart resolver is set,
|
||||
@@ -525,15 +502,13 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
* Checks if the request has a readable body (not a GET, HEAD, or OPTIONS request) and a Content-Type header.
|
||||
*/
|
||||
private boolean isReadable(ServletServerHttpRequest request) {
|
||||
HttpMethod method = request.getMethod();
|
||||
if (HttpMethod.GET.equals(method) || HttpMethod.HEAD.equals(method) || HttpMethod.OPTIONS.equals(method)) {
|
||||
return false;
|
||||
}
|
||||
return request.getHeaders().getContentType() != null;
|
||||
return !(CollectionUtils.containsInstance(nonReadableBodyHttpMethods, request.getMethod()))
|
||||
&& request.getHeaders().getContentType() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up any resources used by the given multipart request (if any).
|
||||
*
|
||||
* @param request current HTTP request
|
||||
* @see MultipartResolver#cleanupMultipart
|
||||
*/
|
||||
@@ -547,12 +522,12 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
* Converts a servlet request's parameterMap to a {@link MultiValueMap}.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private LinkedMultiValueMap<String, String> convertParameterMap(Map parameterMap) {
|
||||
LinkedMultiValueMap<String, String> convertedMap = new LinkedMultiValueMap<String, String>();
|
||||
for (Object key : parameterMap.keySet()) {
|
||||
String[] values = (String[]) parameterMap.get(key);
|
||||
private MultiValueMap<String, String> convertParameterMap(Map<String, String[]> parameterMap) {
|
||||
MultiValueMap<String, String> convertedMap = new LinkedMultiValueMap<String, String>(parameterMap.size());
|
||||
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
|
||||
String[] values = entry.getValue();
|
||||
for (String value : values) {
|
||||
convertedMap.add((String) key, value);
|
||||
convertedMap.add(entry.getKey(), value);
|
||||
}
|
||||
}
|
||||
return convertedMap;
|
||||
@@ -595,18 +570,28 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
}
|
||||
|
||||
private void validateSupportedMethods() {
|
||||
if (this.requestPayloadType != null){
|
||||
for (HttpMethod httpMethod : this.supportedMethods) {
|
||||
if (HttpMethod.GET.equals(httpMethod) || HttpMethod.HEAD.equals(httpMethod) || HttpMethod.OPTIONS.equals(httpMethod)){
|
||||
if (logger.isWarnEnabled()){
|
||||
logger.warn("The 'requestPayloadType' attribute will have no relevance for one of the specified HTTP methods '" +
|
||||
httpMethod + "'");
|
||||
}
|
||||
}
|
||||
if (this.requestPayloadType != null
|
||||
&& CollectionUtils.containsAny(nonReadableBodyHttpMethods, Arrays.asList(this.requestMapping.getMethods()))) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("The 'requestPayloadType' attribute will have no relevance for one of the specified HTTP methods '" +
|
||||
nonReadableBodyHttpMethods + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle
|
||||
*/
|
||||
@Override
|
||||
protected void doStart() {
|
||||
this.shuttingDown = false;
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
protected boolean isShuttingDown() {
|
||||
return this.shuttingDown;
|
||||
}
|
||||
|
||||
public int beforeShutdown() {
|
||||
this.shuttingDown = true;
|
||||
return this.activeCount.get();
|
||||
@@ -615,4 +600,5 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa
|
||||
public int afterShutdown() {
|
||||
return this.activeCount.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ import org.springframework.web.HttpRequestHandler;
|
||||
* (e.g. 200 OK).
|
||||
* <p>
|
||||
* The default supported request methods are GET and POST, but the list of values can be configured with the
|
||||
* {@link #supportedMethods} property. The payload generated from a GET request (or HEAD or OPTIONS if supported) will
|
||||
* {@link RequestMapping#methods} property. The payload generated from a GET request (or HEAD or OPTIONS if supported) will
|
||||
* be a {@link MultiValueMap} containing the parameter values. For a request containing a body (e.g. a POST), the type
|
||||
* of the payload is determined by the {@link #setRequestPayloadType(Class) request payload type}.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.mvc.condition.RequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
/**
|
||||
* The {@link org.springframework.web.servlet.HandlerMapping} implementation that
|
||||
* detects and registers {@link RequestMappingInfo}s for {@link HttpRequestHandlingEndpointSupport}
|
||||
* from a Spring Integration HTTP configuration of
|
||||
* {@code <inbound-channel-adapter/>} and {@code <inbound-gateway/>} elements.
|
||||
* <p/>
|
||||
* This class is automatically configured as bean in the application context on the parsing phase of
|
||||
* the {@code <inbound-channel-adapter/>} and {@code <inbound-gateway/>} elements, if there is none registered, yet.
|
||||
* However it can be configured as a regular bean with appropriate configuration for
|
||||
* {@link RequestMappingHandlerMapping}. It is recommended to have only one similar bean in the application context
|
||||
* using the 'id' {@link org.springframework.integration.http.support.HttpContextUtils#HANDLER_MAPPING_BEAN_NAME}.
|
||||
* <p/>
|
||||
* In most cases Spring MVC offers to configure Request Mapping via {@link org.springframework.stereotype.Controller}
|
||||
* and {@link org.springframework.web.bind.annotation.RequestMapping}.
|
||||
* That's why Spring MVC's Handler Mapping infrastructure relies on {@link org.springframework.web.method.HandlerMethod},
|
||||
* as different methods at the same {@link org.springframework.stereotype.Controller} user-class may have their own
|
||||
* {@link org.springframework.web.bind.annotation.RequestMapping}. On the other side, all Spring Integration HTTP Inbound
|
||||
* Endpoints are configured on the basis of the same {@link HttpRequestHandlingEndpointSupport} class and there is no
|
||||
* single {@link RequestMappingInfo} configuration without {@link org.springframework.web.method.HandlerMethod} in Spring MVC.
|
||||
* Accordingly {@link IntegrationRequestMappingHandlerMapping} is a some {@link org.springframework.web.servlet.HandlerMapping}
|
||||
* compromise implementation between method-level annotations and component-level (e.g. Spring Integration XML) configurations.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @see RequestMapping
|
||||
* @see RequestMappingHandlerMapping
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class IntegrationRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
|
||||
|
||||
private static final Method HANDLE_REQUEST_METHOD = ReflectionUtils.findMethod(HttpRequestHandler.class,
|
||||
"handleRequest", HttpServletRequest.class, HttpServletResponse.class);
|
||||
|
||||
private static final Method CREATE_REQUEST_MAPPING_INFO_METHOD;
|
||||
|
||||
static {
|
||||
/**
|
||||
* Need for full reuse {@link RequestMappingHandlerMapping}'s logic
|
||||
* and makes this class Spring MVC version independent.
|
||||
*/
|
||||
CREATE_REQUEST_MAPPING_INFO_METHOD = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class,
|
||||
"createRequestMappingInfo", org.springframework.web.bind.annotation.RequestMapping.class, RequestCondition.class);
|
||||
ReflectionUtils.makeAccessible(CREATE_REQUEST_MAPPING_INFO_METHOD);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean isHandler(Class<?> beanType) {
|
||||
return HttpRequestHandlingEndpointSupport.class.isAssignableFrom(beanType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
handler = handlerMethod.getBean();
|
||||
}
|
||||
return super.getHandlerExecutionChain(handler, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void detectHandlerMethods(Object handler) {
|
||||
if (handler instanceof String) {
|
||||
handler = this.getApplicationContext().getBean((String) handler);
|
||||
}
|
||||
RequestMappingInfo mapping = this.getMappingForEndpoint((HttpRequestHandlingEndpointSupport) handler);
|
||||
this.registerHandlerMethod(handler, HANDLE_REQUEST_METHOD, mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Created a {@link RequestMappingInfo} from a 'Spring Integration HTTP Inbound Endpoint' {@link RequestMapping}.
|
||||
*
|
||||
* @see RequestMappingHandlerMapping#getMappingForMethod
|
||||
*/
|
||||
private RequestMappingInfo getMappingForEndpoint(HttpRequestHandlingEndpointSupport endpoint) {
|
||||
final RequestMapping requestMapping = endpoint.getRequestMapping();
|
||||
|
||||
org.springframework.web.bind.annotation.RequestMapping requestMappingAnnotation =
|
||||
new org.springframework.web.bind.annotation.RequestMapping() {
|
||||
public String[] value() {
|
||||
return requestMapping.getPathPatterns();
|
||||
}
|
||||
|
||||
public RequestMethod[] method() {
|
||||
return requestMapping.getRequestMethods();
|
||||
}
|
||||
|
||||
public String[] params() {
|
||||
return requestMapping.getParams();
|
||||
}
|
||||
|
||||
public String[] headers() {
|
||||
return requestMapping.getHeaders();
|
||||
}
|
||||
|
||||
public String[] consumes() {
|
||||
return requestMapping.getConsumes();
|
||||
}
|
||||
|
||||
public String[] produces() {
|
||||
return requestMapping.getProduces();
|
||||
}
|
||||
|
||||
public Class<? extends Annotation> annotationType() {
|
||||
return org.springframework.web.bind.annotation.RequestMapping.class;
|
||||
}
|
||||
};
|
||||
|
||||
Object[] createRequestMappingInfoParams = new Object[]{requestMappingAnnotation, this.getCustomTypeCondition(endpoint.getClass())};
|
||||
return (RequestMappingInfo) ReflectionUtils.invokeMethod(CREATE_REQUEST_MAPPING_INFO_METHOD, this, createRequestMappingInfoParams);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.http.HttpMethod;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
* Class for mapping web requests onto specific {@link HttpRequestHandlingEndpointSupport}.
|
||||
* Provides direct mapping in terms of functionality compared to
|
||||
* {@link org.springframework.web.bind.annotation.RequestMapping}.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping
|
||||
* @see IntegrationRequestMappingHandlerMapping
|
||||
*/
|
||||
public class RequestMapping {
|
||||
|
||||
private String[] pathPatterns;
|
||||
|
||||
private HttpMethod[] methods = new HttpMethod[]{HttpMethod.GET, HttpMethod.POST};
|
||||
|
||||
private String[] params;
|
||||
|
||||
private String[] headers;
|
||||
|
||||
private String[] consumes;
|
||||
|
||||
private String[] produces;
|
||||
|
||||
public void setPathPatterns(String... pathPatterns) {
|
||||
this.pathPatterns = pathPatterns;
|
||||
}
|
||||
|
||||
public String[] getPathPatterns() {
|
||||
return pathPatterns;
|
||||
}
|
||||
|
||||
public void setMethods(HttpMethod... supportedMethods) {
|
||||
Assert.notEmpty(supportedMethods, "at least one supported methods is required");
|
||||
this.methods = supportedMethods;
|
||||
}
|
||||
|
||||
public HttpMethod[] getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public void setParams(String... params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public String[] getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setHeaders(String... headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public String[] getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public void setConsumes(String... consumes) {
|
||||
this.consumes = consumes;
|
||||
}
|
||||
|
||||
public String[] getConsumes() {
|
||||
return consumes;
|
||||
}
|
||||
|
||||
public void setProduces(String... produces) {
|
||||
this.produces = produces;
|
||||
}
|
||||
|
||||
public String[] getProduces() {
|
||||
return produces;
|
||||
}
|
||||
|
||||
public RequestMethod[] getRequestMethods() {
|
||||
RequestMethod[] requestMethods = new RequestMethod[this.methods.length];
|
||||
for (int i = 0; i < this.methods.length; i++) {
|
||||
requestMethods[i] = RequestMethod.valueOf(this.methods[i].name());
|
||||
}
|
||||
return requestMethods;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.support;
|
||||
|
||||
/**
|
||||
* Utility class for accessing HTTP integration components from the {@link org.springframework.beans.factory.BeanFactory}.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class HttpContextUtils {
|
||||
|
||||
/**
|
||||
* @see org.springframework.integration.http.config.HttpInboundEndpointParser
|
||||
*/
|
||||
public static final String HANDLER_MAPPING_BEAN_NAME = "integrationRequestMappingHandlerMapping";
|
||||
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/http" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
targetNamespace="http://www.springframework.org/schema/integration/http" elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
targetNamespace="http://www.springframework.org/schema/integration/http" elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration" schemaLocation="http://www.springframework.org/schema/integration/spring-integration-3.0.xsd" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration"
|
||||
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-3.0.xsd" />
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -16,172 +17,88 @@
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="inbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an inbound HTTP-based Channel Adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an inbound HTTP-based Channel Adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="header" type="headerType" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="request-mapping" type="requestMappingType" minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines configuration for org.springframework.integration.http.inbound.RequestMapping
|
||||
as RESTFul attributes for Spring Integration HTTP Inbound Endpoints.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="header" type="headerType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specifies a Message header as a result of expression evaluation
|
||||
against ServletRequest and URI Variables.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="integration:channelAdapterAttributes"/>
|
||||
<xsd:attribute name="name" type="xsd:string">
|
||||
<xsd:attribute name="send-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
[DEPRECATED since v2.1] Use the 'path' attribute if you want
|
||||
to specify the path or the 'id' attribute if you simply want
|
||||
to identify this component.
|
||||
|
||||
When using the 'path' attribute, please ensure to also
|
||||
declare a handler mapping bean of type
|
||||
'org.springframework.integration.http.inbound.UriPathHandlerMapping'.
|
||||
|
||||
This bean is used by the Spring MVC DispatcherServlet
|
||||
to evaluate which URL maps to which inbound endpoint.
|
||||
For more information please see the chapter on
|
||||
'Handler mappings' in the Spring Framework Reference
|
||||
Documentation.
|
||||
Maximum amount of time in milliseconds to wait when sending
|
||||
a message to the channel if such channel may block.
|
||||
For example, a Queue Channel can block until space
|
||||
is available if its maximum capacity has been reached.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-payload-type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Target type for payload that is the conversion result of the request.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="send-timeout" type="xsd:string" />
|
||||
<xsd:attribute name="supported-methods" type="xsd:string" />
|
||||
<xsd:attribute name="view-name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
View name to be resolved when rendering a response.
|
||||
This attribute is not allowed if there is a 'view-expression' attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="view-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
SpEL expression that resolves to a view to be resolved when rendering a response.
|
||||
The expression can resolve to a view name or View object.
|
||||
However, because there is no reply message, the
|
||||
'evaluationContext' for this expression is rather lightweight; it has a
|
||||
'BeanResolver' but no variables,
|
||||
so the usage of this attribute is somewhat limited.
|
||||
An example might be to resolve, at runtime, some scoped Bean that returns a
|
||||
view name or View object.
|
||||
This attribute is not allowed if there is a 'view-name' attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="errors-key" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
In the case that a view-name is specified this attribute can be used to
|
||||
override the default key of the Errors (if the request cannot be handled).
|
||||
Defaults to "errors" (similar to normal MVC
|
||||
usage).
|
||||
</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 the URI path (e.g., /orderId/{order})
|
||||
|
||||
When using the 'path' attribute, please ensure to also
|
||||
declare a handler mapping bean of type
|
||||
'org.springframework.integration.http.inbound.UriPathHandlerMapping'.
|
||||
|
||||
This bean is used by the Spring MVC DispatcherServlet to
|
||||
evaluate which URL maps to which inbound endpoint. For
|
||||
more information please see the chapter on 'Handler mappings'
|
||||
in the Spring Framework Reference Documentation.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-code" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
In the case that a view-name is specified this attribute can be used to
|
||||
override the default error code under which the handling exception is exposed.
|
||||
Defaults to
|
||||
"spring.integration.http.handler.error" and is supplied with 3
|
||||
parameters: the exception itself, its message and
|
||||
its stack trace as a String.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="message-converters" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
List of HttpMessageConverters for this Channel Adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="merge-with-default-converters" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Flag to indicate if the default converters should be registered after any
|
||||
custom converters. This flag is used only if message-converters
|
||||
are provided, otherwise all default converters will be registered.
|
||||
|
||||
Defaults to "false"
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="header-mapper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.mapping.HeaderMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-request-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Comma-separated list of names of HttpHeaders to be mapped from the HTTP request into the MessageHeaders..
|
||||
This can only be provided if the 'header-mapper' reference is not being set directly. The values in
|
||||
this list can also be simple patterns to be matched against the header names (e.g. "foo*" or "*foo").
|
||||
The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Request headers.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="inboundCommonAttributes" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="inbound-gateway">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an inbound HTTP-based Messaging Gateway.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an inbound HTTP-based Messaging Gateway.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="gatewayType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="header" type="headerType" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:sequence>
|
||||
<xsd:element name="request-mapping" minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines configuration for org.springframework.integration.http.inbound.RequestMapping
|
||||
as RESTFul attributes for Spring Integration HTTP Inbound Endpoints.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="requestMappingType">
|
||||
<xsd:attribute name="produces" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The producible media types of the mapped request, narrowing the primary mapping.
|
||||
The format is a sequence of media types ("text/plain", "application/*),
|
||||
with a request only mapped if the Accept matches one of these media types.
|
||||
Expressions can be negated by using the "!" operator, as in "!text/plain", which matches
|
||||
all requests with a Accept other than "text/plain".
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="header" type="headerType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specifies a Message header as a result of expression evaluation
|
||||
against ServletRequest and URI Variables.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="request-channel" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
@@ -190,87 +107,18 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
[DEPRECATED since v2.1] Use the 'path' attribute if you want
|
||||
to specify the path or the 'id' attribute if you simply want
|
||||
to identify this component.
|
||||
|
||||
When using the 'path' attribute, please ensure to also
|
||||
declare a handler mapping bean of type
|
||||
'org.springframework.integration.http.inbound.UriPathHandlerMapping'.
|
||||
|
||||
This bean is used by the Spring MVC DispatcherServlet
|
||||
to evaluate which URL maps to which inbound endpoint.
|
||||
For more information please see the chapter on
|
||||
'Handler mappings' in the Spring Framework Reference
|
||||
Documentation.
|
||||
The receiving Message Channel of this endpoint.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="extract-reply-payload" type="xsd:string" default="true" />
|
||||
<xsd:attribute name="supported-methods" type="xsd:string" />
|
||||
<xsd:attribute name="view-name" type="xsd:string">
|
||||
<xsd:attributeGroup ref="inboundCommonAttributes" />
|
||||
<xsd:attribute name="extract-reply-payload" type="xsd:string" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
View name to be resolved when rendering a response.
|
||||
This attribute is not allowed if there is a 'view-expression' attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="view-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
SpEL expression that resolves to a view to be resolved when rendering a response.
|
||||
The expression can resolve to a view name or View object.
|
||||
The root object of the evaluation context is the reply message.
|
||||
This attribute is not allowed if there is a 'view-name' attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="errors-key" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
In the case that a view-name is specified this attribute can be used to
|
||||
override the default key of the Errors (if the request cannot be handled).
|
||||
Defaults to "errors" (similar to normal MVC usage).
|
||||
</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 the URI path (e.g., /orderId/{order})
|
||||
|
||||
When using the 'path' attribute, please ensure to also
|
||||
declare a handler mapping bean of type
|
||||
'org.springframework.integration.http.inbound.UriPathHandlerMapping'.
|
||||
|
||||
This bean is used by the Spring MVC DispatcherServlet
|
||||
to evaluate which URL maps to which inbound endpoint.
|
||||
For more information please see the chapter on
|
||||
'Handler mappings' in the Spring Framework Reference
|
||||
Documentation.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-code" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
In the case that a view-name is specified this attribute can be used to
|
||||
override the default error code under which the handling exception is exposed.
|
||||
Defaults to "spring.integration.http.handler.error" and is supplied with 3
|
||||
parameters: the exception itself, its message and its stack trace as a String.
|
||||
Specify whether only the reply Message's payload should be passed in the response.
|
||||
If this is set to 'false', the entire Message will be used to generate the response.
|
||||
The default is 'true'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -284,59 +132,6 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-payload-type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Target type for payload that is the conversion result of the request.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="message-converters" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
List of HttpMessageConverters for this Gateway.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="merge-with-default-converters" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Flag to indicate if the default converters should be registered after any custom
|
||||
converters. This flag is used only if message-converters
|
||||
are provided, otherwise all default converters will be registered.
|
||||
|
||||
Defaults to "false"
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="header-mapper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.mapping.HeaderMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-request-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Comma-separated list of names of HttpHeaders to be mapped from the HTTP request into the MessageHeaders.
|
||||
This can only be provided if the 'header-mapper' reference is not being set directly. The values in
|
||||
this list can also be simple patterns to be matched against the header names (e.g. "foo*" or "*foo").
|
||||
The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Request headers.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-response-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -347,7 +142,16 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-key" type="xsd:string" />
|
||||
<xsd:attribute name="reply-key" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
In the case that a view-name is specified this attribute can be used to
|
||||
override the default key of the MVC Controller's ModelAndView attribute
|
||||
to keep a reply from underlying message flow.
|
||||
Default is 'reply'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -358,7 +162,7 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-timeout" type="xsd:string">
|
||||
<xsd:attribute name="reply-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Used to set the revceiveTimeout on the underlying MessagingTemplate instance
|
||||
@@ -373,15 +177,154 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="outbound-channel-adapter">
|
||||
<xsd:complexType>
|
||||
<xsd:attributeGroup name="inboundCommonAttributes">
|
||||
<xsd:attribute name="path" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an outbound HTTP-based Channel Adapter.
|
||||
Comma-separated URI paths (e.g., /orderId/{order}).
|
||||
Ant-style path patterns are also supported (e.g. /myPath/*.do).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="supported-methods">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Comma-separated HTTP Method names. Determines which types of Request are
|
||||
allowed with this Endpoint.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="httpMethodEnumeration xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="view-name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
View name to be resolved when rendering a response.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="view-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
SpEL expression that resolves to a view to be resolved when rendering a response.
|
||||
The expression can resolve to a view name or View object.
|
||||
In the case of 'inbound-gateway' the root object of the evaluation context is the reply message.
|
||||
In the case of 'inbound-channel-adapter' the 'evaluationContext' for this expression
|
||||
is rather lightweight, because there is no reply message, ; it has a
|
||||
'BeanResolver' but no variables,
|
||||
so the usage of this attribute is somewhat limited.
|
||||
An example might be to resolve, at runtime, some scoped Bean that returns a
|
||||
view name or View object.
|
||||
This attribute is not allowed if there is a 'view-name' attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-code" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
In the case that a view-name is specified this attribute can be used to
|
||||
override the default error code under which the handling exception is exposed.
|
||||
Defaults to "spring.integration.http.handler.error" and is supplied with 3
|
||||
parameters: the exception itself, its message and its stack trace as a String.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="errors-key" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
In the case that a view-name is specified this attribute can be used to
|
||||
override the default key of the Errors (if the request cannot be handled).
|
||||
Defaults to "errors" (similar to normal MVC usage).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-payload-type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Target type for payload that is the conversion result of the request.
|
||||
</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="message-converters" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
List of HttpMessageConverters for this Channel Adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="merge-with-default-converters" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Flag to indicate if the default converters should be registered after any custom
|
||||
converters. This flag is used only if message-converters
|
||||
are provided, otherwise all default converters will be registered.
|
||||
|
||||
Defaults to "false"
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="header-mapper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.mapping.HeaderMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
Specifies a reference to org.springframework.integration.mapping.HeaderMapper
|
||||
implementation bean. Only one of 'header-mapper' or 'mapped-request-headers' attributes
|
||||
can be provided.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-request-headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Comma-separated list of names of HttpHeaders to be mapped from the HTTP request into the MessageHeaders.
|
||||
This can only be provided if the 'header-mapper' reference is not being set directly. The values in
|
||||
this list can also be simple patterns to be matched against the header names (e.g. "foo*" or "*foo").
|
||||
The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Request headers.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
The MessagingGateway's 'error-channel' where to send an ErrorMessage in case
|
||||
of Exception is caused from original message flow.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:element name="outbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an outbound HTTP-based Channel Adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:choice minOccurs="0" maxOccurs="2">
|
||||
<xsd:element name="uri-variable" type="uriVariableType" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="uri-variable" type="uriVariableType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify an expression for URI variable placeholder within 'url'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="request-handler-advice-chain" type="integration:adviceChainType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:choice>
|
||||
<xsd:attributeGroup ref="integration:channelAdapterAttributes"/>
|
||||
@@ -438,10 +381,29 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
<tool:expected-type type="org.springframework.web.client.RestTemplate" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
The reference to org.springframework.web.client.RestTemplate bean to send the HTTP Request.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="charset" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify the charset name to use for converting String-typed payloads to bytes.
|
||||
The default is 'UTF-8'
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="extract-payload" type="xsd:string" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify 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'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="charset" type="xsd:string" />
|
||||
<xsd:attribute name="extract-payload" type="xsd:string" />
|
||||
<xsd:attribute name="expected-response-type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -481,6 +443,11 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
<tool:expected-type type="org.springframework.integration.mapping.HeaderMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
Specify a reference to org.springframework.integration.mapping.HeaderMapper
|
||||
implementation bean. Only one of 'header-mapper' or 'mapped-request-headers' attributes
|
||||
can be provided.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="mapped-request-headers" type="xsd:string">
|
||||
@@ -528,16 +495,22 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="outbound-gateway">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an outbound HTTP-based Messaging Gateway.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an outbound HTTP-based Messaging Gateway.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="gatewayType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="2">
|
||||
<xsd:element name="uri-variable" type="uriVariableType" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="uri-variable" type="uriVariableType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify an expression for URI variable placeholder within 'url'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="request-handler-advice-chain" type="integration:adviceChainType" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="request-channel" type="xsd:string">
|
||||
@@ -547,6 +520,9 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
The receiving Message Channel of this endpoint.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="url" type="xsd:string" use="optional">
|
||||
@@ -609,6 +585,12 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
<tool:expected-type type="org.springframework.integration.mapping.HeaderMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="rest-template" type="xsd:string">
|
||||
@@ -617,6 +599,9 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.web.client.RestTemplate" />
|
||||
</tool:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to org.springframework.web.client.RestTemplate bean to send the HTTP Request.
|
||||
</xsd:documentation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
@@ -640,7 +625,16 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="extract-request-payload" type="xsd:string" />
|
||||
<xsd:attribute name="extract-request-payload" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expected-response-type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -665,7 +659,14 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="charset" type="xsd:string" />
|
||||
<xsd:attribute name="charset" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify the charset name to use for converting String-typed payloads to bytes.
|
||||
The default is 'UTF-8'
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -807,9 +808,69 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
Identifies the channel to which this gateway will subscribe, to receive(send) reply Messages.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="requestMappingType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines configuration for org.springframework.integration.http.inbound.RequestMapping
|
||||
as RESTFul attributes for Spring Integration HTTP Inbound Endpoints.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="params" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The parameters of the mapped request, narrowing the primary mapping.
|
||||
A sequence of "myParam=myValue" style
|
||||
expressions, with a request only mapped if each such parameter is found
|
||||
to have the given value.
|
||||
Expressions can be negated by using the "!=" operator,
|
||||
as in "myParam!=myValue".
|
||||
"myParam" style expressions are also supported,
|
||||
with such parameters having to be present in the request (allowed to have
|
||||
any value).
|
||||
"!myParam" style expressions indicate that the
|
||||
specified parameter is not supposed to be present in the request.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="headers" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The headers of the mapped request, narrowing the primary mapping.
|
||||
A sequence of "My-Header=myValue" style
|
||||
expressions, with a request only mapped if each such header is found
|
||||
to have the given value.
|
||||
Expressions can be negated by using the "!=" operator,
|
||||
as in "My-Header!=myValue".
|
||||
"My-Header" style expressions are also supported,
|
||||
with such headers having to be present in the request (allowed to have
|
||||
any value).
|
||||
"!My-Header" style expressions indicate that the
|
||||
specified header is not supposed to be present in the request.
|
||||
Also supports media type wildcards (*), for headers such as Accept
|
||||
and Content-Type. For instance, headers = "content-type=text/*"
|
||||
will match requests with a Content-Type of "text/html", "text/plain", etc.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="consumes" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The consumable media types of the mapped request, narrowing the primary mapping.
|
||||
The format is a sequence of media types ("text/plain", "application/*),
|
||||
with a request only mapped if the Content-Type matches one of these media types.
|
||||
Expressions can be negated by using the "!" operator, as in "!text/plain", which matches
|
||||
all requests with a Content-Type other than "text/plain".
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<beans:bean class="org.springframework.integration.http.inbound.UriPathHandlerMapping"/>
|
||||
|
||||
<inbound-gateway path="/test" request-channel="testChannel"
|
||||
payload-expression="T(org.springframework.web.context.request.RequestContextHolder).requestAttributes.request.queryString"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 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.
|
||||
@@ -32,6 +32,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.PropertyAccessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/http
|
||||
http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
<si:message-history/>
|
||||
|
||||
@@ -18,13 +22,13 @@
|
||||
|
||||
<inbound-channel-adapter id="defaultAdapter" channel="requests" error-channel="errorChannel"/>
|
||||
|
||||
<inbound-channel-adapter id="postOnlyAdapter" channel="requests" supported-methods="POST"/>
|
||||
<inbound-channel-adapter id="postOnlyAdapter" path="/postOnly" channel="requests" supported-methods="POST"/>
|
||||
|
||||
<inbound-channel-adapter id="adapterWithCustomConverterWithDefaults" message-converters="customConverters"
|
||||
channel="requests" supported-methods="POST" merge-with-default-converters="true"/>
|
||||
channel="requests" supported-methods="DELETE" merge-with-default-converters="true"/>
|
||||
|
||||
<inbound-channel-adapter id="adapterWithCustomConverterNoDefaults" message-converters="customConverters"
|
||||
channel="requests" supported-methods="POST" />
|
||||
channel="requests" supported-methods="HEAD" />
|
||||
|
||||
<inbound-channel-adapter id="adapterNoCustomConverterNoDefaults" channel="requests" supported-methods="POST" />
|
||||
|
||||
@@ -34,43 +38,41 @@
|
||||
|
||||
<inbound-channel-adapter id="putOrDeleteAdapter" channel="requests" supported-methods="PUT, delete"/>
|
||||
|
||||
<inbound-channel-adapter id="inboundController" channel="requests" view-name="foo" error-code="oops"/>
|
||||
<inbound-channel-adapter id="inboundController" channel="requests" view-name="foo" error-code="oops">
|
||||
<request-mapping headers="BAR"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="inboundControllerViewExp" channel="requests" view-expression="'foo'"/>
|
||||
<inbound-channel-adapter id="inboundControllerViewExp" channel="requests" view-expression="'foo'">
|
||||
<request-mapping headers="BAR2"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="withMappedHeaders" channel="requests"
|
||||
mapped-request-headers="foo,bar"/>
|
||||
mapped-request-headers="foo,bar">
|
||||
<request-mapping headers="foo=bar"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="inboundAdapterWithExpressions"
|
||||
path="/fname/{f}/lname/{l}"
|
||||
channel="requests"
|
||||
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"
|
||||
<inbound-channel-adapter channel="requests"
|
||||
mapped-request-headers="foo,bar"
|
||||
payload-expression="#pathVariables.f">
|
||||
<request-mapping headers="invalid"/>
|
||||
<header name="lname" expression="#pathVariables.l"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<inbound-channel-adapter id="autoChannel"
|
||||
path="/fname/{f}/lname/{l}"
|
||||
path="/fname/{f}/lname2/{l}"
|
||||
mapped-request-headers="foo,bar"
|
||||
payload-expression="#pathVariables.f">
|
||||
<header name="lname" expression="#pathVariables.l"/>
|
||||
</inbound-channel-adapter>
|
||||
|
||||
<si:bridge input-channel="autoChannel" output-channel="nullChannel" />
|
||||
<si:bridge input-channel="autoChannel" output-channel="nullChannel"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -20,9 +20,9 @@ import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
@@ -58,7 +58,11 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
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.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -66,7 +70,6 @@ import org.springframework.util.MultiValueMap;
|
||||
* @author Gary Russell
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@@ -76,6 +79,9 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private PollableChannel requests;
|
||||
|
||||
@Autowired
|
||||
private HandlerMapping integrationRequestMappingHandlerMapping;
|
||||
|
||||
@Autowired
|
||||
private HttpRequestHandlingMessagingGateway defaultAdapter;
|
||||
|
||||
@@ -95,14 +101,6 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
@Autowired
|
||||
private HttpRequestHandlingMessagingGateway inboundAdapterWithExpressions;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("/fname/{blah}/lname/{boo}")
|
||||
private HttpRequestHandlingMessagingGateway inboundAdapterWithNameAndExpressions;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("/fname/{f}/lname/{l}")
|
||||
private HttpRequestHandlingMessagingGateway inboundAdapterWithNameNoPath;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("adapterWithCustomConverterNoDefaults")
|
||||
private HttpRequestHandlingMessagingGateway adapterWithCustomConverterNoDefaults;
|
||||
@@ -167,7 +165,15 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
String requestURI = "/fname/bill/lname/clinton";
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
Map<String, String> uriTemplateVariables =
|
||||
new AntPathMatcher().extractUriTemplateVariables("/fname/{f}/lname/{l}", requestURI);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
inboundAdapterWithExpressions.handleRequest(request, response);
|
||||
@@ -180,60 +186,20 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
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(expected=SpelEvaluationException.class)
|
||||
// INT-1677
|
||||
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 {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.setParameter("foo", "bar");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
postOnlyAdapter.handleRequest(request, response);
|
||||
assertEquals(HttpServletResponse.SC_METHOD_NOT_ALLOWED, response.getStatus());
|
||||
Message<?> message = requests.receive(0);
|
||||
assertNull(message);
|
||||
request.setRequestURI("/postOnly");
|
||||
try {
|
||||
this.integrationRequestMappingHandlerMapping.getHandler(request);
|
||||
}
|
||||
catch (HttpRequestMethodNotSupportedException e) {
|
||||
assertEquals("GET", e.getMethod());
|
||||
assertArrayEquals(new String[] {"POST"}, e.getSupportedMethods());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -241,10 +207,7 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContent("test".getBytes());
|
||||
|
||||
//request.setContentType("text/plain"); //Works in Spring 3.1.2.RELEASE but not in Spring 3.0.7.RELEASE
|
||||
//Instead use:
|
||||
request.addHeader("Content-Type", "text/plain");
|
||||
request.setContentType("text/plain");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
postOnlyAdapter.handleRequest(request, response);
|
||||
@@ -267,10 +230,7 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
new ObjectOutputStream(byteStream).writeObject(obj);
|
||||
request.setContent(byteStream.toByteArray());
|
||||
|
||||
// //request.setContentType("application/x-java-serialized-object"); //Works in Spring 3.1.2.RELEASE but not in Spring 3.0.7.RELEASE
|
||||
// //Instead use:
|
||||
request.addHeader("Content-Type", "application/x-java-serialized-object");
|
||||
request.setContentType("application/x-java-serialized-object");
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
@@ -284,13 +244,11 @@ public class HttpInboundChannelAdapterParserTests {
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putOrDeleteMethodsSupported() throws Exception {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(putOrDeleteAdapter);
|
||||
List<String> supportedMethods = (List<String>) accessor.getPropertyValue("supportedMethods");
|
||||
assertEquals(2, supportedMethods.size());
|
||||
assertTrue(supportedMethods.contains(HttpMethod.PUT));
|
||||
assertTrue(supportedMethods.contains(HttpMethod.DELETE));
|
||||
HttpMethod[] supportedMethods =
|
||||
TestUtils.getPropertyValue(putOrDeleteAdapter, "requestMapping.methods", HttpMethod[].class);
|
||||
assertEquals(2, supportedMethods.length);
|
||||
assertArrayEquals(new HttpMethod[]{HttpMethod.PUT, HttpMethod.DELETE}, supportedMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
@@ -19,27 +18,35 @@
|
||||
</si:channel>
|
||||
|
||||
<inbound-gateway id="inboundGateway"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
convert-exceptions="true"
|
||||
request-timeout="1234"
|
||||
reply-timeout="4567"
|
||||
error-channel="errorChannel"/>
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
convert-exceptions="true"
|
||||
request-timeout="1234"
|
||||
reply-timeout="4567"
|
||||
error-channel="errorChannel"/>
|
||||
|
||||
<inbound-gateway id="inboundController" request-channel="requests" reply-channel="responses" view-name="foo"
|
||||
error-code="oops">
|
||||
<request-mapping headers="BAR"/>
|
||||
</inbound-gateway>
|
||||
|
||||
<inbound-gateway id="inboundGatewayWithOneCustomConverter"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
supported-methods="DELETE"
|
||||
message-converters="customConverters"/>
|
||||
|
||||
<inbound-gateway id="inboundGatewayNoDefaultConverters"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
supported-methods="TRACE"
|
||||
message-converters="customConverters"
|
||||
merge-with-default-converters="false"/>
|
||||
|
||||
<inbound-gateway id="inboundGatewayWithCustomAndDefaultConverters"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
supported-methods="HEAD"
|
||||
message-converters="customConverters"
|
||||
merge-with-default-converters="true"/>
|
||||
|
||||
@@ -47,26 +54,28 @@
|
||||
<beans:bean class="org.springframework.integration.http.converter.SerializingHttpMessageConverter"/>
|
||||
</util:list>
|
||||
|
||||
|
||||
<inbound-gateway id="inboundController" request-channel="requests" reply-channel="responses" view-name="foo" error-code="oops"/>
|
||||
|
||||
<inbound-gateway id="inboundControllerViewExp"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
view-expression="'bar'"
|
||||
error-code="oops"/>
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
view-expression="'bar'"
|
||||
error-code="oops">
|
||||
<request-mapping headers="BAR2"/>
|
||||
</inbound-gateway>
|
||||
|
||||
<inbound-gateway id="withMappedHeaders" request-channel="requests"
|
||||
mapped-response-headers="abc, xyz"
|
||||
mapped-request-headers="foo,bar"/>
|
||||
|
||||
mapped-response-headers="abc, xyz"
|
||||
mapped-request-headers="foo,bar">
|
||||
<request-mapping headers="foo=bar"/>
|
||||
</inbound-gateway>
|
||||
<inbound-gateway id="withMappedHeadersAndConverter" request-channel="requests"
|
||||
mapped-response-headers="abc, xyz, person"
|
||||
mapped-request-headers="foo,bar"/>
|
||||
mapped-response-headers="abc, xyz, person"
|
||||
mapped-request-headers="foo,bar">
|
||||
<request-mapping headers="foo=bar2"/>
|
||||
</inbound-gateway>
|
||||
|
||||
<si:converter ref="personConverter"/>
|
||||
|
||||
<beans:bean id="personConverter" class="org.springframework.integration.http.config.HttpInboundGatewayParserTests.PersonConverter"/>
|
||||
|
||||
<beans:bean id="personConverter"
|
||||
class="org.springframework.integration.http.config.HttpInboundGatewayParserTests$PersonConverter"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -68,6 +68,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Gary Russell
|
||||
* @author Gunnar Hillert
|
||||
* @author Biju Kunjummen
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@@ -119,8 +120,8 @@ public class HttpInboundGatewayParserTests {
|
||||
assertNotNull(TestUtils.getPropertyValue(gateway, "errorChannel"));
|
||||
MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(
|
||||
gateway, "messagingTemplate", MessagingTemplate.class);
|
||||
assertEquals(Long.valueOf(1234), TestUtils.getPropertyValue(messagingTemplate, "sendTimeout"));
|
||||
assertEquals(Long.valueOf(4567), TestUtils.getPropertyValue(messagingTemplate, "receiveTimeout"));
|
||||
assertEquals(1234L, TestUtils.getPropertyValue(messagingTemplate, "sendTimeout"));
|
||||
assertEquals(4567L, TestUtils.getPropertyValue(messagingTemplate, "receiveTimeout"));
|
||||
|
||||
boolean registerDefaultConverters = TestUtils.getPropertyValue(gateway,"mergeWithDefaultConverters", Boolean.class);
|
||||
assertFalse("By default the register-default-converters flag should be false", registerDefaultConverters);
|
||||
@@ -148,9 +149,7 @@ public class HttpInboundGatewayParserTests {
|
||||
gateway.handleRequest(request, response);
|
||||
assertThat(response.getStatus(), is(HttpServletResponse.SC_OK));
|
||||
|
||||
//MockHttpServletResponse#getContentType() works in Spring 3.1.2.RELEASE but not in 3.0.7.RELEASE
|
||||
//For 3.0.7.RELEASE we have to rely on MockHttpServletResponse#getHeader instead
|
||||
assertEquals(response.getHeader("Content-Type"), "application/x-java-serialized-object");
|
||||
assertEquals(response.getContentType(), "application/x-java-serialized-object");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -34,12 +34,15 @@ import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Gunnar Hillert
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Biju Kunjummen
|
||||
*/
|
||||
public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
@@ -69,10 +72,14 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
RequestMapping requestMapping = new RequestMapping();
|
||||
requestMapping.setPathPatterns("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestMapping(requestMapping);
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Object result = gateway.doHandleRequest(request, response);
|
||||
@@ -97,12 +104,24 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
String requestURI = "/fname/bill/lname/clinton";
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
Map<String, String> uriTemplateVariables =
|
||||
new AntPathMatcher().extractUriTemplateVariables("/fname/{f}/lname/{l}", requestURI);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
RequestMapping requestMapping = new RequestMapping();
|
||||
requestMapping.setPathPatterns("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestMapping(requestMapping);
|
||||
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables.f"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
@@ -130,12 +149,24 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
String requestURI = "/fname/bill/lname/clinton";
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
Map<String, String> uriTemplateVariables =
|
||||
new AntPathMatcher().extractUriTemplateVariables("/fname/{f}/lname/{l}", requestURI);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
RequestMapping requestMapping = new RequestMapping();
|
||||
requestMapping.setPathPatterns("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestMapping(requestMapping);
|
||||
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables"));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns:int-http="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/http
|
||||
http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">
|
||||
|
||||
<int-http:inbound-gateway path="/path1,/path2"
|
||||
request-channel="multiplePathsChannel"/>
|
||||
|
||||
<int:transformer input-channel="multiplePathsChannel"
|
||||
expression="T(org.springframework.integration.http.inbound.Int2312RequestMappingIntegrationTests).TEST_STRING_MULTIPLE_PATHS"/>
|
||||
|
||||
<util:constant id="TEST_PATH"
|
||||
static-field="org.springframework.integration.http.inbound.Int2312RequestMappingIntegrationTests.TEST_PATH"/>
|
||||
|
||||
<int-http:inbound-gateway path="#{TEST_PATH}"
|
||||
request-channel="toLowerCaseChannel"
|
||||
payload-expression="#pathVariables.value">
|
||||
<int-http:request-mapping headers="toLowerCase"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="toLowerCaseChannel" expression="payload.toLowerCase()"/>
|
||||
|
||||
<int-http:inbound-gateway path="#{TEST_PATH}"
|
||||
request-channel="toUpperCaseChannel"
|
||||
payload-expression="#pathVariables.value">
|
||||
<int-http:request-mapping headers="toUpperCase"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="toUpperCaseChannel" expression="payload.toUpperCase()"/>
|
||||
|
||||
<int-http:inbound-gateway path="/params"
|
||||
request-channel="twoParamsChannel">
|
||||
<int-http:request-mapping params="param1,param2"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="twoParamsChannel" expression="'User=1;account=1'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/params"
|
||||
request-channel="onlyOneParamChannel">
|
||||
<int-http:request-mapping params="param1,!param2"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="onlyOneParamChannel" expression="'User=1'"/>
|
||||
|
||||
|
||||
<int-http:inbound-gateway path="/consumes"
|
||||
request-channel="consumesNonXmlChannel"
|
||||
supported-methods="GET,PUT">
|
||||
<int-http:request-mapping consumes="!text/xml,text/*"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="consumesNonXmlChannel" expression="'BAR'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/consumes"
|
||||
request-channel="consumesXmlChannel"
|
||||
supported-methods="GET,PUT">
|
||||
<int-http:request-mapping consumes="text/xml"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="consumesXmlChannel" expression="'<test>TEXT_XML</test>'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/produces"
|
||||
request-channel="contentXmlChannel">
|
||||
<int-http:request-mapping produces="application/xml"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="contentXmlChannel" expression="'<test>XML</test>'"/>
|
||||
|
||||
<int-http:inbound-gateway path="/produces"
|
||||
request-channel="contentNonXmlChannel">
|
||||
<int-http:request-mapping produces="!application/xml"/>
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
<int:transformer input-channel="contentNonXmlChannel" expression="'{"json":"body"}'"/>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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 static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
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.web.bind.UnsatisfiedServletRequestParameterException;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
//INT-2312
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class Int2312RequestMappingIntegrationTests {
|
||||
|
||||
public static final String TEST_PATH = "/test/{value}";
|
||||
|
||||
public static final String TEST_STRING_MULTIPLE_PATHS = "Multiple Paths The Same Endpoint";
|
||||
|
||||
@Autowired
|
||||
private HandlerMapping handlerMapping;
|
||||
|
||||
private HandlerAdapter handlerAdapter = new HttpRequestHandlerAdapter();
|
||||
|
||||
@Test
|
||||
public void testMultiplePathsTheSameEndpoint() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.setRequestURI("/path1");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
Object handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
assertEquals(TEST_STRING_MULTIPLE_PATHS, response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.setRequestURI("/path2");
|
||||
response = new MockHttpServletResponse();
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
assertEquals(TEST_STRING_MULTIPLE_PATHS, response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testURIVariablesAndHeaders() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
String testRequest = "aBc";
|
||||
String requestURI = "/test/" + testRequest;
|
||||
request.setRequestURI(requestURI);
|
||||
|
||||
//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);
|
||||
|
||||
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();
|
||||
assertEquals(testRequest.toLowerCase(), testResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParams() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/params");
|
||||
Object handler = null;
|
||||
try {
|
||||
handler = this.handlerMapping.getHandler(request);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// There is no matching handlers and some default handler
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleNoMatch
|
||||
assertTrue(e instanceof UnsatisfiedServletRequestParameterException);
|
||||
}
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/params");
|
||||
request.addParameter("param1", "1");
|
||||
request.addParameter("param2", "1");
|
||||
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
String testResponse = response.getContentAsString();
|
||||
assertEquals("User=1;account=1", testResponse);
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/params");
|
||||
request.addParameter("param1", "1");
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
testResponse = response.getContentAsString();
|
||||
assertEquals("User=1", testResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumes() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/consumes");
|
||||
request.setContentType("text/plain");
|
||||
Object handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
String testResponse = response.getContentAsString();
|
||||
assertEquals("BAR", testResponse);
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/consumes");
|
||||
request.setContentType("text/xml");
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
testResponse = response.getContentAsString();
|
||||
assertEquals("<test>TEXT_XML</test>", testResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProduces() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/produces");
|
||||
request.addHeader("Accept", "application/xml");
|
||||
Object handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
assertEquals(Collections.singleton(MediaType.APPLICATION_XML),
|
||||
request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE));
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
String testResponse = response.getContentAsString();
|
||||
assertEquals("<test>XML</test>", testResponse);
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/produces");
|
||||
request.addHeader("Accept", "application/json");
|
||||
handler = this.handlerMapping.getHandler(request).getHandler();
|
||||
|
||||
//See org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping#handleMatch
|
||||
assertNull("Negated expression should not be listed as a producible type",
|
||||
request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE));
|
||||
|
||||
response = new MockHttpServletResponse();
|
||||
|
||||
this.handlerAdapter.handle(request, response, handler);
|
||||
testResponse = response.getContentAsString();
|
||||
assertEquals("{\"json\":\"body\"}", testResponse);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -501,11 +502,10 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests {
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void validateCustomHeadersWithNonStringValuesAndDefaultConverterOnly() throws Exception{
|
||||
DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper();
|
||||
mapper.setOutboundHeaderNames(new String[] {"customHeader*"});
|
||||
ConversionService cs = ConversionServiceFactory.createDefaultConversionService();
|
||||
ConversionService cs = new DefaultConversionService();
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("integrationConversionService", cs);
|
||||
mapper.setBeanFactory(beanFactory);
|
||||
@@ -523,11 +523,10 @@ public class DefaultHttpHeaderMapperFromMessageInboundTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void validateCustomHeadersWithNonStringValuesAndDefaultConverterWithCustomConverter() throws Exception{
|
||||
DefaultHttpHeaderMapper mapper = new DefaultHttpHeaderMapper();
|
||||
mapper.setOutboundHeaderNames(new String[] {"customHeader*"});
|
||||
GenericConversionService cs = ConversionServiceFactory.createDefaultConversionService();
|
||||
GenericConversionService cs = new DefaultConversionService();
|
||||
cs.addConverter(new TestClassConverter());
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("integrationConversionService", cs);
|
||||
|
||||
Reference in New Issue
Block a user