Support generic target types in the RestTemplate
This change makes it possible to use the RestTemplate to read an HTTP response into a target generic type object. The RestTemplate has three new exchange(...) methods that accept ParameterizedTypeReference -- a new class that enables capturing and passing generic type info. See the Javadoc of the three new methods in RestOperations for a short example. To support this feature, the HttpMessageConverter is now extended by GenericHttpMessageConverter, which adds a method for reading an HttpInputMessage to a specific generic type. The new interface is implemented by the MappingJacksonHttpMessageConverter and also by a new Jaxb2CollectionHttpMessageConverter that can read read a generic Collection where the generic type is a JAXB type annotated with @XmlRootElement or @XmlType. Issue: SPR-7023
This commit is contained in:
committed by
Rossen Stoyanchev
parent
789e12a0c7
commit
ed3823b045
@@ -16,23 +16,22 @@
|
||||
|
||||
package org.springframework.http.converter.json;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MockHttpInputMessage;
|
||||
import org.springframework.http.MockHttpOutputMessage;
|
||||
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Jackson 2.x converter tests.
|
||||
*
|
||||
@@ -52,12 +51,12 @@ public class MappingJackson2HttpMessageConverterTests extends AbstractMappingJac
|
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter() {
|
||||
|
||||
@Override
|
||||
protected JavaType getJavaType(Class<?> clazz) {
|
||||
if (List.class.isAssignableFrom(clazz)) {
|
||||
protected JavaType getJavaType(Type type) {
|
||||
if (type instanceof Class && List.class.isAssignableFrom((Class)type)) {
|
||||
return new ObjectMapper().getTypeFactory().constructCollectionType(ArrayList.class, MyBean.class);
|
||||
}
|
||||
else {
|
||||
return super.getJavaType(clazz);
|
||||
return super.getJavaType(type);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -77,6 +76,29 @@ public class MappingJackson2HttpMessageConverterTests extends AbstractMappingJac
|
||||
assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readParameterizedType() throws IOException {
|
||||
ParameterizedTypeReference<List<MyBean>> beansList = new ParameterizedTypeReference<List<MyBean>>() {};
|
||||
|
||||
String body =
|
||||
"[{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
|
||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
|
||||
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
|
||||
|
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||
List<MyBean> results = (List<MyBean>) converter.read(beansList.getType(), inputMessage);
|
||||
assertEquals(1, results.size());
|
||||
MyBean result = results.get(0);
|
||||
assertEquals("Foo", result.getString());
|
||||
assertEquals(42, result.getNumber());
|
||||
assertEquals(42F, result.getFraction(), 0F);
|
||||
assertArrayEquals(new String[]{"Foo", "Bar"}, result.getArray());
|
||||
assertTrue(result.isBool());
|
||||
assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void prettyPrint() throws Exception {
|
||||
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
package org.springframework.http.converter.json;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.codehaus.jackson.map.type.TypeFactory;
|
||||
import org.codehaus.jackson.type.JavaType;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.MockHttpInputMessage;
|
||||
import org.springframework.http.MockHttpOutputMessage;
|
||||
@@ -49,12 +49,12 @@ public class MappingJacksonHttpMessageConverterTests extends AbstractMappingJack
|
||||
public void readGenerics() throws IOException {
|
||||
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter() {
|
||||
@Override
|
||||
protected JavaType getJavaType(Class<?> clazz) {
|
||||
if (List.class.isAssignableFrom(clazz)) {
|
||||
protected JavaType getJavaType(Type type) {
|
||||
if (type instanceof Class && List.class.isAssignableFrom((Class)type)) {
|
||||
return TypeFactory.collectionType(ArrayList.class, MyBean.class);
|
||||
}
|
||||
else {
|
||||
return super.getJavaType(clazz);
|
||||
return super.getJavaType(type);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -74,6 +74,28 @@ public class MappingJacksonHttpMessageConverterTests extends AbstractMappingJack
|
||||
assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readParameterizedType() throws IOException {
|
||||
ParameterizedTypeReference<List<MyBean>> beansList = new ParameterizedTypeReference<List<MyBean>>() {};
|
||||
|
||||
String body =
|
||||
"[{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
|
||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
|
||||
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
|
||||
|
||||
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
|
||||
List<MyBean> results = (List<MyBean>) converter.read(beansList.getType(), inputMessage);
|
||||
assertEquals(1, results.size());
|
||||
MyBean result = results.get(0);
|
||||
assertEquals("Foo", result.getString());
|
||||
assertEquals(42, result.getNumber());
|
||||
assertEquals(42F, result.getFraction(), 0F);
|
||||
assertArrayEquals(new String[]{"Foo", "Bar"}, result.getArray());
|
||||
assertTrue(result.isBool());
|
||||
assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prettyPrint() throws Exception {
|
||||
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.http.converter.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.MockHttpInputMessage;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link Jaxb2CollectionHttpMessageConverter}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class Jaxb2CollectionHttpMessageConverterTests {
|
||||
|
||||
private Jaxb2CollectionHttpMessageConverter<?> converter;
|
||||
|
||||
private Type rootElementListType;
|
||||
|
||||
private Type rootElementSetType;
|
||||
|
||||
private Type typeListType;
|
||||
|
||||
private Type typeSetType;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
converter = new Jaxb2CollectionHttpMessageConverter<Collection<Object>>();
|
||||
rootElementListType = new ParameterizedTypeReference<List<RootElement>>() {}.getType();
|
||||
rootElementSetType = new ParameterizedTypeReference<Set<RootElement>>() {}.getType();
|
||||
typeListType = new ParameterizedTypeReference<List<TestType>>() {}.getType();
|
||||
typeSetType = new ParameterizedTypeReference<Set<TestType>>() {}.getType();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canRead() throws Exception {
|
||||
assertTrue(converter.canRead(rootElementListType, null));
|
||||
assertTrue(converter.canRead(rootElementSetType, null));
|
||||
assertTrue(converter.canRead(typeSetType, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readXmlRootElementList() throws Exception {
|
||||
String content = "<list><rootElement><type s=\"1\"/></rootElement><rootElement><type s=\"2\"/></rootElement></list>";
|
||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
|
||||
|
||||
List<RootElement> result = (List<RootElement>) converter.read(rootElementListType, inputMessage);
|
||||
|
||||
assertEquals("Invalid result", 2, result.size());
|
||||
assertEquals("Invalid result", "1", result.get(0).type.s);
|
||||
assertEquals("Invalid result", "2", result.get(1).type.s);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readXmlRootElementSet() throws Exception {
|
||||
String content = "<set><rootElement><type s=\"1\"/></rootElement><rootElement><type s=\"2\"/></rootElement></set>";
|
||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
|
||||
|
||||
Set<RootElement> result = (Set<RootElement>) converter.read(rootElementSetType, inputMessage);
|
||||
|
||||
assertEquals("Invalid result", 2, result.size());
|
||||
assertTrue("Invalid result", result.contains(new RootElement("1")));
|
||||
assertTrue("Invalid result", result.contains(new RootElement("2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readXmlTypeList() throws Exception {
|
||||
String content = "<list><foo s=\"1\"/><bar s=\"2\"/></list>";
|
||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
|
||||
|
||||
List<TestType> result = (List<TestType>) converter.read(typeListType, inputMessage);
|
||||
|
||||
assertEquals("Invalid result", 2, result.size());
|
||||
assertEquals("Invalid result", "1", result.get(0).s);
|
||||
assertEquals("Invalid result", "2", result.get(1).s);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readXmlTypeSet() throws Exception {
|
||||
String content = "<set><foo s=\"1\"/><bar s=\"2\"/></set>";
|
||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
|
||||
|
||||
Set<TestType> result = (Set<TestType>) converter.read(typeSetType, inputMessage);
|
||||
|
||||
assertEquals("Invalid result", 2, result.size());
|
||||
assertTrue("Invalid result", result.contains(new TestType("1")));
|
||||
assertTrue("Invalid result", result.contains(new TestType("2")));
|
||||
}
|
||||
|
||||
|
||||
@XmlRootElement
|
||||
public static class RootElement {
|
||||
|
||||
public RootElement() {
|
||||
}
|
||||
|
||||
public RootElement(String s) {
|
||||
this.type = new TestType(s);
|
||||
}
|
||||
|
||||
@XmlElement
|
||||
public TestType type = new TestType();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof RootElement) {
|
||||
RootElement other = (RootElement) o;
|
||||
return this.type.equals(other.type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return type.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@XmlType
|
||||
public static class TestType {
|
||||
|
||||
public TestType() {
|
||||
}
|
||||
|
||||
public TestType(String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
@XmlAttribute
|
||||
public String s = "Hello World";
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o instanceof TestType) {
|
||||
TestType other = (TestType) o;
|
||||
return this.s.equals(other.s);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return s.hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.web.client;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.converter.GenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link HttpMessageConverter}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class HttpMessageConverterExtractorTests {
|
||||
|
||||
private HttpMessageConverterExtractor extractor;
|
||||
|
||||
private ClientHttpResponse response;
|
||||
|
||||
@Before
|
||||
public void createMocks() {
|
||||
response = createMock(ClientHttpResponse.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noContent() throws IOException {
|
||||
HttpMessageConverter<?> converter = createMock(HttpMessageConverter.class);
|
||||
|
||||
extractor = new HttpMessageConverterExtractor<String>(String.class, createConverterList(converter));
|
||||
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.NO_CONTENT);
|
||||
|
||||
replay(response, converter);
|
||||
Object result = extractor.extractData(response);
|
||||
|
||||
assertNull(result);
|
||||
verify(response, converter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notModified() throws IOException {
|
||||
HttpMessageConverter<?> converter = createMock(HttpMessageConverter.class);
|
||||
|
||||
extractor = new HttpMessageConverterExtractor<String>(String.class, createConverterList(converter));
|
||||
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.NOT_MODIFIED);
|
||||
|
||||
replay(response, converter);
|
||||
Object result = extractor.extractData(response);
|
||||
|
||||
assertNull(result);
|
||||
verify(response, converter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zeroContentLength() throws IOException {
|
||||
HttpMessageConverter<?> converter = createMock(HttpMessageConverter.class);
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentLength(0);
|
||||
|
||||
extractor = new HttpMessageConverterExtractor<String>(String.class, createConverterList(converter));
|
||||
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
expect(response.getHeaders()).andReturn(responseHeaders);
|
||||
|
||||
replay(response, converter);
|
||||
Object result = extractor.extractData(response);
|
||||
|
||||
assertNull(result);
|
||||
verify(response, converter);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void normal() throws IOException {
|
||||
HttpMessageConverter<String> converter = createMock(HttpMessageConverter.class);
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(converter);
|
||||
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
MediaType contentType = MediaType.TEXT_PLAIN;
|
||||
responseHeaders.setContentType(contentType);
|
||||
String expected = "Foo";
|
||||
|
||||
extractor = new HttpMessageConverterExtractor<String>(String.class, converters);
|
||||
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
expect(response.getHeaders()).andReturn(responseHeaders).times(2);
|
||||
expect(converter.canRead(String.class, contentType)).andReturn(true);
|
||||
expect(converter.read(String.class, response)).andReturn(expected);
|
||||
|
||||
replay(response, converter);
|
||||
Object result = extractor.extractData(response);
|
||||
|
||||
assertEquals(expected, result);
|
||||
verify(response, converter);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void cannotRead() throws IOException {
|
||||
HttpMessageConverter<String> converter = createMock(HttpMessageConverter.class);
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
|
||||
converters.add(converter);
|
||||
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
MediaType contentType = MediaType.TEXT_PLAIN;
|
||||
responseHeaders.setContentType(contentType);
|
||||
|
||||
extractor = new HttpMessageConverterExtractor<String>(String.class, converters);
|
||||
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
expect(response.getHeaders()).andReturn(responseHeaders).times(2);
|
||||
expect(converter.canRead(String.class, contentType)).andReturn(false);
|
||||
|
||||
replay(response, converter);
|
||||
try {
|
||||
extractor.extractData(response);
|
||||
fail("RestClientException expected");
|
||||
}
|
||||
catch (RestClientException expected) {
|
||||
// expected
|
||||
}
|
||||
|
||||
verify(response, converter);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void generics() throws IOException {
|
||||
GenericHttpMessageConverter<String> converter = createMock(GenericHttpMessageConverter.class);
|
||||
List<HttpMessageConverter<?>> converters = createConverterList(converter);
|
||||
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
MediaType contentType = MediaType.TEXT_PLAIN;
|
||||
responseHeaders.setContentType(contentType);
|
||||
String expected = "Foo";
|
||||
|
||||
ParameterizedTypeReference<List<String>> reference = new ParameterizedTypeReference<List<String>>() {};
|
||||
Type type = reference.getType();
|
||||
|
||||
extractor = new HttpMessageConverterExtractor<List<String>>(type, converters);
|
||||
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
expect(response.getHeaders()).andReturn(responseHeaders).times(2);
|
||||
expect(converter.canRead(type, contentType)).andReturn(true);
|
||||
expect(converter.read(type, response)).andReturn(expected);
|
||||
|
||||
replay(response, converter);
|
||||
Object result = extractor.extractData(response);
|
||||
|
||||
assertEquals(expected, result);
|
||||
verify(response, converter);
|
||||
}
|
||||
|
||||
private List<HttpMessageConverter<?>> createConverterList(HttpMessageConverter converter) {
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>(1);
|
||||
converters.add(converter);
|
||||
return converters;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
@@ -21,12 +21,16 @@ import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -36,11 +40,9 @@ 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.GenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/** @author Arjen Poutsma */
|
||||
@SuppressWarnings("unchecked")
|
||||
public class RestTemplateTests {
|
||||
@@ -600,9 +602,8 @@ public class RestTemplateTests {
|
||||
|
||||
@Test
|
||||
public void exchange() throws Exception {
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
expect(converter.canRead(Integer.class, null)).andReturn(true);
|
||||
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(textPlain));
|
||||
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(this.request);
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
expect(this.request.getHeaders()).andReturn(requestHeaders).times(2);
|
||||
@@ -612,12 +613,12 @@ public class RestTemplateTests {
|
||||
expect(this.request.execute()).andReturn(response);
|
||||
expect(errorHandler.hasError(response)).andReturn(false);
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentType(textPlain);
|
||||
responseHeaders.setContentType(MediaType.TEXT_PLAIN);
|
||||
responseHeaders.setContentLength(10);
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
expect(response.getHeaders()).andReturn(responseHeaders).times(3);
|
||||
Integer expected = 42;
|
||||
expect(converter.canRead(Integer.class, textPlain)).andReturn(true);
|
||||
expect(converter.canRead(Integer.class, MediaType.TEXT_PLAIN)).andReturn(true);
|
||||
expect(converter.read(Integer.class, response)).andReturn(expected);
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
response.close();
|
||||
@@ -629,14 +630,56 @@ public class RestTemplateTests {
|
||||
HttpEntity<String> requestEntity = new HttpEntity<String>(body, entityHeaders);
|
||||
ResponseEntity<Integer> result = template.exchange("http://example.com", HttpMethod.POST, requestEntity, Integer.class);
|
||||
assertEquals("Invalid POST result", expected, result.getBody());
|
||||
assertEquals("Invalid Content-Type", textPlain, result.getHeaders().getContentType());
|
||||
assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept"));
|
||||
assertEquals("Invalid Content-Type", MediaType.TEXT_PLAIN, result.getHeaders().getContentType());
|
||||
assertEquals("Invalid Accept header", MediaType.TEXT_PLAIN_VALUE, requestHeaders.getFirst("Accept"));
|
||||
assertEquals("Invalid custom header", "MyValue", requestHeaders.getFirst("MyHeader"));
|
||||
assertEquals("Invalid status code", HttpStatus.OK, result.getStatusCode());
|
||||
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exchangeParameterizedType() throws Exception {
|
||||
GenericHttpMessageConverter converter = createMock(GenericHttpMessageConverter.class);
|
||||
template.setMessageConverters(Collections.<HttpMessageConverter<?>>singletonList(converter));
|
||||
|
||||
ParameterizedTypeReference<List<Integer>> intList = new ParameterizedTypeReference<List<Integer>>() {};
|
||||
expect(converter.canRead(intList.getType(), null)).andReturn(true);
|
||||
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(this.request);
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
expect(this.request.getHeaders()).andReturn(requestHeaders).times(2);
|
||||
expect(converter.canWrite(String.class, null)).andReturn(true);
|
||||
String requestBody = "Hello World";
|
||||
converter.write(requestBody, null, this.request);
|
||||
expect(this.request.execute()).andReturn(response);
|
||||
expect(errorHandler.hasError(response)).andReturn(false);
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentType(MediaType.TEXT_PLAIN);
|
||||
responseHeaders.setContentLength(10);
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
expect(response.getHeaders()).andReturn(responseHeaders).times(3);
|
||||
List<Integer> expected = Collections.singletonList(42);
|
||||
expect(converter.canRead(intList.getType(), MediaType.TEXT_PLAIN)).andReturn(true);
|
||||
expect(converter.read(intList.getType(), response)).andReturn(expected);
|
||||
expect(response.getStatusCode()).andReturn(HttpStatus.OK);
|
||||
response.close();
|
||||
|
||||
replay(requestFactory, request, response, errorHandler, converter);
|
||||
|
||||
HttpHeaders entityHeaders = new HttpHeaders();
|
||||
entityHeaders.set("MyHeader", "MyValue");
|
||||
HttpEntity<String> requestEntity = new HttpEntity<String>(requestBody, entityHeaders);
|
||||
ResponseEntity<List<Integer>> result = template.exchange("http://example.com", HttpMethod.POST, requestEntity, intList);
|
||||
assertEquals("Invalid POST result", expected, result.getBody());
|
||||
assertEquals("Invalid Content-Type", MediaType.TEXT_PLAIN, result.getHeaders().getContentType());
|
||||
assertEquals("Invalid Accept header", MediaType.TEXT_PLAIN_VALUE, requestHeaders.getFirst("Accept"));
|
||||
assertEquals("Invalid custom header", "MyValue", requestHeaders.getFirst("MyHeader"));
|
||||
assertEquals("Invalid status code", HttpStatus.OK, result.getStatusCode());
|
||||
|
||||
verify(requestFactory, request, response, errorHandler, converter);
|
||||
}
|
||||
|
||||
|
||||
private void replayMocks() {
|
||||
replay(requestFactory, request, response, errorHandler, converter);
|
||||
|
||||
Reference in New Issue
Block a user