Commit 5e1552b7 authored by Phillip Webb's avatar Phillip Webb

Retain default order in HttpMessageConverters

The original fix for gh-1293 (commit 05e6af23) caused test failures due
to the fact that Spring Boot's MappingJackson2HttpMessageConverter was
added before Spring's default StringHttpMessageConverter.

This commit changes the HttpMessageConverters logic so that additional
converts are added just before any default converter of the same type.
This allows additional converters to be added whilst still retaining
the sensible ordering of the default converters.

Fixes gh-1293
parent 05e6af23
...@@ -67,16 +67,27 @@ public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>> ...@@ -67,16 +67,27 @@ public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>>
/** /**
* Create a new {@link HttpMessageConverters} instance with the specified additional * Create a new {@link HttpMessageConverters} instance with the specified additional
* converters. * converters.
* @param additionalConverters additional converters to be added. New converters will * @param additionalConverters additional converters to be added. Items are added just
* be added to the front of the list, overrides will replace existing items without * before any default converter of the same type (or at the front of the list if no
* changing the order. The {@link #getConverters()} methods can be used for further * default converter is found) The {@link #getConverters()} methods can be used for
* converter manipulation. * further converter manipulation.
*/ */
public HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters) { public HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters) {
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>(); List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
List<HttpMessageConverter<?>> defaultConverters = getDefaultConverters(); List<HttpMessageConverter<?>> processing = new ArrayList<HttpMessageConverter<?>>(
converters.addAll(additionalConverters); additionalConverters);
converters.addAll(defaultConverters); for (HttpMessageConverter<?> defaultConverter : getDefaultConverters()) {
Iterator<HttpMessageConverter<?>> iterator = processing.iterator();
while (iterator.hasNext()) {
HttpMessageConverter<?> candidate = iterator.next();
if (ClassUtils.isAssignableValue(defaultConverter.getClass(), candidate)) {
converters.add(candidate);
iterator.remove();
}
}
converters.add(defaultConverter);
}
converters.addAll(0, processing);
this.converters = Collections.unmodifiableList(converters); this.converters = Collections.unmodifiableList(converters);
} }
......
...@@ -34,6 +34,7 @@ import org.springframework.http.converter.xml.SourceHttpMessageConverter; ...@@ -34,6 +34,7 @@ import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
...@@ -65,27 +66,35 @@ public class HttpMessageConvertersTests { ...@@ -65,27 +66,35 @@ public class HttpMessageConvertersTests {
} }
@Test @Test
public void overrideExistingConverter() { public void addBeforeExistingConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); MappingJackson2HttpMessageConverter converter1 = new MappingJackson2HttpMessageConverter();
HttpMessageConverters converters = new HttpMessageConverters(converter); MappingJackson2HttpMessageConverter converter2 = new MappingJackson2HttpMessageConverter();
assertTrue(converters.getConverters().contains(converter)); HttpMessageConverters converters = new HttpMessageConverters(converter1,
int count = 0; converter2);
for (HttpMessageConverter<?> httpMessageConverter : converters) { assertTrue(converters.getConverters().contains(converter1));
if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) { assertTrue(converters.getConverters().contains(converter2));
count++; List<MappingJackson2HttpMessageConverter> httpConverters = new ArrayList<MappingJackson2HttpMessageConverter>();
for (HttpMessageConverter<?> candidate : converters) {
if (candidate instanceof MappingJackson2HttpMessageConverter) {
httpConverters.add((MappingJackson2HttpMessageConverter) candidate);
} }
} }
// The existing converter is still there, but with a lower priority // The existing converter is still there, but with a lower priority
assertEquals(2, count); assertEquals(3, httpConverters.size());
assertEquals(0, converters.getConverters().indexOf(converter)); assertEquals(0, httpConverters.indexOf(converter1));
assertEquals(1, httpConverters.indexOf(converter2));
assertNotEquals(0, converters.getConverters().indexOf(converter1));
} }
@Test @Test
public void addNewConverter() { public void addNewConverters() {
HttpMessageConverter<?> converter = mock(HttpMessageConverter.class); HttpMessageConverter<?> converter1 = mock(HttpMessageConverter.class);
HttpMessageConverters converters = new HttpMessageConverters(converter); HttpMessageConverter<?> converter2 = mock(HttpMessageConverter.class);
assertTrue(converters.getConverters().contains(converter)); HttpMessageConverters converters = new HttpMessageConverters(converter1,
assertEquals(converter, converters.getConverters().get(0)); converter2);
assertTrue(converters.getConverters().contains(converter1));
assertEquals(converter1, converters.getConverters().get(0));
assertEquals(converter2, converters.getConverters().get(1));
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment