diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/converter/SerializingHttpMessageConverter.java b/spring-integration-http/src/main/java/org/springframework/integration/http/converter/SerializingHttpMessageConverter.java index f613b8e5c6..f497cd9b84 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/converter/SerializingHttpMessageConverter.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/converter/SerializingHttpMessageConverter.java @@ -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. @@ -31,8 +31,9 @@ import org.springframework.util.FileCopyUtils; /** * An {@link HttpMessageConverter} implementation for {@link Serializable} instances. - * + * * @author Mark Fisher + * @author Gary Russell * @since 2.0 */ public class SerializingHttpMessageConverter extends AbstractHttpMessageConverter { @@ -51,11 +52,6 @@ public class SerializingHttpMessageConverter extends AbstractHttpMessageConverte return Serializable.class.isAssignableFrom(clazz); } - @Override - public boolean canRead(Class clazz, MediaType mediaType) { - return (Serializable.class.isAssignableFrom(clazz) && APPLICATION_JAVA_SERIALIZED_OBJECT.includes(mediaType)); - } - @Override public boolean canWrite(Class clazz, MediaType mediaType) { return (Serializable.class.isAssignableFrom(clazz) && APPLICATION_JAVA_SERIALIZED_OBJECT.includes(mediaType)); 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 7e9d2325e3..9223f3b641 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 @@ -54,7 +54,6 @@ import org.springframework.integration.context.OrderlyShutdownCapable; import org.springframework.integration.expression.ExpressionUtils; import org.springframework.integration.gateway.MessagingGatewaySupport; import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter; -import org.springframework.integration.http.converter.SerializingHttpMessageConverter; import org.springframework.integration.http.multipart.MultipartHttpInputMessage; import org.springframework.integration.http.support.DefaultHttpHeaderMapper; import org.springframework.integration.mapping.HeaderMapper; @@ -147,7 +146,6 @@ public abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewa public HttpRequestHandlingEndpointSupport(boolean expectReply) { this.expectReply = expectReply; this.messageConverters.add(new MultipartAwareFormHttpMessageConverter()); - this.messageConverters.add(new SerializingHttpMessageConverter()); this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(new StringHttpMessageConverter()); this.messageConverters.add(new ResourceHttpMessageConverter()); diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java index 15a17846f1..d76929d3e6 100755 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java @@ -51,7 +51,6 @@ import org.springframework.integration.MessageHandlingException; import org.springframework.integration.MessagingException; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; -import org.springframework.integration.http.converter.SerializingHttpMessageConverter; import org.springframework.integration.http.support.DefaultHttpHeaderMapper; import org.springframework.integration.mapping.HeaderMapper; import org.springframework.integration.support.MessageBuilder; @@ -152,7 +151,6 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe public HttpRequestExecutingMessageHandler(Expression uriExpression, RestTemplate restTemplate) { Assert.notNull(uriExpression, "URI Expression is required"); this.restTemplate = (restTemplate == null ? new RestTemplate() : restTemplate); - this.restTemplate.getMessageConverters().add(0, new SerializingHttpMessageConverter()); this.uriExpression = uriExpression; StandardEvaluationContext sec = new StandardEvaluationContext(); sec.addPropertyAccessor(new MapAccessor()); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java index 785ac66445..c01ecbbe90 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; @@ -40,16 +41,19 @@ import org.springframework.expression.Expression; import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.converter.HttpMessageConverter; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.core.PollableChannel; import org.springframework.integration.history.MessageHistory; +import org.springframework.integration.http.converter.SerializingHttpMessageConverter; import org.springframework.integration.http.inbound.HttpRequestHandlingController; import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway; import org.springframework.integration.http.support.DefaultHttpHeaderMapper; import org.springframework.integration.test.util.TestUtils; import org.springframework.mock.web.MockHttpServletRequest; 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.MultiValueMap; @@ -60,6 +64,7 @@ import org.springframework.util.MultiValueMap; * @author Gary Russell * @author Gunnar Hillert * @author Artem Bilan + * @author Gary Russell */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @@ -239,7 +244,7 @@ public class HttpInboundChannelAdapterParserTests { assertEquals("test", message.getPayload()); } - @Test + @Test @DirtiesContext public void postRequestWithSerializedObjectContentOk() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("POST"); @@ -253,6 +258,11 @@ public class HttpInboundChannelAdapterParserTests { request.addHeader("Content-Type", "application/x-java-serialized-object"); MockHttpServletResponse response = new MockHttpServletResponse(); + + List> converters = new ArrayList>(); + converters.add(new SerializingHttpMessageConverter()); + postOnlyAdapter.setMessageConverters(converters); + postOnlyAdapter.handleRequest(request, response); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); Message message = requests.receive(0); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java index 0e9159642b..0d47aca5b7 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import static org.springframework.integration.test.util.TestUtils.getPropertyValue; import static org.springframework.integration.test.util.TestUtils.handlerExpecting; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -40,17 +41,20 @@ 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.http.converter.HttpMessageConverter; import org.springframework.integration.Message; import org.springframework.integration.MessageHeaders; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.core.PollableChannel; import org.springframework.integration.core.SubscribableChannel; +import org.springframework.integration.http.converter.SerializingHttpMessageConverter; import org.springframework.integration.http.inbound.HttpRequestHandlingController; import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway; import org.springframework.integration.http.support.DefaultHttpHeaderMapper; import org.springframework.integration.test.util.TestUtils; import org.springframework.mock.web.MockHttpServletRequest; 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; @@ -103,7 +107,7 @@ public class HttpInboundGatewayParserTests { assertEquals(Long.valueOf(4567), TestUtils.getPropertyValue(messagingTemplate, "receiveTimeout")); } - @Test(timeout=1000) + @Test(timeout=1000) @DirtiesContext public void checkFlow() throws Exception { requests.subscribe(handlerExpecting(any(Message.class))); MockHttpServletRequest request = new MockHttpServletRequest(); @@ -112,6 +116,10 @@ public class HttpInboundGatewayParserTests { request.setParameter("foo", "bar"); MockHttpServletResponse response = new MockHttpServletResponse(); + List> converters = new ArrayList>(); + converters.add(new SerializingHttpMessageConverter()); + gateway.setMessageConverters(converters); + gateway.handleRequest(request, response); assertThat(response.getStatus(), is(HttpServletResponse.SC_OK)); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml index 74c1768ed9..4dcd714616 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests-context.xml @@ -3,9 +3,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration" xmlns:int-http="http://www.springframework.org/schema/integration/http" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + 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/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.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"> + + + + + + + diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java index 3b6f72330b..080e54d1ea 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/OutboundResponseTypeTests.java @@ -26,11 +26,9 @@ import java.net.InetSocketAddress; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; - import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.http.MediaType; @@ -39,6 +37,7 @@ import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.message.GenericMessage; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.sun.net.httpserver.HttpExchange; @@ -48,6 +47,7 @@ import com.sun.net.httpserver.HttpServer; /** * @author Oleg Zhurakousky * @author Artem Bilan + * @author Gary Russell * @since 2.2 * *

@@ -76,6 +76,9 @@ public class OutboundResponseTypeTests { @Autowired private MessageChannel resTypeExpressionSetChannel; + @Autowired + private MessageChannel resTypeExpressionSetSerializationChannel; + @BeforeClass public static void createServer() throws Exception { httpHandler = new MyHandler(); @@ -115,7 +118,7 @@ public class OutboundResponseTypeTests { @Test public void testWithResponseTypeExpressionSetAsClass() throws Exception { - this.resTypeExpressionSetChannel.send(new GenericMessage>(String.class)); + this.resTypeExpressionSetSerializationChannel.send(new GenericMessage>(String.class)); Message message = this.replyChannel.receive(5000); assertNotNull(message); assertTrue(message.getPayload() instanceof String); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java index 6fa61090e5..9d87c1fe39 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java @@ -39,6 +39,7 @@ 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.http.converter.SerializingHttpMessageConverter; import org.springframework.integration.support.MessageBuilder; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -198,6 +199,11 @@ public class HttpRequestHandlingMessagingGatewayTests { HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false); gateway.setRequestPayloadType(TestBean.class); gateway.setRequestChannel(channel); + + List> converters = new ArrayList>(); + converters.add(new SerializingHttpMessageConverter()); + gateway.setMessageConverters(converters); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test"); //request.setContentType("application/x-java-serialized-object"); //Works in Spring 3.1.2.RELEASE but NOT in 3.0.7.RELEASE diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java index 0dfacb0a10..94b2e13ce8 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java @@ -21,9 +21,13 @@ import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.IOException; +import java.io.Serializable; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -47,14 +51,21 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.ConverterRegistry; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.converter.HttpMessageConverter; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.core.PollableChannel; +import org.springframework.integration.http.converter.SerializingHttpMessageConverter; +import org.springframework.integration.message.GenericMessage; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.test.util.TestUtils; import org.springframework.util.MultiValueMap; @@ -735,6 +746,96 @@ public class HttpRequestExecutingMessageHandlerTests { assertSame(mockConversionService, TestUtils.getPropertyValue(handler, "conversionService")); } + @Test + public void acceptHeaderForSerializableResponse() throws Exception { + HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("http://www.springsource.org/spring-integration"); + handler.setHttpMethod(HttpMethod.GET); + handler.setExpectedResponseType(Foo.class); + + List> converters = new ArrayList>(); + converters.add(new SerializingHttpMessageConverter()); + handler.setMessageConverters(converters); + handler.afterPropertiesSet(); + + RestTemplate restTemplate = TestUtils.getPropertyValue(handler, "restTemplate", RestTemplate.class); + + HttpHeaders requestHeaders = setUpMocksToCaptureSentHeaders(restTemplate); + + Message message = MessageBuilder.withPayload("foo").build(); + Exception exception = null; + try { + handler.handleMessage(message); + } + catch (Exception e) { + exception = e; + } + assertTrue(requestHeaders.getAccept() != null); + assertTrue(requestHeaders.getAccept().size() > 0); + assertEquals("404 null", exception.getCause().getMessage()); + List accept = requestHeaders.getAccept(); + assertTrue(accept != null && accept.size() > 0); + assertEquals("application", accept.get(0).getType()); + assertEquals("x-java-serialized-object", accept.get(0).getSubtype()); + } + + @Test + public void acceptHeaderForSerializableResponseMessageExchange() throws Exception { + HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("http://www.springsource.org/spring-integration"); + + handler.setHttpMethod(HttpMethod.GET); + handler.setExtractPayload(false); + handler.setExpectedResponseType(GenericMessage.class); + + List> converters = new ArrayList>(); + converters.add(new SerializingHttpMessageConverter()); + handler.setMessageConverters(converters); + handler.afterPropertiesSet(); + + RestTemplate restTemplate = TestUtils.getPropertyValue(handler, "restTemplate", RestTemplate.class); + + HttpHeaders requestHeaders = setUpMocksToCaptureSentHeaders(restTemplate); + + Message message = MessageBuilder.withPayload("foo").build(); + Exception exception = null; + try { + handler.handleMessage(message); + } + catch (Exception e) { + exception = e; + } + assertTrue(requestHeaders.getAccept() != null); + assertTrue(requestHeaders.getAccept().size() > 0); + assertEquals("404 null", exception.getCause().getMessage()); + List accept = requestHeaders.getAccept(); + assertTrue(accept != null && accept.size() > 0); + assertEquals("application", accept.get(0).getType()); + assertEquals("x-java-serialized-object", accept.get(0).getSubtype()); + } + + private HttpHeaders setUpMocksToCaptureSentHeaders(RestTemplate restTemplate) throws IOException { + + HttpHeaders headers = new HttpHeaders(); + + ClientHttpRequestFactory requestFactory = mock(ClientHttpRequestFactory.class); + ClientHttpRequest clientRequest = mock(ClientHttpRequest.class); + when(clientRequest.getHeaders()).thenReturn(headers); + + when(requestFactory.createRequest(any(URI.class), any(HttpMethod.class))) + .thenReturn(clientRequest ); + + ClientHttpResponse response = mock(ClientHttpResponse.class); + when(response.getStatusCode()).thenReturn(HttpStatus.NOT_FOUND); + + HttpHeaders responseHeaders = new HttpHeaders(); + when(response.getHeaders()).thenReturn(responseHeaders); + + when(clientRequest.execute()).thenReturn(response); + + restTemplate.setRequestFactory(requestFactory); + + return headers; + } + public static class City{ private final String name; public City(String name){ @@ -770,4 +871,9 @@ public class HttpRequestExecutingMessageHandlerTests { } } + private static class Foo implements Serializable { + + private static final long serialVersionUID = 1L; + + } } diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml index c44398422d..38a2f41a00 100644 --- a/src/reference/docbook/whats-new.xml +++ b/src/reference/docbook/whats-new.xml @@ -190,6 +190,28 @@ by default. For more information see . +

+ Http Support + + Java serialization over http is no longer enabled by default. Previously, when + setting a expected-response-type to a Serializable + object, the Accept header was not properly set up. The + SerializingHttpMessageConverter has now been updated + to set the Accept header to application/x-java-serialized-object. + However, because this could cause incompatibility with existing applications, + it was decided to no longer automatically add this converter to the http endpoints. + + + If you wish to use Java serialization, you will need to add the + SerializingHttpMessageConverter to the appropriate + endpoints, using the message-converters attribute, when using + XML configuration, or using the setMessageConverters() method. + + + Alternatively, you may wish to consider using JSON instead which is enabled + by simply having Jackson on the classpath. + +