From bff8c9a9e6328ba12b6efc4ed9198f088399628e Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 30 Aug 2011 18:30:12 -0400 Subject: [PATCH] INT-1677 added initial spell support for extracting Request data --- .../HttpRequestHandlingEndpointSupport.java | 63 ++++++++++++++++- ...gMessagingGatewayWithPathMappingTests.java | 69 ++++++++++++++++++- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java index 5ccc417177..88e13b5bf0 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java @@ -17,6 +17,7 @@ package org.springframework.integration.http.inbound; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -28,6 +29,14 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.context.expression.MapAccessor; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.converter.Converter; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.expression.spel.support.StandardTypeConverter; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -82,9 +91,12 @@ import org.springframework.web.util.UriTemplate; * false. * * @author Mark Fisher + * @author Oleg Zhurakousky * @since 2.0 */ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySupport { + + private static final ExpressionParser PARSER = new SpelExpressionParser(); private static final boolean jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", HttpRequestHandlingEndpointSupport.class.getClassLoader()); @@ -112,6 +124,8 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor private volatile boolean extractReplyPayload = true; private volatile MultipartResolver multipartResolver; + + private final StandardEvaluationContext evaluationContext; public HttpRequestHandlingEndpointSupport() { this(true); @@ -137,6 +151,9 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor // this.messageConverters.add(new AtomFeedHttpMessageConverter()); // this.messageConverters.add(new RssChannelHttpMessageConverter()); } + StandardEvaluationContext sec = new StandardEvaluationContext(); + sec.addPropertyAccessor(new MapAccessor()); + this.evaluationContext = sec; } /** @@ -247,6 +264,13 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor } } } + if (beanFactory != null) { + this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); + } + ConversionService conversionService = this.getConversionService(); + if (conversionService != null) { + this.evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService)); + } } /** @@ -277,7 +301,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor Object payload = null; if (this.isReadable(request)) { - payload = this.generatePayloadFromRequestBody(request); + payload = this.extractRequestBody(request); headers.putAll(uriVariableMappings); } else { @@ -336,7 +360,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor if (this.multipartResolver != null && this.multipartResolver.isMultipart(servletRequest)) { return new MultipartHttpInputMessage(this.multipartResolver.resolveMultipart(servletRequest)); } - return new ServletServerHttpRequest(servletRequest); + return new SmartServletServerHttpRequest(servletRequest); } /** @@ -377,7 +401,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor } @SuppressWarnings({"unchecked", "rawtypes"}) - private Object generatePayloadFromRequestBody(ServletServerHttpRequest request) throws IOException { + private Object extractRequestBody(ServletServerHttpRequest request) throws IOException { MediaType contentType = request.getHeaders().getContentType(); Class expectedType = this.requestPayloadType; if (expectedType == null) { @@ -407,5 +431,38 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor } return httpStatus; } + + public class SmartServletServerHttpRequest extends ServletServerHttpRequest{ + + private final Map requestParamMap; + @SuppressWarnings("rawtypes") + private final Map uriVarsMap; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public SmartServletServerHttpRequest(HttpServletRequest servletRequest) { + super(servletRequest); + + requestParamMap = servletRequest.getParameterMap(); + Map uriVariableMappings = null; + // + if (StringUtils.hasText(HttpRequestHandlingEndpointSupport.this.path)){ + UriTemplate template = new UriTemplate(HttpRequestHandlingEndpointSupport.this.path); + uriVariableMappings = template.match(this.getURI().getPath()); + if (logger.isDebugEnabled()){ + logger.debug("Mapped URI variables: " + uriVariableMappings); + } + } + uriVarsMap = uriVariableMappings; + } + + public Map getRequestParamMap() { + return requestParamMap; + } + + @SuppressWarnings("rawtypes") + public Map getUriVars() { + return uriVarsMap; + } + } } diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayWithPathMappingTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayWithPathMappingTests.java index c52ca74e74..718614a4b3 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayWithPathMappingTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayWithPathMappingTests.java @@ -16,18 +16,32 @@ package org.springframework.integration.http.inbound; +import java.io.IOException; +import java.io.InputStream; import java.util.Collections; +import java.util.List; import java.util.Map; import org.junit.Test; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.ConversionServiceFactory; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.expression.spel.support.StandardTypeConverter; +import org.springframework.http.HttpHeaders; import org.springframework.integration.Message; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.http.MockHttpServletRequest; +import org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport.SmartServletServerHttpRequest; import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.util.CollectionUtils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; /** * @author Oleg Zhurakousky @@ -75,6 +89,59 @@ public class HttpRequestHandlingMessagingGatewayWithPathMappingTests { assertEquals(Collections.singletonList("bill"), payload.get("f")); assertEquals(Collections.singletonList("clinton"), payload.get("l")); } + /** + * This is a temporary test which simply shows what would happen inside of the gateway which has an internal + * capability for SpEL based extraction of data such as UriVariabe mappings, HttpHeaders, Body and Request Parameters. + * + * @throws Exception + */ + @Test + public void withExpression() 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"); + + HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true); + gateway.setPath("/fname/{f}/lname/{l}"); + + SmartServletServerHttpRequest smartRequest = gateway.new SmartServletServerHttpRequest(request); + + StandardEvaluationContext context = new StandardEvaluationContext(); + ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService(); + + context.setTypeConverter(new StandardTypeConverter(conversionService)); + + ExpressionParser parser = new SpelExpressionParser(); + + Expression bodyExpression = parser.parseExpression("#this.body"); + InputStream body = bodyExpression.getValue(context, smartRequest, InputStream.class); + assertNotNull(body); + assertEquals("hello", this.convertToString(body)); + + Expression headersExpression = parser.parseExpression("#this.headers['Content-Type']"); + List headers = headersExpression.getValue(context, smartRequest, List.class); + assertNotNull(headers); + assertEquals("text/plain", headers.get(0)); + + Expression uriVarsExpression = parser.parseExpression("#this.uriVars"); + Map uriVars = uriVarsExpression.getValue(context, smartRequest, Map.class); + assertNotNull(uriVars); + assertTrue(!CollectionUtils.isEmpty(uriVars)); + assertEquals("bill", "f"); + assertEquals("bill", "f"); + + } + + public String convertToString(InputStream in) throws IOException { + StringBuffer out = new StringBuffer(); + byte[] b = new byte[4096]; + for (int n; (n = in.read(b)) != -1;) { + out.append(new String(b, 0, n)); + } + return out.toString(); + } - }