Skip to content

Commit 34cbcf5

Browse files
committed
Support better HttpMessageConverters manipulation
Add additional constructor and a protected postProcessConverters method to make it easier to manipulate the final converter list that will be used. Fixes gh-1482
1 parent 0c0a0a7 commit 34cbcf5

File tree

2 files changed

+71
-16
lines changed

2 files changed

+71
-16
lines changed

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

+44-16
Original file line numberDiff line numberDiff line change
@@ -69,26 +69,54 @@ public HttpMessageConverters(HttpMessageConverter<?>... additionalConverters) {
6969
* converters.
7070
* @param additionalConverters additional converters to be added. Items are added just
7171
* 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.
72+
* default converter is found) The {@link #postProcessConverters(List)} method can be
73+
* used for further converter manipulation.
7474
*/
7575
public HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters) {
76-
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
76+
this(true, additionalConverters);
77+
}
78+
79+
/**
80+
* Create a new {@link HttpMessageConverters} instance with the specified converters.
81+
* @param addDefaultConverters if default converters should be added
82+
* @param converters converters to be added. Items are added just before any default
83+
* converter of the same type (or at the front of the list if no default converter is
84+
* found) The {@link #postProcessConverters(List)} method can be used for further
85+
* converter manipulation.
86+
*/
87+
public HttpMessageConverters(boolean addDefaultConverters,
88+
Collection<HttpMessageConverter<?>> converters) {
89+
List<HttpMessageConverter<?>> combined = new ArrayList<HttpMessageConverter<?>>();
7790
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();
91+
converters);
92+
if (addDefaultConverters) {
93+
for (HttpMessageConverter<?> defaultConverter : getDefaultConverters()) {
94+
Iterator<HttpMessageConverter<?>> iterator = processing.iterator();
95+
while (iterator.hasNext()) {
96+
HttpMessageConverter<?> candidate = iterator.next();
97+
if (ClassUtils.isAssignableValue(defaultConverter.getClass(),
98+
candidate)) {
99+
combined.add(candidate);
100+
iterator.remove();
101+
}
86102
}
103+
combined.add(defaultConverter);
87104
}
88-
converters.add(defaultConverter);
89105
}
90-
converters.addAll(0, processing);
91-
this.converters = Collections.unmodifiableList(converters);
106+
combined.addAll(0, processing);
107+
combined = postProcessConverters(combined);
108+
this.converters = Collections.unmodifiableList(combined);
109+
}
110+
111+
/**
112+
* Method that can be used to post-process the {@link HttpMessageConverter} list
113+
* before it is used.
114+
* @param converters a mutable list of the converters that will be used.
115+
* @return the final converts list to use
116+
*/
117+
protected List<HttpMessageConverter<?>> postProcessConverters(
118+
List<HttpMessageConverter<?>> converters) {
119+
return converters;
92120
}
93121

94122
private List<HttpMessageConverter<?>> getDefaultConverters() {
@@ -127,8 +155,8 @@ public Iterator<HttpMessageConverter<?>> iterator() {
127155
}
128156

129157
/**
130-
* Return a mutable list of the converters in the order that they will be registered.
131-
* Values in the list cannot be modified once the bean has been initialized.
158+
* Return an immutable list of the converters in the order that they will be
159+
* registered.
132160
* @return the converters
133161
*/
134162
public List<HttpMessageConverter<?>> getConverters() {

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

+27
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.Arrays;
21+
import java.util.Iterator;
2122
import java.util.List;
2223

2324
import org.junit.Rule;
@@ -97,4 +98,30 @@ public void addNewConverters() {
9798
assertEquals(converter2, converters.getConverters().get(1));
9899
}
99100

101+
@Test
102+
public void postProcessConverters() throws Exception {
103+
HttpMessageConverters converters = new HttpMessageConverters() {
104+
@Override
105+
protected List<HttpMessageConverter<?>> postProcessConverters(
106+
List<HttpMessageConverter<?>> converters) {
107+
for (Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); iterator
108+
.hasNext();) {
109+
if (iterator.next() instanceof Jaxb2RootElementHttpMessageConverter) {
110+
iterator.remove();
111+
}
112+
}
113+
return converters;
114+
};
115+
};
116+
List<Class<?>> converterClasses = new ArrayList<Class<?>>();
117+
for (HttpMessageConverter<?> converter : converters) {
118+
converterClasses.add(converter.getClass());
119+
}
120+
assertThat(converterClasses, equalTo(Arrays.<Class<?>> asList(
121+
ByteArrayHttpMessageConverter.class, StringHttpMessageConverter.class,
122+
ResourceHttpMessageConverter.class, SourceHttpMessageConverter.class,
123+
AllEncompassingFormHttpMessageConverter.class,
124+
MappingJackson2HttpMessageConverter.class)));
125+
}
126+
100127
}

0 commit comments

Comments
 (0)