diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/ContentTypeResolver.java b/spring-integration-http/src/main/java/org/springframework/integration/http/ContentTypeResolver.java deleted file mode 100644 index 62040fdcce..0000000000 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/ContentTypeResolver.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2002-2010 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; - -import org.springframework.http.MediaType; - -/** - * Strategy for resolving the content type of a given object. The content type - * will be represented as an instance of the {@link MediaType} enum. - * - * @author Mark Fisher - * @since 2.0 - */ -public interface ContentTypeResolver { - - /** - * Resolves the content type of a given object. - * - * @param content the object whose content type should be resolved - */ - MediaType resolveContentType(Object content); - - /** - * Resolves the content type of a given String instance and charset name. - * - * @param content the String whose content type should be resolved - * @param charset charset name - */ - MediaType resolveContentType(String content, String charset); - -} diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/DataBindingInboundRequestMapper.java b/spring-integration-http/src/main/java/org/springframework/integration/http/DataBindingInboundRequestMapper.java deleted file mode 100644 index 2d80509227..0000000000 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/DataBindingInboundRequestMapper.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2002-2009 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; - -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.integration.Message; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.util.Assert; -import org.springframework.web.bind.ServletRequestDataBinder; -import org.springframework.web.bind.support.WebBindingInitializer; -import org.springframework.web.servlet.handler.DispatcherServletWebRequest; - -/** - * InboundRequestMapper implementation that binds the request parameter map to - * a target instance. The target instance may be a non-singleton bean as - * specified by the {@link #setTargetBeanName(String) 'targetBeanName'} - * property. Otherwise, this mapper's target type must provide a default, - * no-arg constructor. - * - * @author Mark Fisher - * @since 1.0.2 - */ -public class DataBindingInboundRequestMapper implements InboundRequestMapper, BeanFactoryAware, InitializingBean { - - private volatile Class targetType = Object.class; - - private volatile String targetBeanName; - - private volatile WebBindingInitializer webBindingInitializer; - - private volatile BeanFactory beanFactory; - - private volatile boolean validated; - - - public DataBindingInboundRequestMapper() { - this.targetType = Object.class; - } - - public DataBindingInboundRequestMapper(Class targetType) { - Assert.notNull(targetType, "targetType must not be null"); - this.targetType = targetType; - } - - - public void setTargetType(Class targetType) { - this.targetType = targetType; - } - - /** - * Specify the name of a bean definition to use when creating the target - * instance. The bean must not be a singleton, and it must be - * compatible with the {@link #targetType}. - *

If no 'targetBeanName' value is provided, the target type must - * provide a default, no-arg constructor. - */ - public void setTargetBeanName(String targetBeanName) { - this.targetBeanName = targetBeanName; - } - - /** - * Specify an optional {@link WebBindingInitializer} to be invoked prior - * to the request binding process. - */ - public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) { - this.webBindingInitializer = webBindingInitializer; - } - - /** - * Provides the {@link BeanFactory} necessary to look up a - * {@link #setTargetBeanName(String) 'targetBeanName'} if specified. - * This method is typically invoked automatically by the container. - */ - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } - - public final void afterPropertiesSet() { - if (this.targetBeanName == null && Object.class.equals(this.targetType)) { - throw new IllegalArgumentException( - "When no 'targetBeanName' is provided, the 'targetType' must be more specific than Object."); - } - this.validateTargetBeanIfNecessary(); - } - - private void validateTargetBeanIfNecessary() { - if (this.targetBeanName != null && !this.validated) { - Assert.notNull(this.beanFactory, "beanFactory is required for binding to a bean"); - if (this.beanFactory.isSingleton(this.targetBeanName)) { - throw new IllegalArgumentException("binding target bean must not be a singleton"); - } - Class beanType = this.beanFactory.getType(this.targetBeanName); - if (beanType != null) { - Assert.isAssignable(this.targetType, beanType); - } - this.validated = true; - } - } - - @SuppressWarnings("unchecked") - public Message toMessage(HttpServletRequest request) throws Exception { - ServletRequestDataBinder binder = new ServletRequestDataBinder(getTarget()); - this.initBinder(binder, request); - binder.bind(request); - // this will immediately throw any bind Exceptions - Map map = binder.close(); - Object payload = map.get(ServletRequestDataBinder.DEFAULT_OBJECT_NAME); - return MessageBuilder.withPayload(payload).build(); - } - - private void initBinder(ServletRequestDataBinder binder, HttpServletRequest request) { - if (this.webBindingInitializer != null) { - this.webBindingInitializer.initBinder(binder, new DispatcherServletWebRequest(request)); - } - } - - private Object getTarget() throws InstantiationException, IllegalAccessException { - if (this.targetBeanName != null) { - this.validateTargetBeanIfNecessary(); - return this.beanFactory.getBean(this.targetBeanName, this.targetType); - } - return this.targetType.newInstance(); - } - -} diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java index 298f8bfea7..d9ba35685d 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java @@ -106,7 +106,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor this(true); } - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") public HttpRequestHandlingEndpointSupport(boolean expectReply) { this.expectReply = expectReply; this.messageConverters.add(new MultipartAwareFormHttpMessageConverter()); @@ -324,7 +324,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor /** * Converts a servlet request's parameterMap to a {@link MultiValueMap}. */ - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") private LinkedMultiValueMap convertParameterMap(Map parameterMap) { LinkedMultiValueMap convertedMap = new LinkedMultiValueMap(); for (Object key : parameterMap.keySet()) { @@ -336,7 +336,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor return convertedMap; } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) private Object generatePayloadFromRequestBody(ServletServerHttpRequest request) throws IOException { MediaType contentType = request.getHeaders().getContentType(); Class expectedType = this.requestPayloadType; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java index efcdbc2f57..cd77aecb16 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java @@ -53,11 +53,11 @@ import org.springframework.web.HttpRequestHandler; * @author Mark Fisher * @since 2.0 */ -public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndpointSupport implements - HttpRequestHandler { +public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndpointSupport implements HttpRequestHandler { private volatile boolean convertExceptions; + public HttpRequestHandlingMessagingGateway() { this(true); } @@ -66,6 +66,7 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp super(expectReply); } + /** * 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 @@ -99,22 +100,24 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp } private Object handleExceptionInternal(Exception e) throws IOException { - if (convertExceptions && isExpectReply()) { + if (this.convertExceptions && isExpectReply()) { return e; } else { if (e instanceof IOException) { throw (IOException) e; } - else { + else if (e instanceof RuntimeException) { throw (RuntimeException) e; } + else { + throw new MessagingException("error occurred handling HTTP request", e); + } } } - @SuppressWarnings("unchecked") - private void writeResponse(Object content, ServletServerHttpResponse response, List acceptTypes) - throws IOException { + @SuppressWarnings({"unchecked", "rawtypes"}) + private void writeResponse(Object content, ServletServerHttpResponse response, List acceptTypes) throws IOException { for (HttpMessageConverter converter : this.getMessageConverters()) { for (MediaType acceptType : acceptTypes) { if (converter.canWrite(content.getClass(), acceptType)) { diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java index 44b333b9ba..bcbb2e519e 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java @@ -98,10 +98,9 @@ public class MultipartAwareFormHttpMessageConverter implements HttpMessageConver return this.readMultipart(multipartInputMessage); } - @SuppressWarnings("unchecked") private MultiValueMap readMultipart(MultipartHttpInputMessage multipartRequest) throws IOException { MultiValueMap resultMap = new LinkedMultiValueMap(); - Map parameterMap = multipartRequest.getParameterMap(); + Map parameterMap = multipartRequest.getParameterMap(); for (Object key : parameterMap.keySet()) { resultMap.add((String) key, parameterMap.get(key)); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java index 9f57bfe551..b83cff4bfd 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java @@ -62,7 +62,7 @@ public class MultipartHttpInputMessage extends ServletServerHttpRequest implemen } // TODO: return MultiValueMap? - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") public Map getParameterMap() { return this.multipartServletRequest.getParameterMap(); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java b/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java index 78130d59d5..984e1cbade 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java @@ -62,7 +62,7 @@ public class SerializingHttpMessageConverter extends AbstractHttpMessageConverte } @Override - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") public Serializable readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { try { return (Serializable) new ObjectInputStream(inputMessage.getBody()).readObject(); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/DataBindingInboundRequestMapperTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/DataBindingInboundRequestMapperTests.java deleted file mode 100644 index dcb20e57ba..0000000000 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/DataBindingInboundRequestMapperTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2009 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; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; - -import org.springframework.beans.MutablePropertyValues; -import org.springframework.context.support.StaticApplicationContext; -import org.springframework.integration.Message; -import org.springframework.integration.http.DataBindingInboundRequestMapper; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; - -/** - * @author Mark Fisher - */ -public class DataBindingInboundRequestMapperTests { - - @Test - public void bindToType() throws Exception { - DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setParameter("name", "testBean"); - request.setParameter("age", "42"); - Message result = mapper.toMessage(request); - assertNotNull(result); - assertEquals(TestBean.class, result.getPayload().getClass()); - TestBean payload = (TestBean) result.getPayload(); - assertEquals("testBean", payload.name); - assertEquals(84, payload.age); - } - - @Test - public void bindToTypeWithBindingInitializer() throws Exception { - DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class); - ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer(); - initializer.setDirectFieldAccess(true); - mapper.setWebBindingInitializer(initializer); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setParameter("name", "testBean"); - request.setParameter("age", "42"); - Message result = mapper.toMessage(request); - assertNotNull(result); - assertEquals(TestBean.class, result.getPayload().getClass()); - TestBean payload = (TestBean) result.getPayload(); - assertEquals("testBean", payload.name); - assertEquals(42, payload.age); - } - - @Test - public void bindToPrototypeBean() throws Exception { - StaticApplicationContext context = new StaticApplicationContext(); - MutablePropertyValues properties = new MutablePropertyValues(); - properties.addPropertyValue("name", "prototype"); - context.registerPrototype("prototypeTarget", TestBean.class, properties); - DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class); - mapper.setTargetBeanName("prototypeTarget"); - mapper.setBeanFactory(context); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setParameter("age", "42"); - Message result = mapper.toMessage(request); - assertNotNull(result); - assertEquals(TestBean.class, result.getPayload().getClass()); - TestBean payload = (TestBean) result.getPayload(); - assertEquals("prototype", payload.name); - assertEquals(84, payload.age); - } - - - public static class TestBean { - - String name; - - int age; - - public void setName(String name) { - this.name = name; - } - - public void setAge(int age) { - this.age = age * 2; - } - } - -} diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java index 660f79df27..792f41d7ba 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java @@ -21,9 +21,12 @@ import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.io.PrintWriter; +import java.io.Serializable; import java.util.Arrays; +import java.util.List; import org.junit.Test; + import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; @@ -37,6 +40,7 @@ import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.SerializationUtils; /** * @author Mark Fisher @@ -113,7 +117,7 @@ public class HttpRequestHandlingMessagingGatewayTests { HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true); gateway.setRequestChannel(requestChannel); gateway.setConvertExceptions(true); - gateway.setMessageConverters(Arrays.>asList(new DumbHttpMessageConverter())); + gateway.setMessageConverters(Arrays.>asList(new TestHttpMessageConverter())); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Accept", "application/x-java-serialized-object"); request.setMethod("GET"); @@ -123,9 +127,61 @@ public class HttpRequestHandlingMessagingGatewayTests { assertEquals("Planned", content); } - private static class DumbHttpMessageConverter extends AbstractHttpMessageConverter { + @Test + public void multiValueParameterMap() throws Exception { + QueueChannel channel = new QueueChannel(); + HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false); + gateway.setRequestChannel(channel); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); + request.setParameter("foo", "123"); + request.addParameter("bar", "456"); + request.addParameter("bar", "789"); + MockHttpServletResponse response = new MockHttpServletResponse(); + gateway.handleRequest(request, response); + Message message = channel.receive(0); + assertNotNull(message); + assertNotNull(message.getPayload()); + assertEquals(LinkedMultiValueMap.class, message.getPayload().getClass()); + @SuppressWarnings("unchecked") + LinkedMultiValueMap map = (LinkedMultiValueMap) message.getPayload(); + List fooValues = map.get("foo"); + List barValues = map.get("bar"); + assertEquals(1, fooValues.size()); + assertEquals("123", fooValues.get(0)); + assertEquals(2, barValues.size()); + assertEquals("456", barValues.get(0)); + assertEquals("789", barValues.get(1)); + } + + @Test + public void serializableRequestBody() throws Exception { + QueueChannel channel = new QueueChannel(); + HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false); + gateway.setRequestPayloadType(TestBean.class); + gateway.setRequestChannel(channel); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test"); + request.setContentType("application/x-java-serialized-object"); + TestBean testBean = new TestBean(); + testBean.setName("T. Bean"); + testBean.setAge(42); + request.setContent(SerializationUtils.serialize(testBean)); + MockHttpServletResponse response = new MockHttpServletResponse(); + gateway.handleRequest(request, response); + byte[] bytes = response.getContentAsByteArray(); + assertNotNull(bytes); + Message message = channel.receive(0); + assertNotNull(message); + assertNotNull(message.getPayload()); + assertEquals(TestBean.class, message.getPayload().getClass()); + TestBean result = (TestBean) message.getPayload(); + assertEquals("T. Bean", result.name); + assertEquals(84, result.age); + } + + + private static class TestHttpMessageConverter extends AbstractHttpMessageConverter { - public DumbHttpMessageConverter() { + public TestHttpMessageConverter() { setSupportedMediaTypes(Arrays.asList(MediaType.ALL)); } @@ -141,11 +197,27 @@ public class HttpRequestHandlingMessagingGatewayTests { } @Override - protected void writeInternal(Exception t, HttpOutputMessage outputMessage) throws IOException, - HttpMessageNotWritableException { + protected void writeInternal(Exception t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { new PrintWriter(outputMessage.getBody()).append(t.getCause().getMessage()).flush(); } + } + + + @SuppressWarnings("serial") + public static class TestBean implements Serializable { + + String name; + + int age; + + public void setName(String name) { + this.name = name; + } + + public void setAge(int age) { + this.age = age * 2; + } } }