Skip to content

Commit dc279d8

Browse files
committed
Use refactored CodecConfigurer
This commit changes the `HandlerStrategies` and `ExchangeStrategies` builders to use the `CodecConfigurer` for configuring Decoder|Encoder and HttpMessage[Reader|Writer]. Other classes that use `CodecConfigurer` have also been changed to reflect the refactoring to interfaces. This commit also removes the ExchangeStrategies methods that take an application context, as it was too naive approach to simply look up every message reader and writer in the context. Issue: SPR-15415, SPR-15435
1 parent 908d169 commit dc279d8

File tree

9 files changed

+64
-314
lines changed

9 files changed

+64
-314
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@
7070
*/
7171
public class WebFluxConfigurationSupport implements ApplicationContextAware {
7272

73+
static final boolean jackson2Present =
74+
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
75+
WebFluxConfigurationSupport.class.getClassLoader()) &&
76+
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
77+
WebFluxConfigurationSupport.class.getClassLoader());
78+
79+
7380
private Map<String, CorsConfiguration> corsConfigurations;
7481

7582
private PathMatchConfigurer pathMatchConfigurer;
@@ -148,7 +155,7 @@ public CompositeContentTypeResolver webFluxContentTypeResolver() {
148155
*/
149156
protected Map<String, MediaType> getDefaultMediaTypeMappings() {
150157
Map<String, MediaType> map = new HashMap<>();
151-
if (ServerCodecConfigurer.jackson2Present) {
158+
if (jackson2Present) {
152159
map.put("json", MediaType.APPLICATION_JSON);
153160
}
154161
return map;
@@ -266,7 +273,7 @@ protected void configureArgumentResolvers(ArgumentResolverConfigurer configurer)
266273
*/
267274
protected final ServerCodecConfigurer getMessageCodecsConfigurer() {
268275
if (this.messageCodecsConfigurer == null) {
269-
this.messageCodecsConfigurer = new ServerCodecConfigurer();
276+
this.messageCodecsConfigurer = ServerCodecConfigurer.create();
270277
configureHttpMessageCodecs(this.getMessageCodecsConfigurer());
271278
}
272279
return this.messageCodecsConfigurer;

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java

+16-34
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,11 @@
1919
import java.util.ArrayList;
2020
import java.util.Collections;
2121
import java.util.List;
22+
import java.util.function.Consumer;
2223
import java.util.function.Supplier;
2324
import java.util.stream.Stream;
2425

25-
import org.springframework.context.ApplicationContext;
26-
import org.springframework.core.codec.Decoder;
27-
import org.springframework.core.codec.Encoder;
2826
import org.springframework.http.codec.ClientCodecConfigurer;
29-
import org.springframework.http.codec.DecoderHttpMessageReader;
30-
import org.springframework.http.codec.EncoderHttpMessageWriter;
3127
import org.springframework.http.codec.HttpMessageReader;
3228
import org.springframework.http.codec.HttpMessageWriter;
3329
import org.springframework.util.Assert;
@@ -40,51 +36,37 @@
4036
*/
4137
class DefaultExchangeStrategiesBuilder implements ExchangeStrategies.Builder {
4238

43-
private final List<HttpMessageReader<?>> messageReaders = new ArrayList<>();
39+
private final ClientCodecConfigurer codecConfigurer = ClientCodecConfigurer.create();
4440

45-
private final List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
4641

47-
48-
public void defaultConfiguration() {
49-
ClientCodecConfigurer configurer = new ClientCodecConfigurer();
50-
configurer.getReaders().forEach(this::messageReader);
51-
configurer.getWriters().forEach(this::messageWriter);
42+
public DefaultExchangeStrategiesBuilder() {
43+
this.codecConfigurer.registerDefaults(false);
5244
}
5345

54-
public void applicationContext(ApplicationContext applicationContext) {
55-
applicationContext.getBeansOfType(HttpMessageReader.class).values().forEach(this::messageReader);
56-
applicationContext.getBeansOfType(HttpMessageWriter.class).values().forEach(this::messageWriter);
46+
public void defaultConfiguration() {
47+
this.codecConfigurer.registerDefaults(true);
5748
}
5849

5950
@Override
60-
public ExchangeStrategies.Builder messageReader(HttpMessageReader<?> messageReader) {
61-
Assert.notNull(messageReader, "'messageReader' must not be null");
62-
this.messageReaders.add(messageReader);
51+
public ExchangeStrategies.Builder defaultCodecs(
52+
Consumer<ClientCodecConfigurer.ClientDefaultCodecsConfigurer> consumer) {
53+
Assert.notNull(consumer, "'consumer' must not be null");
54+
consumer.accept(this.codecConfigurer.defaultCodecs());
6355
return this;
6456
}
6557

6658
@Override
67-
public ExchangeStrategies.Builder decoder(Decoder<?> decoder) {
68-
Assert.notNull(decoder, "'decoder' must not be null");
69-
return messageReader(new DecoderHttpMessageReader<>(decoder));
70-
}
71-
72-
@Override
73-
public ExchangeStrategies.Builder messageWriter(HttpMessageWriter<?> messageWriter) {
74-
Assert.notNull(messageWriter, "'messageWriter' must not be null");
75-
this.messageWriters.add(messageWriter);
59+
public ExchangeStrategies.Builder customCodecs(
60+
Consumer<ClientCodecConfigurer.CustomCodecsConfigurer> consumer) {
61+
Assert.notNull(consumer, "'consumer' must not be null");
62+
consumer.accept(this.codecConfigurer.customCodecs());
7663
return this;
7764
}
7865

79-
@Override
80-
public ExchangeStrategies.Builder encoder(Encoder<?> encoder) {
81-
Assert.notNull(encoder, "'encoder' must not be null");
82-
return messageWriter(new EncoderHttpMessageWriter<>(encoder));
83-
}
84-
8566
@Override
8667
public ExchangeStrategies build() {
87-
return new DefaultExchangeStrategies(this.messageReaders, this.messageWriters);
68+
return new DefaultExchangeStrategies(this.codecConfigurer.getReaders(),
69+
this.codecConfigurer.getWriters());
8870
}
8971

9072

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java

+10-83
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@
1616

1717
package org.springframework.web.reactive.function.client;
1818

19+
import java.util.function.Consumer;
1920
import java.util.function.Supplier;
2021
import java.util.stream.Stream;
2122

22-
import org.springframework.context.ApplicationContext;
23-
import org.springframework.core.codec.Decoder;
24-
import org.springframework.core.codec.Encoder;
23+
import org.springframework.http.codec.ClientCodecConfigurer;
2524
import org.springframework.http.codec.HttpMessageReader;
2625
import org.springframework.http.codec.HttpMessageWriter;
27-
import org.springframework.util.Assert;
2826

2927
/**
3028
* Defines the strategies for invoking {@link ExchangeFunction}s. An instance of
@@ -66,48 +64,6 @@ static ExchangeStrategies withDefaults() {
6664
return builder().build();
6765
}
6866

69-
/**
70-
* Return a new {@code ExchangeStrategies} based on the given
71-
* {@linkplain ApplicationContext application context}.
72-
* The returned supplier will search for all {@link HttpMessageReader}, and
73-
* {@link HttpMessageWriter} instances in the given application context and return
74-
* them for {@link #messageReaders()}, and {@link #messageWriters()} respectively.
75-
* @param applicationContext the application context to base the strategies on
76-
* @return the new {@code ExchangeStrategies}
77-
*/
78-
static ExchangeStrategies of(ApplicationContext applicationContext) {
79-
return builder(applicationContext).build();
80-
}
81-
82-
/**
83-
* Return a new {@code ExchangeStrategies} described by the given supplier functions.
84-
* All provided supplier function parameters can be {@code null} to indicate an empty
85-
* stream is to be returned.
86-
* @param messageReaders the supplier function for {@link HttpMessageReader} instances
87-
* (can be {@code null})
88-
* @param messageWriters the supplier function for {@link HttpMessageWriter} instances
89-
* (can be {@code null})
90-
* @return the new {@code ExchangeStrategies}
91-
*/
92-
static ExchangeStrategies of(Supplier<Stream<HttpMessageReader<?>>> messageReaders,
93-
Supplier<Stream<HttpMessageWriter<?>>> messageWriters) {
94-
95-
return new ExchangeStrategies() {
96-
@Override
97-
public Supplier<Stream<HttpMessageReader<?>>> messageReaders() {
98-
return checkForNull(messageReaders);
99-
}
100-
@Override
101-
public Supplier<Stream<HttpMessageWriter<?>>> messageWriters() {
102-
return checkForNull(messageWriters);
103-
}
104-
private <T> Supplier<Stream<T>> checkForNull(Supplier<Stream<T>> supplier) {
105-
return supplier != null ? supplier : Stream::empty;
106-
}
107-
};
108-
}
109-
110-
11167
// Builder methods
11268

11369
/**
@@ -120,21 +76,6 @@ static Builder builder() {
12076
return builder;
12177
}
12278

123-
/**
124-
* Return a mutable builder based on the given {@linkplain ApplicationContext application context}.
125-
* The returned builder will search for all {@link HttpMessageReader}, and
126-
* {@link HttpMessageWriter} instances in the given application context and return them for
127-
* {@link #messageReaders()}, and {@link #messageWriters()}.
128-
* @param applicationContext the application context to base the strategies on
129-
* @return the builder
130-
*/
131-
static Builder builder(ApplicationContext applicationContext) {
132-
Assert.notNull(applicationContext, "ApplicationContext must not be null");
133-
DefaultExchangeStrategiesBuilder builder = new DefaultExchangeStrategiesBuilder();
134-
builder.applicationContext(applicationContext);
135-
return builder;
136-
}
137-
13879
/**
13980
* Return a mutable, empty builder for a {@code ExchangeStrategies}.
14081
* @return the builder
@@ -150,34 +91,20 @@ static Builder empty() {
15091
interface Builder {
15192

15293
/**
153-
* Add the given message reader to this builder.
154-
* @param messageReader the message reader to add
155-
* @return this builder
156-
*/
157-
Builder messageReader(HttpMessageReader<?> messageReader);
158-
159-
/**
160-
* Add the given decoder to this builder. This is a convenient alternative to adding a
161-
* {@link org.springframework.http.codec.DecoderHttpMessageReader} that wraps the given decoder.
162-
* @param decoder the decoder to add
163-
* @return this builder
164-
*/
165-
Builder decoder(Decoder<?> decoder);
166-
167-
/**
168-
* Add the given message writer to this builder.
169-
* @param messageWriter the message writer to add
94+
* Customize the list of default client-side HTTP message readers and writers.
95+
* @param consumer the consumer to customize the default codecs
17096
* @return this builder
97+
* @see #customCodecs(Consumer)
17198
*/
172-
Builder messageWriter(HttpMessageWriter<?> messageWriter);
99+
Builder defaultCodecs(Consumer<ClientCodecConfigurer.ClientDefaultCodecsConfigurer> consumer);
173100

174101
/**
175-
* Add the given encoder to this builder. This is a convenient alternative to adding a
176-
* {@link org.springframework.http.codec.EncoderHttpMessageWriter} that wraps the given encoder.
177-
* @param encoder the encoder to add
102+
* Customize the list of custom client-side HTTP message readers and writers.
103+
* @param consumer the consumer to customize the custom codecs
178104
* @return this builder
105+
* @see #defaultCodecs(Consumer)
179106
*/
180-
Builder encoder(Encoder<?> encoder);
107+
Builder customCodecs(Consumer<ClientCodecConfigurer.CustomCodecsConfigurer> consumer);
181108

182109
/**
183110
* Builds the {@link ExchangeStrategies}.

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java

+12-46
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@
2121
import java.util.List;
2222
import java.util.Locale;
2323
import java.util.Optional;
24+
import java.util.function.Consumer;
2425
import java.util.function.Function;
2526
import java.util.function.Supplier;
2627
import java.util.stream.Stream;
2728

28-
import org.springframework.core.codec.Decoder;
29-
import org.springframework.core.codec.Encoder;
29+
import org.springframework.http.codec.CodecConfigurer;
3030
import org.springframework.http.codec.HttpMessageReader;
3131
import org.springframework.http.codec.HttpMessageWriter;
3232
import org.springframework.http.codec.ServerCodecConfigurer;
33-
import org.springframework.http.codec.json.Jackson2JsonDecoder;
34-
import org.springframework.http.codec.json.Jackson2JsonEncoder;
3533
import org.springframework.util.Assert;
3634
import org.springframework.web.reactive.result.view.ViewResolver;
3735

@@ -49,7 +47,8 @@ class DefaultHandlerStrategiesBuilder implements HandlerStrategies.Builder {
4947
.map(Locale::forLanguageTag).findFirst();
5048

5149

52-
private final ServerCodecConfigurer codecConfigurer = new ServerCodecConfigurer();
50+
private final ServerCodecConfigurer codecConfigurer = ServerCodecConfigurer.create();
51+
5352
private final List<ViewResolver> viewResolvers = new ArrayList<>();
5453

5554
private Function<ServerRequest, Optional<Locale>> localeResolver;
@@ -66,51 +65,18 @@ public void defaultConfiguration() {
6665
}
6766

6867
@Override
69-
public HandlerStrategies.Builder serverSentEventEncoder(Encoder<?> encoder) {
70-
Assert.notNull(encoder, "'encoder' must not be null");
71-
this.codecConfigurer.defaultCodecs().serverSentEventEncoder(encoder);
72-
return this;
73-
}
74-
75-
@Override
76-
public HandlerStrategies.Builder jackson2Decoder(Jackson2JsonDecoder decoder) {
77-
Assert.notNull(decoder, "'decoder' must not be null");
78-
this.codecConfigurer.defaultCodecs().jackson2Decoder(decoder);
79-
return this;
80-
}
81-
82-
@Override
83-
public HandlerStrategies.Builder jackson2Encoder(Jackson2JsonEncoder encoder) {
84-
Assert.notNull(encoder, "'encoder' must not be null");
85-
this.codecConfigurer.defaultCodecs().jackson2Encoder(encoder);
86-
return this;
87-
}
88-
89-
@Override
90-
public HandlerStrategies.Builder customDecoder(Decoder<?> decoder) {
91-
Assert.notNull(decoder, "'decoder' must not be null");
92-
this.codecConfigurer.customCodecs().decoder(decoder);
93-
return this;
94-
}
95-
96-
@Override
97-
public HandlerStrategies.Builder customEncoder(Encoder<?> encoder) {
98-
Assert.notNull(encoder, "'encoder' must not be null");
99-
this.codecConfigurer.customCodecs().encoder(encoder);
100-
return this;
101-
}
102-
103-
@Override
104-
public HandlerStrategies.Builder customMessageReader(HttpMessageReader<?> reader) {
105-
Assert.notNull(reader, "'reader' must not be null");
106-
this.codecConfigurer.customCodecs().reader(reader);
68+
public HandlerStrategies.Builder defaultCodecs(
69+
Consumer<ServerCodecConfigurer.ServerDefaultCodecsConfigurer> consumer) {
70+
Assert.notNull(consumer, "'consumer' must not be null");
71+
consumer.accept(this.codecConfigurer.defaultCodecs());
10772
return this;
10873
}
10974

11075
@Override
111-
public HandlerStrategies.Builder customMessageWriter(HttpMessageWriter<?> writer) {
112-
Assert.notNull(writer, "'writer' must not be null");
113-
this.codecConfigurer.customCodecs().writer(writer);
76+
public HandlerStrategies.Builder customCodecs(
77+
Consumer<CodecConfigurer.CustomCodecsConfigurer> consumer) {
78+
Assert.notNull(consumer, "'consumer' must not be null");
79+
consumer.accept(this.codecConfigurer.customCodecs());
11480
return this;
11581
}
11682

0 commit comments

Comments
 (0)