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
@@ -20,7 +20,6 @@ import java.util.List;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
@@ -40,6 +39,8 @@ import org.springframework.integration.endpoint.AbstractPollingEndpoint;
|
||||
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -58,11 +59,11 @@ import org.springframework.util.xml.DomUtils;
|
||||
*/
|
||||
public abstract class IntegrationNamespaceUtils {
|
||||
|
||||
static final String BASE_PACKAGE = "org.springframework.integration";
|
||||
static final String REF_ATTRIBUTE = "ref";
|
||||
static final String METHOD_ATTRIBUTE = "method";
|
||||
static final String ORDER = "order";
|
||||
static final String EXPRESSION_ATTRIBUTE = "expression";
|
||||
public static final String BASE_PACKAGE = "org.springframework.integration";
|
||||
public static final String REF_ATTRIBUTE = "ref";
|
||||
public static final String METHOD_ATTRIBUTE = "method";
|
||||
public static final String ORDER = "order";
|
||||
public static final String EXPRESSION_ATTRIBUTE = "expression";
|
||||
public static final String HANDLER_ALIAS_SUFFIX = ".handler";
|
||||
public static final String REQUEST_HANDLER_ADVICE_CHAIN = "request-handler-advice-chain";
|
||||
public static final String AUTO_STARTUP = "auto-startup";
|
||||
@@ -303,7 +304,8 @@ public abstract class IntegrationNamespaceUtils {
|
||||
/**
|
||||
* Utility method to configure HeaderMapper for Inbound and Outbound channel adapters/gateway
|
||||
*/
|
||||
public static void configureHeaderMapper(Element element, BeanDefinitionBuilder rootBuilder, ParserContext parserContext, Class<?> headerMapperClass, String replyHeaderValue){
|
||||
public static void configureHeaderMapper(Element element, BeanDefinitionBuilder rootBuilder,
|
||||
ParserContext parserContext, Class<?> headerMapperClass, String replyHeaderValue) {
|
||||
String defaultMappedReplyHeadersAttributeName = "mapped-reply-headers";
|
||||
if (!StringUtils.hasText(replyHeaderValue)){
|
||||
replyHeaderValue = defaultMappedReplyHeadersAttributeName;
|
||||
@@ -429,11 +431,11 @@ public abstract class IntegrationNamespaceUtils {
|
||||
return adviceChain;
|
||||
}
|
||||
|
||||
public static RootBeanDefinition createExpressionDefinitionFromValueOrExpression(String valueElementName,
|
||||
public static BeanDefinition createExpressionDefinitionFromValueOrExpression(String valueElementName,
|
||||
String expressionElementName, ParserContext parserContext, Element element, boolean oneRequired) {
|
||||
|
||||
Assert.hasText(valueElementName, "'valueElementName' must not be empty");
|
||||
Assert.hasText(expressionElementName, "'expressionElementName' must no be empty");
|
||||
Assert.hasText(expressionElementName, "'expressionElementName' must not be empty");
|
||||
|
||||
String valueElementValue = element.getAttribute(valueElementName);
|
||||
String expressionElementValue = element.getAttribute(expressionElementName);
|
||||
@@ -450,19 +452,16 @@ public abstract class IntegrationNamespaceUtils {
|
||||
parserContext.getReaderContext().error("One of '" + valueElementName + "' or '"
|
||||
+ expressionElementName + "' is required", element);
|
||||
}
|
||||
RootBeanDefinition expressionDef = null;
|
||||
BeanDefinition expressionDef = null;
|
||||
if (hasAttributeValue) {
|
||||
expressionDef = new RootBeanDefinition(LiteralExpression.class);
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(valueElementValue);
|
||||
}
|
||||
else if (hasAttributeExpression){
|
||||
expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expressionElementValue);
|
||||
else {
|
||||
expressionDef = createExpressionDefIfAttributeDefined(expressionElementName, element);
|
||||
}
|
||||
return expressionDef;
|
||||
}
|
||||
|
||||
|
||||
public static void registerSpelFunctionBean(BeanDefinitionRegistry registry, String functionId, String className,
|
||||
String methodSignature) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SpelFunctionFactoryBean.class)
|
||||
@@ -470,4 +469,30 @@ public abstract class IntegrationNamespaceUtils {
|
||||
.addConstructorArgValue(methodSignature);
|
||||
registry.registerBeanDefinition(functionId, builder.getBeanDefinition());
|
||||
}
|
||||
public static BeanDefinition createExpressionDefIfAttributeDefined(String expressionElementName, Element element) {
|
||||
|
||||
Assert.hasText(expressionElementName, "'expressionElementName' must no be empty");
|
||||
|
||||
String expressionElementValue = element.getAttribute(expressionElementName);
|
||||
|
||||
if (StringUtils.hasText(expressionElementValue)){
|
||||
BeanDefinitionBuilder expressionDefBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class);
|
||||
expressionDefBuilder.addConstructorArgValue(expressionElementValue);
|
||||
return expressionDefBuilder.getRawBeanDefinition();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String createDirectChannel(Element element, ParserContext parserContext) {
|
||||
String channelId = element.getAttribute(ID_ATTRIBUTE);
|
||||
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);
|
||||
}
|
||||
BeanDefinitionBuilder channelBuilder = BeanDefinitionBuilder.genericBeanDefinition(DirectChannel.class);
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(channelBuilder.getBeanDefinition(), channelId);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
|
||||
return channelId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.w3c.dom.Element;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.jpa.support.OutboundGatewayType;
|
||||
@@ -46,7 +45,7 @@ public class RetrievingJpaOutboundGatewayParser extends AbstractJpaOutboundGatew
|
||||
final BeanDefinitionBuilder jpaExecutorBuilder = JpaParserUtils.getOutboundGatewayJpaExecutorBuilder(gatewayElement, parserContext);
|
||||
|
||||
|
||||
RootBeanDefinition firstResultExpression = createExpressionDefinitionFromValueOrExpression("first-result",
|
||||
BeanDefinition firstResultExpression = createExpressionDefinitionFromValueOrExpression("first-result",
|
||||
"first-result-expression", parserContext, gatewayElement, false);
|
||||
|
||||
if(firstResultExpression != null) {
|
||||
|
||||
@@ -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.
|
||||
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
package org.springframework.integration.mongodb.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
@@ -43,7 +43,7 @@ public class MongoDbInboundChannelAdapterParser extends AbstractPollingInboundCh
|
||||
// 'collection-name', 'collection-name-expression' and 'mongo-converter'
|
||||
MongoParserUtils.processCommonAttributes(element, parserContext, builder);
|
||||
|
||||
RootBeanDefinition queryExpressionDef =
|
||||
BeanDefinition queryExpressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("query", "query-expression",
|
||||
parserContext, element, true);
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.integration.mongodb.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -62,7 +62,7 @@ class MongoParserUtils {
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "mongo-converter");
|
||||
}
|
||||
|
||||
RootBeanDefinition collectionNameExpressionDef =
|
||||
BeanDefinition collectionNameExpressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("collection-name", "collection-name-expression",
|
||||
parserContext, element, false);
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ package org.springframework.integration.redis.config;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
@@ -57,7 +57,7 @@ public class RedisStoreInboundChannelAdapterParser extends AbstractPollingInboun
|
||||
builder.addConstructorArgReference(connectionFactory);
|
||||
}
|
||||
boolean atLeastOneRequired = true;
|
||||
RootBeanDefinition expressionDef =
|
||||
BeanDefinition expressionDef =
|
||||
IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression("key", "key-expression",
|
||||
parserContext, element, atLeastOneRequired);
|
||||
builder.addConstructorArgValue(expressionDef);
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
"multipartResolver" (the same name expected by Spring's DispatcherServlet). If it does in fact locate that
|
||||
bean, then the support for MultipartFiles will be enabled on the inbound request mapper. Otherwise, it will
|
||||
fail when trying to map a multipart-file request to a Spring Integration Message. For more on Spring's
|
||||
support for MultipartResolvers, refer to the <ulink url="http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html#mvc-multipart">Spring Reference Manual</ulink>.
|
||||
support for MultipartResolvers, refer to the <ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-multipart">Spring Reference Manual</ulink>.
|
||||
</note>
|
||||
</para>
|
||||
<para>
|
||||
@@ -139,11 +139,10 @@ By default the HTTP request will be generated using an instance of <classname>Si
|
||||
<classname>HttpURLConnection</classname>. Use of the Apache Commons HTTP Client is also supported through the provided
|
||||
<classname>CommonsClientHttpRequestFactory</classname> which can be injected as shown above.
|
||||
</para>
|
||||
<para>
|
||||
<note>
|
||||
In the case of the Outbound Gateway, the reply message produced by the gateway will contain all Message Headers present in the request message.
|
||||
</note>
|
||||
</para>
|
||||
<note>
|
||||
In the case of the Outbound Gateway, the reply message produced by the gateway
|
||||
will contain all Message Headers present in the request message.
|
||||
</note>
|
||||
<para><emphasis>Cookies</emphasis></para>
|
||||
<para>
|
||||
Basic cookie support is provided by the <emphasis>transfer-cookies</emphasis> attribute on the outbound gateway. When
|
||||
@@ -158,8 +157,7 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
|
||||
If <emphasis>transfer-cookies</emphasis> is false, any <emphasis>Set-Cookie</emphasis> header received will
|
||||
remain as <emphasis>Set-Cookie</emphasis> in the reply message, and will be dropped on subsequent sends.
|
||||
</para>
|
||||
<para>
|
||||
<note>
|
||||
<note>
|
||||
<title>Note: Empty Repsonse Bodies</title>
|
||||
HTTP is a request/response protocol. However the response may not have a body, just headers.
|
||||
In this case, the <classname>HttpRequestExecutingMessageHandler</classname> produces
|
||||
@@ -174,8 +172,7 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
|
||||
routing logic after the Http Outbound Gateway. You could also use a
|
||||
<code><payload-type-router/></code> to route messages with an <classname>HttpEntity</classname>
|
||||
to a different flow than that used for responses with a body.
|
||||
</note>
|
||||
</para>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id="http-namespace">
|
||||
@@ -224,88 +221,140 @@ In the case of the Outbound Gateway, the reply message produced by the gateway w
|
||||
request-channel="requests"
|
||||
reply-channel="responses"/>]]></programlisting>
|
||||
|
||||
<important>
|
||||
<para>
|
||||
Beginning with <emphasis>Spring Integration 2.1</emphasis> the
|
||||
<emphasis>HTTP Inbound Gateway</emphasis> and the <emphasis>HTTP
|
||||
Inbound Channel Adapter</emphasis> should use the <emphasis>path</emphasis>
|
||||
attribute instead of the <emphasis>name</emphasis> attribute for
|
||||
specifying the request path. The <emphasis>name</emphasis> attribute
|
||||
for those 2 components has been deprecated.
|
||||
</para>
|
||||
<para>
|
||||
If you simply want to identify component itself within your application
|
||||
context, please use the <emphasis>id</emphasis> attribute.
|
||||
</para>
|
||||
</important>
|
||||
<para><emphasis>Request Mapping support</emphasis></para>
|
||||
<note>
|
||||
<emphasis>Spring Integration 3.0</emphasis> is improving the REST support by introducing the
|
||||
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html"
|
||||
>IntegrationRequestMappingHandlerMapping</ulink></interfacename>. The implementation relies on the enhanced REST support provided by Spring Framework 3.1 or higher.
|
||||
</note>
|
||||
<para>
|
||||
The parsing of the <emphasis>HTTP Inbound Gateway</emphasis> or the
|
||||
<emphasis>HTTP Inbound Channel Adapter</emphasis> registers an <code>integrationRequestMappingHandlerMapping</code>
|
||||
bean of type
|
||||
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html"
|
||||
>IntegrationRequestMappingHandlerMapping</ulink></interfacename>, in case there is none registered, yet. This particular implementation of the
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html"
|
||||
><interfacename>HandlerMapping</interfacename></ulink> delegates its logic to the
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.html"
|
||||
><interfacename>RequestMappingInfoHandlerMapping</interfacename></ulink>. The implementation provides similar functionality as the one provided by the
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html"
|
||||
><classname>org.springframework.web.bind.annotation.RequestMapping</classname></ulink> annotation in Spring MVC.
|
||||
</para>
|
||||
<note>
|
||||
For more information, please see
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping">Mapping Requests With @RequestMapping</ulink>.
|
||||
</note>
|
||||
<para>
|
||||
For this purpose, <emphasis>Spring Integration 3.0</emphasis> introduces the <code><request-mapping></code> sub-element.
|
||||
This optional sub-element can be added to the <code><http:inbound-channel-adapter></code> and the <code><http:inbound-gateway></code>.
|
||||
It works in conjunction with the <code>path</code> and <code>supported-methods</code> attributes:
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[<inbound-gateway id="inboundController"
|
||||
request-channel="requests"
|
||||
reply-channel="responses"
|
||||
path="/foo/{fooId}"
|
||||
supported-methods="GET"
|
||||
view-name="foo"
|
||||
error-code="oops">
|
||||
<request-mapping headers="User-Agent"
|
||||
params="myParam=myValue"
|
||||
consumes="application/json"
|
||||
produces="!text/plain"/>
|
||||
</inbound-gateway>]]></programlisting>
|
||||
<para>
|
||||
Based on this configuration, the namespace parser creates an instance of the <classname>IntegrationRequestMappingHandlerMapping</classname> (if none exists, yet),
|
||||
a <classname>HttpRequestHandlingController</classname> bean and associated with it an instance of
|
||||
<ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/RequestMapping.html"
|
||||
><classname>RequestMapping</classname></ulink>, which in turn, is converted to the Spring MVC
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/RequestMappingInfo.html"
|
||||
><classname>RequestMappingInfo</classname></ulink>.
|
||||
</para>
|
||||
<para>
|
||||
The <code><request-mapping></code> sub-element provides the following attributes:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>headers</listitem>
|
||||
<listitem>params</listitem>
|
||||
<listitem>consumes</listitem>
|
||||
<listitem>produces</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
With the <code>path</code> and <code>supported-methods</code> attributes of the <code><http:inbound-channel-adapter></code> or
|
||||
the <code><http:inbound-gateway></code>, <code><request-mapping></code> attributes translate directly into the respective options
|
||||
provided by the <classname>org.springframework.web.bind.annotation.RequestMapping</classname> annotation in Spring MVC.
|
||||
</para>
|
||||
<para>
|
||||
The <code><request-mapping></code> sub-element allows you to configure
|
||||
several <emphasis>Spring Integration</emphasis> HTTP Inbound Endpoints to the
|
||||
same <code>path</code> (or even the same <code>supported-methods</code>)
|
||||
and to provide different downstream message flows based on incoming HTTP requests.
|
||||
</para>
|
||||
<para>
|
||||
Alternatively, you can also declare just one HTTP Inbound Endpoint and
|
||||
apply routing and filtering logic within the <emphasis>Spring Integration</emphasis>
|
||||
flow to achieve the same result. This allows you to get the <interfacename>Message</interfacename>
|
||||
into the flow as early as possibly, e.g.:
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[<int-http:inbound-gateway request-channel="httpMethodRouter"
|
||||
supported-methods="GET,DELETE"
|
||||
path="/process/{entId}"
|
||||
payload-expression="#pathVariables.entId"/>
|
||||
|
||||
<para><emphasis>Defining the UriPathHandlerMapping</emphasis></para>
|
||||
<int:router input-channel="httpMethodRouter" expression="headers.http_requestMethod">
|
||||
<int:mapping value="GET" channel="in1"/>
|
||||
<int:mapping value="DELETE" channel="in2"/>
|
||||
</int:router>
|
||||
|
||||
<para>
|
||||
In order to use the <emphasis>HTTP Inbound Gateway</emphasis> or the
|
||||
<emphasis>HTTP Inbound Channel Adapter</emphasis> you must define a
|
||||
<int:service-activator input-channel="in1" ref="service" method="getEntity"/>
|
||||
|
||||
<interfacename><ulink url="http://static.springsource.org/spring-integration/api/org/springframework/integration/http/inbound/UriPathHandlerMapping.html"
|
||||
>UriPathHandlerMapping</ulink></interfacename>. This particular implementation of the
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html"
|
||||
><interfacename>HandlerMapping</interfacename></ulink> matches against
|
||||
the value of the <emphasis>path</emphasis> attribute.
|
||||
</para>
|
||||
<int:service-activator input-channel="in2" ref="service" method="delete"/>]]></programlisting>
|
||||
<para>
|
||||
For more information regarding <emphasis>Handler Mappings</emphasis>, please see:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping"></ulink>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<programlisting language="xml"><![CDATA[<bean class="org.springframework.integration.http.inbound.UriPathHandlerMapping"/>]]></programlisting>
|
||||
<para>
|
||||
For more information regarding <emphasis>Handler Mappings</emphasis>, please
|
||||
see:
|
||||
</para>
|
||||
<para><emphasis>URI Template Variables and Expressions</emphasis></para>
|
||||
<para>
|
||||
By Using the <emphasis>path</emphasis> attribute in conjunction with the
|
||||
<emphasis>payload-expression</emphasis> attribute as well as the <emphasis>
|
||||
header</emphasis> sub-element, you have a high degree of flexibility for
|
||||
mapping inbound request data.
|
||||
</para>
|
||||
<para>
|
||||
In the following example configuration, an Inbound Channel Adapter is
|
||||
configured to accept requests using the following URI:
|
||||
<emphasis>/first-name/{firstName}/last-name/{lastName}</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
Using the <emphasis>payload-expression</emphasis> attribute, the URI
|
||||
template variable <emphasis>{firstName}</emphasis> is mapped to be the
|
||||
Message payload, while the <emphasis>{lastName}</emphasis> URI template
|
||||
variable will map to the <emphasis>lname</emphasis> Message header.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping"></ulink>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><emphasis>URI Template Variables and Expressions</emphasis></para>
|
||||
|
||||
<para>
|
||||
By Using the <emphasis>path</emphasis> attribute in conjunction with the
|
||||
<emphasis>payload-expression</emphasis> attribute as well as the <emphasis>
|
||||
header</emphasis> sub-element, you have a high degree of flexiblity for
|
||||
mapping inbound request data.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the following example configuration, an Inbound Channel Adapter is
|
||||
configured to accept requests using the following URI:
|
||||
<emphasis>/first-name/{firstName}/last-name/{lastName}</emphasis>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Using the <emphasis>payload-expression</emphasis> attribute, the URI
|
||||
template variable <emphasis>{firstName}</emphasis> is mapped to be the
|
||||
Message payload, while the <emphasis>{lastName}</emphasis> URI template
|
||||
variable will map to the <emphasis>lname</emphasis> Message header.
|
||||
</para>
|
||||
|
||||
<programlisting language="xml"><![CDATA[<int-http:inbound-channel-adapter id="inboundAdapterWithExpressions"
|
||||
<programlisting language="xml"><![CDATA[<int-http:inbound-channel-adapter id="inboundAdapterWithExpressions"
|
||||
path="/first-name/{firstName}/last-name/{lastName}"
|
||||
channel="requests"
|
||||
payload-expression="#pathVariables.firstName">
|
||||
<int-http:header name="lname" expression="#pathVariables.lastName"/>
|
||||
</int-http:inbound-channel-adapter>]]></programlisting>
|
||||
|
||||
<para>
|
||||
For more information about <emphasis>URI template variables</emphasis>,
|
||||
please see the Spring Reference Manual:
|
||||
</para>
|
||||
<para>
|
||||
For more information about <emphasis>URI template variables</emphasis>,
|
||||
please see the Spring Reference Manual:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/htmlsingle/spring-framework-reference.html#mvc-ann-requestmapping"></ulink>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><emphasis>Outbound</emphasis></para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<ulink url="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-uri-templates"></ulink>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para><emphasis>Outbound</emphasis></para>
|
||||
<para>
|
||||
To configure the outbound gateway you can use the namespace support as well. The following code snippet shows the different configuration options for an outbound Http gateway. Most importantly, notice that the 'http-method' and 'expected-response-type' are provided. Those are two of the most commonly configured values. The
|
||||
default http-method is POST, and the default response type is <emphasis>null</emphasis>. With a null response type, the payload of the reply Message would
|
||||
|
||||
@@ -119,6 +119,19 @@
|
||||
For more information see <xref linkend="spel-property-accessors" />.
|
||||
</para>
|
||||
</section>
|
||||
<section id="3.0-request-mapping">
|
||||
<title>HTTP Request Mapping</title>
|
||||
<para>
|
||||
The HTTP module now provides powerful Request Mapping support for Inbound Endpoints. Class <classname>UriPathHandlerMapping</classname>
|
||||
was replaced by <classname>IntegrationRequestMappingHandlerMapping</classname>, which is registered under the bean name
|
||||
<code>integrationRequestMappingHandlerMapping</code> in the application context. Upon parsing of the HTTP Inbound Endpoint,
|
||||
a new <classname>IntegrationRequestMappingHandlerMapping</classname> bean is either registered or an existing bean is being reused.
|
||||
To achieve flexible Request Mapping configuration, Spring Integration provides the <code><request-mapping/></code>
|
||||
sub-element for <code><http:inbound-channel-adapter/></code> and <code><http:inbound-gateway/></code>.
|
||||
Both HTTP Inbound Endpoints are now fully based on the Request Mapping infrastructure that was introduced with Spring MVC 3.1.
|
||||
For more information see <xref linkend="http-namespace"/>.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="3.0-general">
|
||||
@@ -260,14 +273,14 @@
|
||||
<listitem>
|
||||
<emphasis role="bold">Outbound Endpoint 'encode-uri'</emphasis> - <code><http:outbound-gateway/></code>
|
||||
and <code><http:outbound-channel-adapter/></code> now
|
||||
provides an <code>encode-uri</code> attribute to allow disabling the encoding of the URI object
|
||||
provide an <code>encode-uri</code> attribute to allow disabling the encoding of the URI object
|
||||
before sending the request.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<emphasis role="bold">Inbound Endpoint 'merge-with-default-converters'</emphasis> -
|
||||
<code><http:inbound-gateway/></code> and <code><http:inbound-channel-adapter/></code> now
|
||||
have a <code>merge-with-default-converters</code> attribute to include the list of default
|
||||
<interfacename>HttpMessageConverter</interfacename> after the custom message converters.
|
||||
<interfacename>HttpMessageConverter</interfacename>s after the custom message converters.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<emphasis role="bold">'If-(Un)Modified-Since' HTTP headers</emphasis> - previously,
|
||||
|
||||
Reference in New Issue
Block a user