Skip to content

Commit af026c0

Browse files
committed
Review HttpMessageConverters semantics in Builder
Prior to this commit, the `HttpMessageConverters` builder API had methods like "jsonMessageConverter" for configuring a specific converter for JSON support. This converter would be always configured at a given position, even if default converters registration is not requested. On the other hand, `customMessageConverter` would add any converter ahead of the list, in all cases. This difference was not conveyed as it should by the API. This commit makes the following changes: * builder methods are renamed to `withJsonConverter` and variants, to better convey the fact that those are replacing the default converter for a given format. * `customMessageConverter` is renamed to `addCustomConverter` to better reflect the additive aspect. * the JavaDoc has been updated accordingly * `withJsonConverter` and others are now only effective if the default registration of auto-detected converters is requested. This better aligns with the behavior in the reactive codecs configuration Closes gh-35704
1 parent 03c5ea2 commit af026c0

File tree

10 files changed

+91
-87
lines changed

10 files changed

+91
-87
lines changed

framework-docs/src/main/java/org/springframework/docs/web/webmvc/mvcconfig/mvcconfigmessageconverters/WebConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ public void configureMessageConverters(HttpMessageConverters.ServerBuilder build
4444
.findAndAddModules()
4545
.defaultUseWrapper(false)
4646
.build();
47-
builder.jsonMessageConverter(new JacksonJsonHttpMessageConverter(jsonMapper))
48-
.xmlMessageConverter(new JacksonXmlHttpMessageConverter(xmlMapper));
47+
builder.withJsonConverter(new JacksonJsonHttpMessageConverter(jsonMapper))
48+
.withXmlConverter(new JacksonXmlHttpMessageConverter(xmlMapper));
4949
}
5050
}
5151
// end::snippet[]

framework-docs/src/main/kotlin/org/springframework/docs/web/webmvc/mvcconfig/mvcconfigmessageconverters/WebConfiguration.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class WebConfiguration : WebMvcConfigurer {
2626
.findAndAddModules()
2727
.defaultUseWrapper(false)
2828
.build()
29-
builder.jsonMessageConverter(JacksonJsonHttpMessageConverter(jsonMapper))
30-
.xmlMessageConverter(JacksonXmlHttpMessageConverter(xmlMapper))
29+
builder.withJsonConverter(JacksonJsonHttpMessageConverter(jsonMapper))
30+
.withXmlConverter(JacksonXmlHttpMessageConverter(xmlMapper))
3131
}
3232
}
3333
// end::snippet[]

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

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -338,43 +338,43 @@ public DefaultClientBuilder registerDefaults() {
338338
}
339339

