INT-2448 Add view-expression to Http Inbound
https://jira.springsource.org/browse/INT-2488 Previously the view name could be specified; with this change, either the view name or a view-epression can be provided, with the reply message being the root object of the evaluation context. INT-2448 Polishing Remove deprecation from view-name. Reuse evaluation context. INT-2448 Polishing PR Comments
This commit is contained in:
committed by
Oleg Zhurakousky
parent
72f5a26682
commit
733e0ead45
@@ -27,9 +27,12 @@ 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.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -39,8 +42,8 @@ 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'.
|
||||
*
|
||||
* 'inbound-channel-adapter' and 'true' for the 'inbound-gateway'.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
@@ -57,9 +60,9 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return element.hasAttribute("view-name")
|
||||
? "org.springframework.integration.http.inbound.HttpRequestHandlingController"
|
||||
: "org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway";
|
||||
return element.hasAttribute("view-name") || element.hasAttribute("view-expression")
|
||||
? HttpRequestHandlingController.class.getName()
|
||||
: HttpRequestHandlingMessagingGateway.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,18 +99,18 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
}
|
||||
builder.addPropertyReference("requestChannel", inputChannelRef);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-channel");
|
||||
|
||||
|
||||
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "path");
|
||||
String payloadExpression = element.getAttribute("payload-expression");
|
||||
if (StringUtils.hasText(payloadExpression)){
|
||||
if (StringUtils.hasText(payloadExpression)) {
|
||||
RootBeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(payloadExpression);
|
||||
builder.addPropertyValue("payloadExpression", expressionDef);
|
||||
}
|
||||
|
||||
|
||||
List<Element> headerElements = DomUtils.getChildElementsByTagName(element, "header");
|
||||
|
||||
|
||||
if (!CollectionUtils.isEmpty(headerElements)) {
|
||||
ManagedMap<String, Object> headerElementsMap = new ManagedMap<String, Object>();
|
||||
for (Element headerElement : headerElements) {
|
||||
@@ -117,11 +120,11 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
RootBeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class);
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expression);
|
||||
headerElementsMap.put(name, expressionDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.addPropertyValue("headerExpressions", headerElementsMap);
|
||||
}
|
||||
|
||||
|
||||
if (this.expectReply) {
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-timeout");
|
||||
@@ -136,18 +139,34 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "supported-methods", "supportedMethodNames");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-payload-type");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "view-name");
|
||||
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);
|
||||
builder.addPropertyValue("viewExpression", expressionDef);
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "errors-key");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "error-code");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-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");
|
||||
|
||||
|
||||
|
||||
|
||||
if (StringUtils.hasText(headerMapper)) {
|
||||
if (StringUtils.hasText(mappedRequestHeaders) || StringUtils.hasText(mappedResponseHeaders)) {
|
||||
parserContext.getReaderContext().error("Neither 'mappped-request-headers' or 'mapped-response-headers' " +
|
||||
@@ -159,7 +178,7 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse
|
||||
BeanDefinitionBuilder headerMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.http.support.DefaultHttpHeaderMapper");
|
||||
headerMapperBuilder.setFactoryMethod("inboundMapper");
|
||||
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(headerMapperBuilder, element, "mapped-request-headers", "inboundHeaderNames");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(headerMapperBuilder, element, "mapped-response-headers", "outboundHeaderNames");
|
||||
builder.addPropertyValue("headerMapper", headerMapperBuilder.getBeanDefinition());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -24,9 +24,16 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.MapBindingResult;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.mvc.Controller;
|
||||
|
||||
/**
|
||||
@@ -40,8 +47,9 @@ import org.springframework.web.servlet.mvc.Controller;
|
||||
* reply Message or payload depending on the value of {@link #extractReplyPayload} (true by default, meaning just the
|
||||
* payload). The corresponding key in the map is determined by the {@link #replyKey} property (with a default of
|
||||
* "reply").
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSupport implements Controller {
|
||||
@@ -52,7 +60,9 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
|
||||
|
||||
private static final String DEFAULT_ERRORS_KEY = "errors";
|
||||
|
||||
private volatile String viewName;
|
||||
private volatile Expression viewExpression;
|
||||
|
||||
private volatile StandardEvaluationContext evaluationContext;
|
||||
|
||||
private volatile String replyKey = DEFAULT_REPLY_KEY;
|
||||
|
||||
@@ -72,7 +82,8 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
|
||||
* Specify the view name.
|
||||
*/
|
||||
public void setViewName(String viewName) {
|
||||
this.viewName = viewName;
|
||||
Assert.isTrue(StringUtils.hasText(viewName), "View name must contain text");
|
||||
this.viewExpression = new LiteralExpression(viewName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,13 +109,27 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
|
||||
* provided in an object error to be optionally translated in the standard MVC way using a {@link MessageSource}.
|
||||
* The default value is <code>spring.integration.http.handler.error</code>. Three arguments are provided: the
|
||||
* exception, its message and its stack trace as a String.
|
||||
*
|
||||
*
|
||||
* @param errorCode the error code to set
|
||||
*/
|
||||
public void setErrorCode(String errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a SpEL expression to evaluate in order to generate the view name.
|
||||
* The EvaluationContext will be populated with the reply message as the root object,
|
||||
*/
|
||||
public void setViewExpression(Expression viewExpression) {
|
||||
this.viewExpression = viewExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
super.onInit();
|
||||
this.evaluationContext = this.createEvaluationContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -112,14 +137,30 @@ public class HttpRequestHandlingController extends HttpRequestHandlingEndpointSu
|
||||
public final ModelAndView handleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
|
||||
throws Exception {
|
||||
ModelAndView modelAndView = new ModelAndView();
|
||||
if (this.viewName != null) {
|
||||
modelAndView.setViewName(this.viewName);
|
||||
}
|
||||
try {
|
||||
Object reply = super.doHandleRequest(servletRequest, servletResponse);
|
||||
if (reply != null) {
|
||||
Message<?> replyMessage = super.doHandleRequest(servletRequest, servletResponse);
|
||||
if (replyMessage != null) {
|
||||
Object reply = setupResponseAndConvertReply(servletResponse, replyMessage);
|
||||
modelAndView.addObject(this.replyKey, reply);
|
||||
}
|
||||
if (this.viewExpression != null) {
|
||||
Object view;
|
||||
if (replyMessage != null) {
|
||||
view = this.viewExpression.getValue(this.evaluationContext, replyMessage);
|
||||
}
|
||||
else {
|
||||
view = this.viewExpression.getValue(this.evaluationContext);
|
||||
}
|
||||
if (view instanceof View) {
|
||||
modelAndView.setView((View) view);
|
||||
}
|
||||
else if (view instanceof String) {
|
||||
modelAndView.setViewName((String) view);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("view expression must resolve to a View or String");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
MapBindingResult errors = new MapBindingResult(new HashMap<String, Object>(), "dummy");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -91,13 +91,14 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
* 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>.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySupport {
|
||||
|
||||
|
||||
private static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder",
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader());
|
||||
|
||||
@@ -105,7 +106,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader())
|
||||
&& ClassUtils.isPresent("org.codehaus.jackson.JsonGenerator", HttpRequestHandlingEndpointSupport.class
|
||||
.getClassLoader());
|
||||
|
||||
|
||||
private static boolean romePresent = ClassUtils.isPresent("com.sun.syndication.feed.WireFeed",
|
||||
HttpRequestHandlingEndpointSupport.class.getClassLoader());
|
||||
|
||||
@@ -128,7 +129,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
private volatile boolean extractReplyPayload = true;
|
||||
|
||||
private volatile MultipartResolver multipartResolver;
|
||||
|
||||
|
||||
private volatile Expression payloadExpression;
|
||||
|
||||
private volatile Map<String, Expression> headerExpressions;
|
||||
@@ -154,10 +155,10 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
}
|
||||
if (romePresent) {
|
||||
this.messageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.messageConverters.add(new RssChannelHttpMessageConverter());
|
||||
this.messageConverters.add(new RssChannelHttpMessageConverter());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return whether to expect reply
|
||||
*/
|
||||
@@ -167,12 +168,12 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
|
||||
/**
|
||||
* Set the path template for which this endpoint expects requests.
|
||||
* May include path variable {keys} to match against.
|
||||
* May include path variable {keys} to match against.
|
||||
*/
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
|
||||
String getPath() {
|
||||
return path;
|
||||
}
|
||||
@@ -300,9 +301,10 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
/**
|
||||
* Handles the HTTP request by generating a Message and sending it to the request channel. If this gateway's
|
||||
* 'expectReply' property is true, it will also generate a response from the reply Message once received.
|
||||
* @return a the response Message
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
protected final Object doHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
|
||||
protected final Message<?> doHandleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
|
||||
try {
|
||||
ServletServerHttpRequest request = this.prepareRequest(servletRequest);
|
||||
if (!this.supportedMethods.contains(request.getMethod())) {
|
||||
@@ -351,13 +353,13 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
|
||||
if (payload == null) {
|
||||
if (requestBody != null) {
|
||||
payload = requestBody;
|
||||
payload = requestBody;
|
||||
}
|
||||
else {
|
||||
payload = requestParams;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MessageBuilder<?> messageBuilder = null;
|
||||
|
||||
if (payload instanceof Message<?>){
|
||||
@@ -366,28 +368,16 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
else {
|
||||
messageBuilder = MessageBuilder.withPayload(payload).copyHeaders(headers);
|
||||
}
|
||||
|
||||
|
||||
Message<?> message = messageBuilder
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_URL, request.getURI().toString())
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.REQUEST_METHOD, request.getMethod().toString())
|
||||
.setHeader(org.springframework.integration.http.HttpHeaders.USER_PRINCIPAL, servletRequest.getUserPrincipal())
|
||||
.build();
|
||||
|
||||
Object reply = null;
|
||||
|
||||
Message<?> reply = null;
|
||||
if (this.expectReply) {
|
||||
reply = this.sendAndReceiveMessage(message);
|
||||
if (reply != null) {
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
this.headerMapper.fromHeaders(((Message<?>) reply).getHeaders(), response.getHeaders());
|
||||
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(((Message<?>) reply).getHeaders());
|
||||
if (httpStatus != null) {
|
||||
response.setStatusCode(httpStatus);
|
||||
}
|
||||
response.close();
|
||||
if (this.extractReplyPayload) {
|
||||
reply = ((Message<?>) reply).getPayload();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.send(message);
|
||||
@@ -399,6 +389,29 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the reply message to the appropriate HTTP reply object and
|
||||
* sets up the servlet response.
|
||||
* @param servletResponse The servlet response.
|
||||
* @param replyMessage The reply message.
|
||||
* @return The message payload (if {@link #extractReplyPayload}) otherwise the
|
||||
* message.
|
||||
*/
|
||||
protected final Object setupResponseAndConvertReply(HttpServletResponse servletResponse, Message<?> replyMessage) {
|
||||
ServletServerHttpResponse response = new ServletServerHttpResponse(servletResponse);
|
||||
this.headerMapper.fromHeaders(replyMessage.getHeaders(), response.getHeaders());
|
||||
HttpStatus httpStatus = this.resolveHttpStatusFromHeaders(((Message<?>) replyMessage).getHeaders());
|
||||
if (httpStatus != null) {
|
||||
response.setStatusCode(httpStatus);
|
||||
}
|
||||
response.close();
|
||||
Object reply = replyMessage;
|
||||
if (this.extractReplyPayload) {
|
||||
reply = replyMessage.getPayload();
|
||||
}
|
||||
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,
|
||||
@@ -485,8 +498,8 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor
|
||||
}
|
||||
return httpStatus;
|
||||
}
|
||||
|
||||
private StandardEvaluationContext createEvaluationContext(){
|
||||
|
||||
protected StandardEvaluationContext createEvaluationContext(){
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
BeanFactory beanFactory = this.getBeanFactory();
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -53,7 +54,7 @@ import org.springframework.web.HttpRequestHandler;
|
||||
* <p/>
|
||||
* By default a number of {@link HttpMessageConverter}s are already configured. The list can be overridden by calling
|
||||
* the {@link #setMessageConverters(List)} method.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
@@ -76,7 +77,7 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
|
||||
* Flag to determine if conversion and writing out of message handling exceptions should be attempted (default
|
||||
* false, in which case they will simply be re-thrown). If the flag is true and no message converter can convert the
|
||||
* exception a new exception will be thrown.
|
||||
*
|
||||
*
|
||||
* @param convertExceptions the flag to set
|
||||
*/
|
||||
public void setConvertExceptions(boolean convertExceptions) {
|
||||
@@ -91,8 +92,12 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp
|
||||
public final void handleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
|
||||
throws ServletException, IOException {
|
||||
Object responseContent = null;
|
||||
Message<?> responseMessage;
|
||||
try {
|
||||
responseContent = super.doHandleRequest(servletRequest, servletResponse);
|
||||
responseMessage = super.doHandleRequest(servletRequest, servletResponse);
|
||||
if (responseMessage != null) {
|
||||
responseContent = setupResponseAndConvertReply(servletResponse, responseMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
responseContent = handleExceptionInternal(e);
|
||||
|
||||
@@ -191,6 +191,15 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
</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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="errors-key" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -28,6 +28,12 @@
|
||||
|
||||
<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"/>
|
||||
|
||||
<inbound-gateway id="withMappedHeaders" request-channel="requests"
|
||||
mapped-response-headers="abc, xyz"
|
||||
mapped-request-headers="foo,bar"/>
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
@@ -61,15 +63,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class HttpInboundGatewayParserTests {
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("inboundGateway")
|
||||
private HttpRequestHandlingMessagingGateway gateway;
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("withMappedHeaders")
|
||||
private HttpRequestHandlingMessagingGateway withMappedHeaders;
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("withMappedHeadersAndConverter")
|
||||
private HttpRequestHandlingMessagingGateway withMappedHeadersAndConverter;
|
||||
@@ -77,6 +79,9 @@ public class HttpInboundGatewayParserTests {
|
||||
@Autowired
|
||||
private HttpRequestHandlingController inboundController;
|
||||
|
||||
@Autowired
|
||||
private HttpRequestHandlingController inboundControllerViewExp;
|
||||
|
||||
@Autowired
|
||||
private SubscribableChannel requests;
|
||||
|
||||
@@ -96,7 +101,7 @@ public class HttpInboundGatewayParserTests {
|
||||
assertEquals(Long.valueOf(1234), TestUtils.getPropertyValue(messagingTemplate, "sendTimeout"));
|
||||
assertEquals(Long.valueOf(4567), TestUtils.getPropertyValue(messagingTemplate, "receiveTimeout"));
|
||||
}
|
||||
|
||||
|
||||
@Test(timeout=1000)
|
||||
public void checkFlow() throws Exception {
|
||||
requests.subscribe(handlerExpecting(any(Message.class)));
|
||||
@@ -115,13 +120,25 @@ public class HttpInboundGatewayParserTests {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(inboundController);
|
||||
String errorCode = (String) accessor.getPropertyValue("errorCode");
|
||||
assertEquals("oops", errorCode);
|
||||
LiteralExpression viewExpression = (LiteralExpression) accessor.getPropertyValue("viewExpression");
|
||||
assertEquals("foo", viewExpression.getValue());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testControllerViewExp() throws Exception {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(inboundControllerViewExp);
|
||||
String errorCode = (String) accessor.getPropertyValue("errorCode");
|
||||
assertEquals("oops", errorCode);
|
||||
SpelExpression viewExpression = (SpelExpression) accessor.getPropertyValue("viewExpression");
|
||||
assertNotNull(viewExpression);
|
||||
assertEquals("'bar'", viewExpression.getExpressionString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeaders() throws Exception {
|
||||
DefaultHttpHeaderMapper headerMapper =
|
||||
DefaultHttpHeaderMapper headerMapper =
|
||||
(DefaultHttpHeaderMapper) TestUtils.getPropertyValue(withMappedHeaders, "headerMapper");
|
||||
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("foo", "foo");
|
||||
headers.set("bar", "bar");
|
||||
@@ -130,7 +147,7 @@ public class HttpInboundGatewayParserTests {
|
||||
assertTrue(map.size() == 2);
|
||||
assertEquals("foo", map.get("foo"));
|
||||
assertEquals("bar", map.get("bar"));
|
||||
|
||||
|
||||
Map<String, Object> mapOfHeaders = new HashMap<String, Object>();
|
||||
mapOfHeaders.put("abc", "abc");
|
||||
MessageHeaders mh = new MessageHeaders(mapOfHeaders);
|
||||
@@ -140,12 +157,12 @@ public class HttpInboundGatewayParserTests {
|
||||
List<String> abc = headers.get("X-abc");
|
||||
assertEquals("abc", abc.get(0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void requestWithHeadersWithConversionService() throws Exception {
|
||||
DefaultHttpHeaderMapper headerMapper =
|
||||
DefaultHttpHeaderMapper headerMapper =
|
||||
(DefaultHttpHeaderMapper) TestUtils.getPropertyValue(withMappedHeadersAndConverter, "headerMapper");
|
||||
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("foo", "foo");
|
||||
headers.set("bar", "bar");
|
||||
@@ -154,7 +171,7 @@ public class HttpInboundGatewayParserTests {
|
||||
assertTrue(map.size() == 2);
|
||||
assertEquals("foo", map.get("foo"));
|
||||
assertEquals("bar", map.get("bar"));
|
||||
|
||||
|
||||
Map<String, Object> mapOfHeaders = new HashMap<String, Object>();
|
||||
mapOfHeaders.put("abc", "abc");
|
||||
Person person = new Person();
|
||||
@@ -169,7 +186,7 @@ public class HttpInboundGatewayParserTests {
|
||||
List<String> personHeaders = headers.get("X-person");
|
||||
assertEquals("Oleg", personHeaders.get(0));
|
||||
}
|
||||
|
||||
|
||||
public static class Person{
|
||||
private String name;
|
||||
|
||||
@@ -181,13 +198,13 @@ public class HttpInboundGatewayParserTests {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class PersonConverter implements Converter<Person, String>{
|
||||
|
||||
public String convert(Person source) {
|
||||
return source.getName();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,21 +19,28 @@ package org.springframework.integration.http.inbound;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.View;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class HttpRequestHandlingControllerTests {
|
||||
@@ -57,6 +64,26 @@ public class HttpRequestHandlingControllerTests {
|
||||
assertEquals("hello", requestMessage.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendOnlyViewExpression() throws Exception {
|
||||
QueueChannel requestChannel = new QueueChannel();
|
||||
HttpRequestHandlingController controller = new HttpRequestHandlingController(false);
|
||||
controller.setRequestChannel(requestChannel);
|
||||
Expression viewExpression = new SpelExpressionParser().parseExpression("'baz'");
|
||||
controller.setViewExpression(viewExpression);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setContentType("text/plain");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView modelAndView = controller.handleRequest(request, response);
|
||||
assertEquals("baz", modelAndView.getViewName());
|
||||
assertEquals(0, modelAndView.getModel().size());
|
||||
Message<?> requestMessage = requestChannel.receive(0);
|
||||
assertNotNull(requestMessage);
|
||||
assertEquals("hello", requestMessage.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestReply() throws Exception {
|
||||
DirectChannel requestChannel = new DirectChannel();
|
||||
@@ -83,6 +110,63 @@ public class HttpRequestHandlingControllerTests {
|
||||
assertEquals("HELLO", reply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestReplyViewExpressionString() throws Exception {
|
||||
DirectChannel requestChannel = new DirectChannel();
|
||||
AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
|
||||
@Override
|
||||
protected Message<String> handleRequestMessage(Message<?> requestMessage) {
|
||||
return MessageBuilder.withPayload("foo")
|
||||
.setHeader("bar", "baz").build();
|
||||
}
|
||||
};
|
||||
requestChannel.subscribe(handler);
|
||||
HttpRequestHandlingController controller = new HttpRequestHandlingController(true);
|
||||
controller.setRequestChannel(requestChannel);
|
||||
Expression viewExpression = new SpelExpressionParser().parseExpression("headers['bar']");
|
||||
controller.setViewExpression(viewExpression);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setContentType("text/plain");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView modelAndView = controller.handleRequest(request, response);
|
||||
assertEquals("baz", modelAndView.getViewName());
|
||||
assertEquals(1, modelAndView.getModel().size());
|
||||
Object reply = modelAndView.getModel().get("reply");
|
||||
assertNotNull(reply);
|
||||
assertEquals("foo", reply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestReplyViewExpressionView() throws Exception {
|
||||
final View view = mock(View.class);
|
||||
DirectChannel requestChannel = new DirectChannel();
|
||||
AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
|
||||
@Override
|
||||
protected Message<String> handleRequestMessage(Message<?> requestMessage) {
|
||||
return MessageBuilder.withPayload("foo")
|
||||
.setHeader("bar", view).build();
|
||||
}
|
||||
};
|
||||
requestChannel.subscribe(handler);
|
||||
HttpRequestHandlingController controller = new HttpRequestHandlingController(true);
|
||||
controller.setRequestChannel(requestChannel);
|
||||
Expression viewExpression = new SpelExpressionParser().parseExpression("headers['bar']");
|
||||
controller.setViewExpression(viewExpression);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setContentType("text/plain");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
ModelAndView modelAndView = controller.handleRequest(request, response);
|
||||
assertSame(view, modelAndView.getView());
|
||||
assertEquals(1, modelAndView.getModel().size());
|
||||
Object reply = modelAndView.getModel().get("reply");
|
||||
assertNotNull(reply);
|
||||
assertEquals("foo", reply);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestReplyWithCustomReplyKey() throws Exception {
|
||||
DirectChannel requestChannel = new DirectChannel();
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.springframework.util.SerializationUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class HttpRequestHandlingMessagingGatewayTests {
|
||||
@@ -89,6 +90,7 @@ public class HttpRequestHandlingMessagingGatewayTests {
|
||||
public void stringExpectedWithReply() throws Exception {
|
||||
DirectChannel requestChannel = new DirectChannel();
|
||||
requestChannel.subscribe(new AbstractReplyProducingMessageHandler() {
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
return requestMessage.getPayload().toString().toUpperCase();
|
||||
}
|
||||
@@ -110,6 +112,7 @@ public class HttpRequestHandlingMessagingGatewayTests {
|
||||
public void noAcceptHeaderOnRequest() throws Exception {
|
||||
DirectChannel requestChannel = new DirectChannel();
|
||||
requestChannel.subscribe(new AbstractReplyProducingMessageHandler() {
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> requestMessage) {
|
||||
return requestMessage.getPayload().toString().toUpperCase();
|
||||
}
|
||||
@@ -149,7 +152,7 @@ public class HttpRequestHandlingMessagingGatewayTests {
|
||||
|
||||
@Test
|
||||
public void multiValueParameterMap() throws Exception {
|
||||
QueueChannel channel = new QueueChannel();
|
||||
QueueChannel channel = new QueueChannel();
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false);
|
||||
gateway.setRequestChannel(channel);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test");
|
||||
@@ -175,7 +178,7 @@ public class HttpRequestHandlingMessagingGatewayTests {
|
||||
|
||||
@Test
|
||||
public void serializableRequestBody() throws Exception {
|
||||
QueueChannel channel = new QueueChannel();
|
||||
QueueChannel channel = new QueueChannel();
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false);
|
||||
gateway.setRequestPayloadType(TestBean.class);
|
||||
gateway.setRequestChannel(channel);
|
||||
@@ -200,7 +203,7 @@ public class HttpRequestHandlingMessagingGatewayTests {
|
||||
|
||||
|
||||
private static class TestHttpMessageConverter extends AbstractHttpMessageConverter<Exception> {
|
||||
|
||||
|
||||
public TestHttpMessageConverter() {
|
||||
setSupportedMediaTypes(Arrays.asList(MediaType.ALL));
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.springframework.integration.http.inbound;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
@@ -30,21 +32,20 @@ import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
|
||||
|
||||
private static ExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void withoutExpression() throws Exception {
|
||||
DirectChannel echoChannel = new DirectChannel();
|
||||
echoChannel.subscribe(new MessageHandler() {
|
||||
|
||||
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
|
||||
replyChannel.send(message);
|
||||
@@ -56,18 +57,19 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
|
||||
Object result = gateway.doHandleRequest(request, response);
|
||||
assertEquals("hello", result);
|
||||
|
||||
assertTrue(result instanceof Message);
|
||||
assertEquals("hello", ((Message<?>) result).getPayload());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withPayloadExpressionPointingToPathVariable() throws Exception {
|
||||
DirectChannel echoChannel = new DirectChannel();
|
||||
@@ -92,16 +94,17 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables.f"));
|
||||
|
||||
Object result = gateway.doHandleRequest(request, response);
|
||||
assertEquals("bill", result);
|
||||
assertTrue(result instanceof Message);
|
||||
assertEquals("bill", ((Message<?>)result).getPayload());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void withoutPayloadExpressionPointingToUriVariables() throws Exception {
|
||||
|
||||
|
||||
DirectChannel echoChannel = new DirectChannel();
|
||||
echoChannel.subscribe(new MessageHandler() {
|
||||
|
||||
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
MessageChannel replyChannel = (MessageChannel) message.getHeaders().getReplyChannel();
|
||||
replyChannel.send(message);
|
||||
@@ -109,20 +112,21 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests {
|
||||
});
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
|
||||
request.setMethod("POST");
|
||||
request.setContentType("text/plain");
|
||||
request.setParameter("foo", "bar");
|
||||
request.setContent("hello".getBytes());
|
||||
request.setRequestURI("/fname/bill/lname/clinton");
|
||||
|
||||
|
||||
HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true);
|
||||
gateway.setPath("/fname/{f}/lname/{l}");
|
||||
gateway.setRequestChannel(echoChannel);
|
||||
gateway.setPayloadExpression(PARSER.parseExpression("#pathVariables"));
|
||||
|
||||
|
||||
Object result = gateway.doHandleRequest(request, response);
|
||||
assertEquals("bill", ((Map<String, Object>)result).get("f"));
|
||||
assertTrue(result instanceof Message);
|
||||
assertEquals("bill", ((Map<String, Object>) ((Message<?>)result).getPayload()).get("f"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user