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:
Arjen Poutsma
2012-06-08 14:47:22 +02:00
committed by Rossen Stoyanchev
parent 789e12a0c7
commit ed3823b045
14 changed files with 1213 additions and 99 deletions

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);