340340
@Override
341-
public ClientBuilder stringMessageConverter(HttpMessageConverter<?> stringMessageConverter) {
341+
public ClientBuilder withStringConverter(HttpMessageConverter<?> stringMessageConverter) {
342342
setStringMessageConverter(stringMessageConverter);
343343
return this;
344344
}
345345

346346
@Override
347-
public ClientBuilder jsonMessageConverter(HttpMessageConverter<?> jsonMessageConverter) {
347+
public ClientBuilder withJsonConverter(HttpMessageConverter<?> jsonMessageConverter) {
348348
setJsonMessageConverter(jsonMessageConverter);
349349
return this;
350350
}
351351

352352
@Override
353-
public ClientBuilder xmlMessageConverter(HttpMessageConverter<?> xmlMessageConverter) {
353+
public ClientBuilder withXmlConverter(HttpMessageConverter<?> xmlMessageConverter) {
354354
setXmlMessageConverter(xmlMessageConverter);
355355
return this;
356356
}
357357

358358
@Override
359-
public ClientBuilder smileMessageConverter(HttpMessageConverter<?> smileMessageConverter) {
359+
public ClientBuilder withSmileConverter(HttpMessageConverter<?> smileMessageConverter) {
360360
setSmileMessageConverter(smileMessageConverter);
361361
return this;
362362
}
363363

364364
@Override
365-
public ClientBuilder cborMessageConverter(HttpMessageConverter<?> cborMessageConverter) {
365+
public ClientBuilder withCborConverter(HttpMessageConverter<?> cborMessageConverter) {
366366
setCborMessageConverter(cborMessageConverter);
367367
return this;
368368
}
369369

370370
@Override
371-
public ClientBuilder yamlMessageConverter(HttpMessageConverter<?> yamlMessageConverter) {
371+
public ClientBuilder withYamlConverter(HttpMessageConverter<?> yamlMessageConverter) {
372372
setYamlMessageConverter(yamlMessageConverter);
373373
return this;
374374
}
375375

376376
@Override
377-
public ClientBuilder customMessageConverter(HttpMessageConverter<?> customConverter) {
377+
public ClientBuilder addCustomConverter(HttpMessageConverter<?> customConverter) {
378378
addCustomMessageConverter(customConverter);
379379
return this;
380380
}
@@ -391,20 +391,21 @@ public HttpMessageConverters build() {
391391
this.resourceMessageConverter = new ResourceHttpMessageConverter(false);
392392
detectMessageConverters();
393393
}
394-
List<HttpMessageConverter<?>> allConverters = new ArrayList<>();
395-
List<HttpMessageConverter<?>> partConverters = new ArrayList<>();
396-
partConverters.addAll(this.getCustomConverters());
397-
partConverters.addAll(this.getCoreConverters());
398-
399-
allConverters.addAll(this.getCustomConverters());
400-
allConverters.addAll(this.getBaseConverters());
401-
if (this.resourceMessageConverter != null) {
402-
allConverters.add(this.resourceMessageConverter);
394+
List<HttpMessageConverter<?>> partConverters = new ArrayList<>(this.getCustomConverters());
395+
List<HttpMessageConverter<?>> allConverters = new ArrayList<>(this.getCustomConverters());
396+
if (this.registerDefaults) {
397+
partConverters.addAll(this.getCoreConverters());
398+
allConverters.addAll(this.getBaseConverters());
399+
if (this.resourceMessageConverter != null) {
400+
allConverters.add(this.resourceMessageConverter);
401+
}
403402
}
404403
if (!partConverters.isEmpty() || !allConverters.isEmpty()) {
405404
allConverters.add(new AllEncompassingFormHttpMessageConverter(partConverters));
406405
}
407-
allConverters.addAll(this.getCoreConverters());
406+
if (this.registerDefaults) {
407+
allConverters.addAll(this.getCoreConverters());
408+
}
408409
if (this.configurer != null) {
409410
allConverters.forEach(this.configurer);
410411
}
@@ -422,43 +423,43 @@ public ServerBuilder registerDefaults() {
422423
}
423424

424425
@Override
425-
public ServerBuilder stringMessageConverter(HttpMessageConverter<?> stringMessageConverter) {
426+
public ServerBuilder withStringConverter(HttpMessageConverter<?> stringMessageConverter) {
426427
setStringMessageConverter(stringMessageConverter);
427428
return this;
428429
}
429430

430431
@Override
431-
public ServerBuilder jsonMessageConverter(HttpMessageConverter<?> jsonMessageConverter) {
432+
public ServerBuilder withJsonConverter(HttpMessageConverter<?> jsonMessageConverter) {
432433
setJsonMessageConverter(jsonMessageConverter);
433434
return this;
434435
}
435436

436437
@Override
437-
public ServerBuilder xmlMessageConverter(HttpMessageConverter<?> xmlMessageConverter) {
438+
public ServerBuilder withXmlConverter(HttpMessageConverter<?> xmlMessageConverter) {
438439
setXmlMessageConverter(xmlMessageConverter);
439440
return this;
440441
}
441442

442443
@Override
443-
public ServerBuilder smileMessageConverter(HttpMessageConverter<?> smileMessageConverter) {
444+
public ServerBuilder withSmileConverter(HttpMessageConverter<?> smileMessageConverter) {
444445
setSmileMessageConverter(smileMessageConverter);
445446
return this;
446447
}
447448

448449
@Override
449-
public ServerBuilder cborMessageConverter(HttpMessageConverter<?> cborMessageConverter) {
450+
public ServerBuilder withCborConverter(HttpMessageConverter<?> cborMessageConverter) {
450451
setCborMessageConverter(cborMessageConverter);
451452
return this;
452453
}
453454

454455
@Override
455-
public ServerBuilder yamlMessageConverter(HttpMessageConverter<?> yamlMessageConverter) {
456+
public ServerBuilder withYamlConverter(HttpMessageConverter<?> yamlMessageConverter) {
456457
setYamlMessageConverter(yamlMessageConverter);
457458
return this;
458459
}
459460

460461
@Override
461-
public ServerBuilder customMessageConverter(HttpMessageConverter<?> customConverter) {
462+
public ServerBuilder addCustomConverter(HttpMessageConverter<?> customConverter) {
462463
addCustomMessageConverter(customConverter);
463464
return this;
464465
}
@@ -476,24 +477,24 @@ public HttpMessageConverters build() {
476477
this.resourceRegionMessageConverter = new ResourceRegionHttpMessageConverter();
477478
detectMessageConverters();
478479
}
479-
List<HttpMessageConverter<?>> allConverters = new ArrayList<>();
480-
List<HttpMessageConverter<?>> partConverters = new ArrayList<>();
481-
482-
partConverters.addAll(this.getCustomConverters());
483-
partConverters.addAll(this.getCoreConverters());
484-
485-
allConverters.addAll(this.getCustomConverters());
486-
allConverters.addAll(this.getBaseConverters());
487-
if (this.resourceMessageConverter != null) {
488-
allConverters.add(this.resourceMessageConverter);
489-
}
490-
if (this.resourceRegionMessageConverter != null) {
491-
allConverters.add(this.resourceRegionMessageConverter);
480+
List<HttpMessageConverter<?>> partConverters = new ArrayList<>(this.getCustomConverters());
481+
List<HttpMessageConverter<?>> allConverters = new ArrayList<>(this.getCustomConverters());
482+
if (this.registerDefaults) {
483+
partConverters.addAll(this.getCoreConverters());
484+
allConverters.addAll(this.getBaseConverters());
485+
if (this.resourceMessageConverter != null) {
486+
allConverters.add(this.resourceMessageConverter);
487+
}
488+
if (this.resourceRegionMessageConverter != null) {
489+
allConverters.add(this.resourceRegionMessageConverter);
490+
}
492491
}
493492
if (!partConverters.isEmpty() || !allConverters.isEmpty()) {
494493
allConverters.add(new AllEncompassingFormHttpMessageConverter(partConverters));
495494
}
496-
allConverters.addAll(this.getCoreConverters());
495+
if (this.registerDefaults) {
496+
allConverters.addAll(this.getCoreConverters());
497+
}
497498
if (this.configurer != null) {
498499
allConverters.forEach(this.configurer);
499500
}

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
/**
2222
* Utility for building and configuring an immutable collection of {@link HttpMessageConverter}
2323
* instances for {@link #forClient() client} or {@link #forServer() server} usage. You can
24-
* ask to {@link Builder#registerDefaults() register default converters with classpath detection},
25-
* add custom converters and post-process configured converters.
24+
* ask to {@link Builder#registerDefaults() register default converters with classpath detection}
25+
* and {@link Builder#withJsonConverter(HttpMessageConverter) override specific converters} that were detected.
26+
* Custom converters can be independently added in front of default ones.
27+
* Finally, {@link Builder#configureMessageConverters(Consumer) default and custom converters can be configured}.
2628
*
2729
* @author Brian Clozel
2830
* @since 7.0
@@ -79,7 +81,7 @@ interface Builder<T extends Builder<T>> {
7981

8082
/**
8183
* Register default converters using classpath detection.
82-
* Manual registrations like {@link #jsonMessageConverter(HttpMessageConverter)} will
84+
* Manual registrations like {@link #withJsonConverter(HttpMessageConverter)} will
8385
* override auto-detected ones.
8486
*/
8587
T registerDefaults();
@@ -90,53 +92,53 @@ interface Builder<T extends Builder<T>> {
9092
* @param stringMessageConverter the converter instance to use
9193
* @see StringHttpMessageConverter
9294
*/
93-
T stringMessageConverter(HttpMessageConverter<?> stringMessageConverter);
95+
T withStringConverter(HttpMessageConverter<?> stringMessageConverter);
9496

9597
/**
9698
* Override the default Jackson 3.x JSON {@code HttpMessageConverter}
9799
* with any converter supporting the JSON format.
98100
* @param jsonMessageConverter the converter instance to use
99101
* @see org.springframework.http.converter.json.JacksonJsonHttpMessageConverter
100102
*/
101-
T jsonMessageConverter(HttpMessageConverter<?> jsonMessageConverter);
103+
T withJsonConverter(HttpMessageConverter<?> jsonMessageConverter);
102104

103105
/**
104106
* Override the default Jackson 3.x XML {@code HttpMessageConverter}
105107
* with any converter supporting the XML format.
106108
* @param xmlMessageConverter the converter instance to use
107109
* @see org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter
108110
*/
109-
T xmlMessageConverter(HttpMessageConverter<?> xmlMessageConverter);
111+
T withXmlConverter(HttpMessageConverter<?> xmlMessageConverter);
110112

111113
/**
112114
* Override the default Jackson 3.x Smile {@code HttpMessageConverter}
113115
* with any converter supporting the Smile format.
114116
* @param smileMessageConverter the converter instance to use
115117
* @see org.springframework.http.converter.smile.JacksonSmileHttpMessageConverter
116118
*/
117-
T smileMessageConverter(HttpMessageConverter<?> smileMessageConverter);
119+
T withSmileConverter(HttpMessageConverter<?> smileMessageConverter);
118120

119121
/**
120122
* Override the default Jackson 3.x CBOR {@code HttpMessageConverter}
121123
* with any converter supporting the CBOR format.
122124
* @param cborMessageConverter the converter instance to use
123125
* @see org.springframework.http.converter.cbor.JacksonCborHttpMessageConverter
124126
*/
125-
T cborMessageConverter(HttpMessageConverter<?> cborMessageConverter);
127+
T withCborConverter(HttpMessageConverter<?> cborMessageConverter);
126128

127129
/**
128130
* Override the default Jackson 3.x Yaml {@code HttpMessageConverter}
129131
* with any converter supporting the Yaml format.
130132
* @param yamlMessageConverter the converter instance to use
131133
* @see org.springframework.http.converter.yaml.JacksonYamlHttpMessageConverter
132134
*/
133-
T yamlMessageConverter(HttpMessageConverter<?> yamlMessageConverter);
135+
T withYamlConverter(HttpMessageConverter<?> yamlMessageConverter);
134136

135137
/**
136-
* Add a custom {@code HttpMessageConverter} to the list of converters.
138+
* Add a custom {@code HttpMessageConverter} to the list of converters, ahead of the default converters.
137139
* @param customConverter the converter instance to add
138140
*/
139-
T customMessageConverter(HttpMessageConverter<?> customConverter);
141+
T addCustomConverter(HttpMessageConverter<?> customConverter);
140142

141143
/**
142144
* Add a consumer for configuring the selected message converters.

spring-web/src/main/java/org/springframework/web/client/DefaultRestClientBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ private List<HttpMessageConverter<?>> initMessageConverters() {
498498
}
499499
else {
500500
if (this.messageConverters != null) {
501-
this.messageConverters.forEach(builder::customMessageConverter);
501+
this.messageConverters.forEach(builder::addCustomConverter);
502502
}
503503
if (this.convertersConfigurer != null) {
504504
this.convertersConfigurer.accept(builder);

0 commit comments

Comments
 (0)