Skip to content

Commit 27ec919

Browse files
committed
Closes gh-36043
Adds ability to add message converter at specific index to builders, and propagates through to java.util.List.add(idx, ...) Signed-off-by: Hayden Rear hayden.rear@gmail.com
1 parent 7be318d commit 27ec919

File tree

3 files changed

+81
-37
lines changed

3 files changed

+81
-37
lines changed

spring-web/src/main/java/org/springframework/http/converter/DefaultHttpMessageConverters.java

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ abstract static class DefaultBuilder {
122122

123123
@Nullable Consumer<HttpMessageConverter<?>> configurer;
124124

125+
@Nullable Consumer<List<HttpMessageConverter<?>>> convertersListConfigurer;
126+
125127
@Nullable HttpMessageConverter<?> kotlinJsonConverter;
126128

127129
@Nullable HttpMessageConverter<?> jsonConverter;
@@ -217,11 +219,6 @@ private void checkConverterSupports(HttpMessageConverter<?> converter, MediaType
217219
throw new IllegalArgumentException("converter should support '" + mediaType + "'");
218220
}
219221

220-
void addCustomMessageConverter(int index, HttpMessageConverter<?> customConverter) {
221-
Assert.notNull(customConverter, "'customConverter' must not be null");
222-
this.customConverters.add(index, customConverter);
223-
}
224-
225222
void addCustomMessageConverter(HttpMessageConverter<?> customConverter) {
226223
Assert.notNull(customConverter, "'customConverter' must not be null");
227224
this.customConverters.add(customConverter);
@@ -231,6 +228,10 @@ void addMessageConverterConfigurer(Consumer<HttpMessageConverter<?>> configurer)
231228
this.configurer = (this.configurer != null) ? configurer.andThen(this.configurer) : configurer;
232229
}
233230

231+
void addMessageConvertersListConfigurer(Consumer<List<HttpMessageConverter<?>>> configurer) {
232+
this.convertersListConfigurer = (this.convertersListConfigurer != null) ? convertersListConfigurer.andThen(this.convertersListConfigurer) : configurer;
233+
}
234+
234235
List<HttpMessageConverter<?>> getBaseConverters() {
235236
List<HttpMessageConverter<?>> converters = new ArrayList<>();
236237
if (this.byteArrayConverter != null) {
@@ -437,19 +438,19 @@ public ClientBuilder withYamlConverter(HttpMessageConverter<?> yamlConverter) {
437438

438439
@Override
439440
public ClientBuilder addCustomConverter(HttpMessageConverter<?> customConverter) {
440-
addCustomConverter(customConverter);
441+
addCustomMessageConverter(customConverter);
441442
return this;
442443
}
443444

444445
@Override
445-
public ClientBuilder addCustomConverter(int index, HttpMessageConverter<?> customConverter) {
446-
addCustomMessageConverter(index, customConverter);
446+
public ClientBuilder configureMessageConverters(Consumer<HttpMessageConverter<?>> configurer) {
447+
addMessageConverterConfigurer(configurer);
447448
return this;
448449
}
449450

450451
@Override
451-
public ClientBuilder configureMessageConverters(Consumer<HttpMessageConverter<?>> configurer) {
452-
addMessageConverterConfigurer(configurer);
452+
public ClientBuilder configureMessageConvertersList(Consumer<List<HttpMessageConverter<?>>> configurer) {
453+
addMessageConvertersListConfigurer(configurer);
453454
return this;
454455
}
455456

@@ -477,6 +478,10 @@ public HttpMessageConverters build() {
477478
if (this.configurer != null) {
478479
allConverters.forEach(this.configurer);
479480
}
481+
if (this.convertersListConfigurer != null) {
482+
this.convertersListConfigurer.accept(allConverters);
483+
}
484+
480485
return new DefaultHttpMessageConverters(allConverters);
481486
}
482487
}
@@ -545,14 +550,14 @@ public ServerBuilder addCustomConverter(HttpMessageConverter<?> customConverter)
545550
}
546551

547552
@Override
548-
public ServerBuilder addCustomConverter(int index, HttpMessageConverter<?> customConverter) {
549-
addCustomMessageConverter(index, customConverter);
553+
public ServerBuilder configureMessageConverters(Consumer<HttpMessageConverter<?>> configurer) {
554+
addMessageConverterConfigurer(configurer);
550555
return this;
551556
}
552557

553558
@Override
554-
public ServerBuilder configureMessageConverters(Consumer<HttpMessageConverter<?>> configurer) {
555-
addMessageConverterConfigurer(configurer);
559+
public ServerBuilder configureMessageConvertersList(Consumer<List<HttpMessageConverter<?>>> configurer) {
560+
addMessageConvertersListConfigurer(configurer);
556561
return this;
557562
}
558563

@@ -584,6 +589,10 @@ public HttpMessageConverters build() {
584589
if (this.configurer != null) {
585590
allConverters.forEach(this.configurer);
586591
}
592+
if (this.convertersListConfigurer != null) {
593+
this.convertersListConfigurer.accept(allConverters);
594+
}
595+
587596
return new DefaultHttpMessageConverters(allConverters);
588597
}
589598
}

spring-web/src/main/java/org/springframework/http/converter/HttpMessageConverters.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.http.converter;
1818

19+
import java.util.List;
1920
import java.util.function.Consumer;
2021

2122
/**
@@ -166,19 +167,17 @@ interface Builder<T extends Builder<T>> {
166167
*/
167168
T addCustomConverter(HttpMessageConverter<?> customConverter);
168169

169-
170170
/**
171-
* Add a custom {@code HttpMessageConverter} to the list of converters, at the specified index, pushing all existing message converters forward one.
172-
* @param customConverter the converter instance to add
173-
* @param index index at which the specified element is to be inserted
171+
* Add a consumer for configuring the selected message converters.
172+
* @param configurer the configurer to use
174173
*/
175-
T addCustomConverter(int index, HttpMessageConverter<?> customConverter);
174+
T configureMessageConverters(Consumer<HttpMessageConverter<?>> configurer);
176175

177176
/**
178-
* Add a consumer for configuring the selected message converters.
177+
* Add a consumer for configuring the message converters list just before it's returned.
179178
* @param configurer the configurer to use
180179
*/
181-
T configureMessageConverters(Consumer<HttpMessageConverter<?>> configurer);
180+
T configureMessageConvertersList(Consumer<List<HttpMessageConverter<?>>> configurer);
182181

183182
/**
184183
* Build and return the {@link HttpMessageConverters} instance configured by this builder.

spring-web/src/test/java/org/springframework/http/converter/DefaultHttpMessageConvertersTests.java

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package org.springframework.http.converter;
1818

1919
import java.io.IOException;
20+
import java.util.Comparator;
2021
import java.util.stream.Stream;
2122
import java.util.stream.StreamSupport;
2223

24+
import org.assertj.core.util.Lists;
2325
import org.junit.jupiter.api.Nested;
2426
import org.junit.jupiter.api.Test;
2527
import org.junit.jupiter.params.ParameterizedTest;
@@ -147,22 +149,6 @@ void registerCustomMessageConverter() {
147149
assertThat(converters).hasExactlyElementsOfTypes(CustomHttpMessageConverter.class, AllEncompassingFormHttpMessageConverter.class);
148150
}
149151

150-
@Test
151-
void registerCustomMessageConverterAtIndex() {
152-
var clientBuilder = HttpMessageConverters.forClient()
153-
.addCustomConverter(0, new CustomHttpMessageConverter());
154-
var converters = clientBuilder.build();
155-
156-
assertThat(converters).hasExactlyElementsOfTypes(CustomHttpMessageConverter.class, AllEncompassingFormHttpMessageConverter.class);
157-
158-
clientBuilder.addCustomConverter(0, new CustomHttpMessageConverter());
159-
converters = clientBuilder.build();
160-
161-
assertThat(converters).hasExactlyElementsOfTypes(
162-
CustomHttpMessageConverter.class, CustomHttpMessageConverter.class,
163-
AllEncompassingFormHttpMessageConverter.class);
164-
}
165-
166152
@Test
167153
void registerCustomMessageConverterAheadOfDefaults() {
168154
var converters = HttpMessageConverters.forClient().registerDefaults()
@@ -227,6 +213,31 @@ void shouldConfigureConverter() {
227213
assertThat(customConverter.processed).isTrue();
228214
}
229215

216+
@Test
217+
void shouldConfigureConverterOrder() {
218+
var customConverter = new CustomHttpMessageConverter();
219+
var converted = HttpMessageConverters.forClient()
220+
.addCustomConverter(customConverter)
221+
.configureMessageConvertersList(converter -> {
222+
converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? 1 : -1));
223+
}).build();
224+
225+
var messageConvertersBack = Lists.newArrayList(converted);
226+
assertThat(messageConvertersBack.size()).isGreaterThan(1);
227+
assertThat(messageConvertersBack.get(messageConvertersBack.size() - 1).getClass()).isEqualTo(CustomHttpMessageConverter.class);
228+
229+
var convertedFront = HttpMessageConverters.forClient()
230+
.addCustomConverter(customConverter)
231+
.configureMessageConvertersList(converter -> {
232+
converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? -1 : 1));
233+
}).build();
234+
235+
var messageConvertersFront = Lists.newArrayList(convertedFront);
236+
assertThat(messageConvertersFront.get(0).getClass()).isEqualTo(CustomHttpMessageConverter.class);
237+
assertThat(messageConvertersFront.size()).isGreaterThan(1);
238+
239+
}
240+
230241
}
231242

232243

@@ -335,6 +346,31 @@ void shouldConfigureConverter() {
335346

336347
assertThat(customConverter.processed).isTrue();
337348
}
349+
350+
@Test
351+
void shouldConfigureConverterOrder() {
352+
var customConverter = new CustomHttpMessageConverter();
353+
var converted = HttpMessageConverters.forServer()
354+
.addCustomConverter(customConverter)
355+
.configureMessageConvertersList(converter -> {
356+
converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? 1 : -1));
357+
}).build();
358+
359+
var messageConvertersBack = Lists.newArrayList(converted);
360+
assertThat(messageConvertersBack.size()).isGreaterThan(1);
361+
assertThat(messageConvertersBack.get(messageConvertersBack.size() - 1).getClass()).isEqualTo(CustomHttpMessageConverter.class);
362+
363+
var convertedFront = HttpMessageConverters.forServer()
364+
.addCustomConverter(customConverter)
365+
.configureMessageConvertersList(converter -> {
366+
converter.sort(Comparator.comparing(s -> s.getClass().equals(CustomHttpMessageConverter.class) ? -1 : 1));
367+
}).build();
368+
369+
var messageConvertersFront = Lists.newArrayList(convertedFront);
370+
assertThat(messageConvertersFront).isNotEmpty();
371+
assertThat(messageConvertersFront.size()).isGreaterThan(1);
372+
373+
}
338374
}
339375

340376
@SuppressWarnings("unchecked")

0 commit comments

Comments
 (0)