Skip to content

Commit 5e1552b

Browse files
author
Phillip Webb
committed
Retain default order in HttpMessageConverters
The original fix for gh-1293 (commit 05e6af2) 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
1 parent 05e6af2 commit 5e1552b

File tree

2 files changed

+42
-22
lines changed

2 files changed

+42
-22
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpMessageConverters.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,27 @@ public HttpMessageConverters(HttpMessageConverter<?>... additionalConverters) {
6767
/**
6868
* Create a new {@link HttpMessageConverters} instance with the specified additional
6969
* converters.
70-
* @param additionalConverters additional converters to be added. New converters will
71-
* be added to the front of the list, overrides will replace existing items without
72-
* changing the order. The {@link #getConverters()} methods can be used for further
73-
* converter manipulation.
70+
* @param additionalConverters additional converters to be added. Items are added just
71+
* before any default converter of the same type (or at the front of the list if no
72+
* default converter is found) The {@link #getConverters()} methods can be used for
73+
* further converter manipulation.
7474
*/
7575
public HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters) {
7676
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
77-
List<HttpMessageConverter<?>> defaultConverters = getDefaultConverters();
78-
converters.addAll(additionalConverters);
79-
converters.addAll(defaultConverters);
77+
List<HttpMessageConverter<?>> processing = new ArrayList<HttpMessageConverter<?>>(
78+
additionalConverters);
79+
for (HttpMessageConverter<?> defaultConverter : getDefaultConverters()) {
80+
Iterator<HttpMessageConverter<?>> iterator = processing.iterator();
81+
while (iterator.hasNext()) {
82+
HttpMessageConverter<?> candidate = iterator.next();
83+
if (ClassUtils.isAssignableValue(defaultConverter.getClass(), candidate)) {
84+
converters.add(candidate);
85+
iterator.remove();
86+
}
87+
}
88+
converters.add(defaultConverter);
89+
}
90+
converters.addAll(0, processing);
8091
this.converters = Collections.unmodifiableList(converters);
8192
}
8293

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersTests.java

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import static org.hamcrest.Matchers.equalTo;
3636
import static org.junit.Assert.assertEquals;
37+
import static org.junit.Assert.assertNotEquals;
3738
import static org.junit.Assert.assertThat;
3839
import static org.junit.Assert.assertTrue;
3940
import static org.mockito.Mockito.mock;
@@ -65,27 +66,35 @@ public void containsDefaults() throws Exception {
6566
}
6667

6768
@Test
68-
public void overrideExistingConverter() {
69-
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
70-
HttpMessageConverters converters = new HttpMessageConverters(converter);
71-
assertTrue(converters.getConverters().contains(converter));
72-
int count = 0;
73-
for (HttpMessageConverter<?> httpMessageConverter : converters) {
74-
if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) {
75-
count++;
69+
public void addBeforeExistingConverter() {
70+
MappingJackson2HttpMessageConverter converter1 = new MappingJackson2HttpMessageConverter();
71+
MappingJackson2HttpMessageConverter converter2 = new MappingJackson2HttpMessageConverter();
72+
HttpMessageConverters converters = new HttpMessageConverters(converter1,
73+
converter2);
74+
assertTrue(converters.getConverters().contains(converter1));
75+
assertTrue(converters.getConverters().contains(converter2));
76+
List<MappingJackson2HttpMessageConverter> httpConverters = new ArrayList<MappingJackson2HttpMessageConverter>();
77+
for (HttpMessageConverter<?> candidate : converters) {
78+
if (candidate instanceof MappingJackson2HttpMessageConverter) {
79+
httpConverters.add((MappingJackson2HttpMessageConverter) candidate);
7680
}
7781
}
7882
// The existing converter is still there, but with a lower priority
79-
assertEquals(2, count);
80-
assertEquals(0, converters.getConverters().indexOf(converter));
83+
assertEquals(3, httpConverters.size());
84+
assertEquals(0, httpConverters.indexOf(converter1));
85+
assertEquals(1, httpConverters.indexOf(converter2));
86+
assertNotEquals(0, converters.getConverters().indexOf(converter1));
8187
}
8288

8389
@Test
84-
public void addNewConverter() {
85-
HttpMessageConverter<?> converter = mock(HttpMessageConverter.class);
86-
HttpMessageConverters converters = new HttpMessageConverters(converter);
87-
assertTrue(converters.getConverters().contains(converter));
88-
assertEquals(converter, converters.getConverters().get(0));
90+
public void addNewConverters() {
91+
HttpMessageConverter<?> converter1 = mock(HttpMessageConverter.class);
92+
HttpMessageConverter<?> converter2 = mock(HttpMessageConverter.class);
93+
HttpMessageConverters converters = new HttpMessageConverters(converter1,
94+
converter2);
95+
assertTrue(converters.getConverters().contains(converter1));
96+
assertEquals(converter1, converters.getConverters().get(0));
97+
assertEquals(converter2, converters.getConverters().get(1));
8998
}
9099

91100
}

0 commit comments

Comments
 (0)