Skip to content

Commit

Permalink
Polishing
Browse files Browse the repository at this point in the history
  • Loading branch information
rstoyanchev committed Dec 2, 2019
1 parent d420939 commit acfeb77
Show file tree
Hide file tree
Showing 18 changed files with 250 additions and 104 deletions.
Expand Up @@ -143,12 +143,6 @@ public WebTestClient.Builder exchangeStrategies(ExchangeStrategies strategies) {
return this;
}

@Override
public WebTestClient.Builder exchangeStrategies(ExchangeStrategies.Builder strategies) {
this.webClientBuilder.exchangeStrategies(strategies);
return this;
}

@Override
public WebTestClient.Builder exchangeStrategies(Consumer<ExchangeStrategies.Builder> configurer) {
this.webClientBuilder.exchangeStrategies(configurer);
Expand Down
Expand Up @@ -444,30 +444,21 @@ interface Builder {

/**
* Configure the {@link ExchangeStrategies} to use.
* <p>This is useful for changing the default settings, yet still allowing
* further customizations via {@link #exchangeStrategies(Consumer)}.
* By default {@link ExchangeStrategies#withDefaults()} is used.
* <p>Note that in a scenario where the builder is configured by
* multiple parties, it is preferable to use
* {@link #exchangeStrategies(Consumer)} in order to customize the same
* {@code ExchangeStrategies}. This method here sets the strategies that
* everyone else then can customize.
* <p>By default this is {@link ExchangeStrategies#withDefaults()}.
* @param strategies the strategies to use
* @deprecated as of 5.1 in favor of {@link #exchangeStrategies(ExchangeStrategies.Builder)}
*/
@Deprecated
Builder exchangeStrategies(ExchangeStrategies strategies);

/**
* Configure the {@link ExchangeStrategies.Builder} to use.
* <p>This is useful for changing the default settings, yet still allowing
* further customizations via {@link #exchangeStrategies(Consumer)}.
* By default {@link ExchangeStrategies#builder()} is used.
* @param strategies the strategies to use
* @since 5.1.12
*/
Builder exchangeStrategies(ExchangeStrategies.Builder strategies);

/**
* Customize the {@link ExchangeStrategies}.
* <p>Allows further customization on {@link ExchangeStrategies},
* mutating them if they were {@link #exchangeStrategies(ExchangeStrategies) set},
* or starting from {@link ExchangeStrategies#withDefaults() defaults}.
* Customize the strategies configured via
* {@link #exchangeStrategies(ExchangeStrategies)}. This method is
* designed for use in scenarios where multiple parties wish to update
* the {@code ExchangeStrategies}.
* @since 5.1.12
*/
Builder exchangeStrategies(Consumer<ExchangeStrategies.Builder> configurer);
Expand Down
Expand Up @@ -64,11 +64,12 @@ public interface ClientCodecConfigurer extends CodecConfigurer {
ClientDefaultCodecs defaultCodecs();

/**
* Clone this {@link ClientCodecConfigurer}.
* {@inheritDoc}.
*/
@Override
ClientCodecConfigurer clone();


/**
* Static factory method for a {@code ClientCodecConfigurer}.
*/
Expand Down
Expand Up @@ -88,7 +88,10 @@ public interface CodecConfigurer {
List<HttpMessageWriter<?>> getWriters();

/**
* Clone this {@link CodecConfigurer}.
* Create a copy of this {@link CodecConfigurer}. The returned clone has its
* own lists of default and custom codecs and generally can be configured
* independently. Keep in mind however that codec instances (if any are
* configured) are themselves not cloned.
* @since 5.1.12
*/
CodecConfigurer clone();
Expand Down
Expand Up @@ -62,6 +62,12 @@ public interface ServerCodecConfigurer extends CodecConfigurer {
@Override
ServerDefaultCodecs defaultCodecs();

/**
* {@inheritDoc}.
*/
@Override
ServerCodecConfigurer clone();


/**
* Static factory method for a {@code ServerCodecConfigurer}.
Expand Down
Expand Up @@ -37,7 +37,7 @@
* @author Brian Clozel
* @since 5.0
*/
class BaseCodecConfigurer implements CodecConfigurer {
abstract class BaseCodecConfigurer implements CodecConfigurer {

protected final BaseDefaultCodecs defaultCodecs;

Expand All @@ -55,14 +55,21 @@ class BaseCodecConfigurer implements CodecConfigurer {
}

/**
* Constructor with another {@link BaseCodecConfigurer} to copy
* the configuration from.
* Create a deep copy of the given {@link BaseCodecConfigurer}.
* @since 5.1.12
*/
BaseCodecConfigurer(BaseCodecConfigurer other) {
protected BaseCodecConfigurer(BaseCodecConfigurer other) {
this.defaultCodecs = other.cloneDefaultCodecs();
this.customCodecs = new DefaultCustomCodecs(other.customCodecs);
}

/**
* Sub-classes should override this to create deep copy of
* {@link BaseDefaultCodecs} which can can be client or server specific.
* @since 5.1.12
*/
protected abstract BaseDefaultCodecs cloneDefaultCodecs();


@Override
public DefaultCodecs defaultCodecs() {
Expand Down Expand Up @@ -99,16 +106,6 @@ public List<HttpMessageWriter<?>> getWriters() {
}


@Override
public CodecConfigurer clone() {
return new BaseCodecConfigurer(this);
}

protected BaseDefaultCodecs cloneDefaultCodecs() {
return new BaseDefaultCodecs(this.defaultCodecs);
}


/**
* Internal method that returns the configured writers.
* @param forMultipart whether to returns writers for general use ("false"),
Expand All @@ -128,6 +125,9 @@ protected List<HttpMessageWriter<?>> getWritersInternal(boolean forMultipart) {
return result;
}

@Override
public abstract CodecConfigurer clone();


/**
* Default implementation of {@code CustomCodecs}.
Expand All @@ -146,6 +146,10 @@ protected static final class DefaultCustomCodecs implements CustomCodecs {
DefaultCustomCodecs() {
}

/**
* Create a deep copy of the given {@link DefaultCustomCodecs}.
* @since 5.1.12
*/
DefaultCustomCodecs(DefaultCustomCodecs other) {
other.typedReaders.addAll(this.typedReaders);
other.typedWriters.addAll(this.typedWriters);
Expand Down
Expand Up @@ -109,6 +109,9 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs {
BaseDefaultCodecs() {
}

/**
* Create a deep copy of the given {@link BaseDefaultCodecs}.
*/
protected BaseDefaultCodecs(BaseDefaultCodecs other) {
this.jackson2JsonDecoder = other.jackson2JsonDecoder;
this.jackson2JsonEncoder = other.jackson2JsonEncoder;
Expand Down
Expand Up @@ -22,6 +22,7 @@
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
Expand Down Expand Up @@ -123,6 +124,47 @@ public void jackson2EncoderOverride() {
.filter(e -> e == decoder).orElse(null)).isSameAs(decoder);
}

@Test
public void cloneConfigurer() {
ClientCodecConfigurer clone = this.configurer.clone();

Jackson2JsonDecoder jackson2Decoder = new Jackson2JsonDecoder();
clone.defaultCodecs().serverSentEventDecoder(jackson2Decoder);
clone.defaultCodecs().multipartCodecs().encoder(new Jackson2SmileEncoder());
clone.defaultCodecs().multipartCodecs().writer(new ResourceHttpMessageWriter());

// Clone has the customizations

Decoder<?> sseDecoder = clone.getReaders().stream()
.filter(reader -> reader instanceof ServerSentEventHttpMessageReader)
.map(reader -> ((ServerSentEventHttpMessageReader) reader).getDecoder())
.findFirst()
.get();

List<HttpMessageWriter<?>> multipartWriters = clone.getWriters().stream()
.filter(writer -> writer instanceof MultipartHttpMessageWriter)
.flatMap(writer -> ((MultipartHttpMessageWriter) writer).getPartWriters().stream())
.collect(Collectors.toList());

assertThat(sseDecoder).isSameAs(jackson2Decoder);
assertThat(multipartWriters).hasSize(2);

// Original does not have the customizations

sseDecoder = this.configurer.getReaders().stream()
.filter(reader -> reader instanceof ServerSentEventHttpMessageReader)
.map(reader -> ((ServerSentEventHttpMessageReader) reader).getDecoder())
.findFirst()
.get();

multipartWriters = this.configurer.getWriters().stream()
.filter(writer -> writer instanceof MultipartHttpMessageWriter)
.flatMap(writer -> ((MultipartHttpMessageWriter) writer).getPartWriters().stream())
.collect(Collectors.toList());

assertThat(sseDecoder).isNotSameAs(jackson2Decoder);
assertThat(multipartWriters).hasSize(10);
}

private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) {
HttpMessageReader<?> reader = readers.get(this.index.getAndIncrement());
Expand Down
Expand Up @@ -18,6 +18,7 @@

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import com.google.protobuf.ExtensionRegistry;
import org.junit.jupiter.api.Test;
Expand All @@ -42,6 +43,8 @@
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageReader;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;
import org.springframework.http.codec.ServerSentEventHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.Jackson2SmileDecoder;
Expand Down Expand Up @@ -269,11 +272,68 @@ public void encoderDecoderOverrides() {
}

@Test
public void cloneConfigurer() {
CodecConfigurer clone = this.configurer.clone();
public void cloneCustomCodecs() {
this.configurer.registerDefaults(false);
CodecConfigurer clone = this.configurer.clone();

clone.customCodecs().encoder(new Jackson2JsonEncoder());
clone.customCodecs().decoder(new Jackson2JsonDecoder());
clone.customCodecs().reader(new ServerSentEventHttpMessageReader());
clone.customCodecs().writer(new ServerSentEventHttpMessageWriter());

assertThat(this.configurer.getReaders().size()).isEqualTo(0);
assertThat(clone.getReaders().size()).isEqualTo(11);
assertThat(this.configurer.getWriters().size()).isEqualTo(0);
assertThat(clone.getReaders().size()).isEqualTo(2);
assertThat(clone.getWriters().size()).isEqualTo(2);
}

@Test
public void cloneDefaultCodecs() {
CodecConfigurer clone = this.configurer.clone();

Jackson2JsonDecoder jacksonDecoder = new Jackson2JsonDecoder();
Jackson2JsonEncoder jacksonEncoder = new Jackson2JsonEncoder();
Jaxb2XmlDecoder jaxb2Decoder = new Jaxb2XmlDecoder();
Jaxb2XmlEncoder jaxb2Encoder = new Jaxb2XmlEncoder();
ProtobufDecoder protoDecoder = new ProtobufDecoder();
ProtobufEncoder protoEncoder = new ProtobufEncoder();

clone.defaultCodecs().jackson2JsonDecoder(jacksonDecoder);
clone.defaultCodecs().jackson2JsonEncoder(jacksonEncoder);
clone.defaultCodecs().jaxb2Decoder(jaxb2Decoder);
clone.defaultCodecs().jaxb2Encoder(jaxb2Encoder);
clone.defaultCodecs().protobufDecoder(protoDecoder);
clone.defaultCodecs().protobufEncoder(protoEncoder);

// Clone has the customized the customizations

List<Decoder<?>> decoders = clone.getReaders().stream()
.filter(reader -> reader instanceof DecoderHttpMessageReader)
.map(reader -> ((DecoderHttpMessageReader<?>) reader).getDecoder())
.collect(Collectors.toList());

List<Encoder<?>> encoders = clone.getWriters().stream()
.filter(writer -> writer instanceof EncoderHttpMessageWriter)
.map(reader -> ((EncoderHttpMessageWriter<?>) reader).getEncoder())
.collect(Collectors.toList());

assertThat(decoders).contains(jacksonDecoder, jaxb2Decoder, protoDecoder);
assertThat(encoders).contains(jacksonEncoder, jaxb2Encoder, protoEncoder);

// Original does not have the customizations

decoders = this.configurer.getReaders().stream()
.filter(reader -> reader instanceof DecoderHttpMessageReader)
.map(reader -> ((DecoderHttpMessageReader<?>) reader).getDecoder())
.collect(Collectors.toList());

encoders = this.configurer.getWriters().stream()
.filter(writer -> writer instanceof EncoderHttpMessageWriter)
.map(reader -> ((EncoderHttpMessageWriter<?>) reader).getEncoder())
.collect(Collectors.toList());

assertThat(decoders).doesNotContain(jacksonDecoder, jaxb2Decoder, protoDecoder);
assertThat(encoders).doesNotContain(jacksonEncoder, jaxb2Encoder, protoEncoder);
}

private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) {
Expand Down Expand Up @@ -324,10 +384,21 @@ private void assertEncoderInstance(Encoder<?> encoder) {
private static class TestCodecConfigurer extends BaseCodecConfigurer {

TestCodecConfigurer() {
super(new TestDefaultCodecs());
super(new BaseDefaultCodecs());
}

TestCodecConfigurer(TestCodecConfigurer other) {
super(other);
}

@Override
protected BaseDefaultCodecs cloneDefaultCodecs() {
return new BaseDefaultCodecs((BaseDefaultCodecs) defaultCodecs());
}

private static class TestDefaultCodecs extends BaseDefaultCodecs {
@Override
public CodecConfigurer clone() {
return new TestCodecConfigurer(this);
}
}

Expand Down
Expand Up @@ -154,6 +154,50 @@ public void maxInMemorySize() {
assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
}

@Test
public void cloneConfigurer() {
ServerCodecConfigurer clone = this.configurer.clone();

MultipartHttpMessageReader reader = new MultipartHttpMessageReader(new SynchronossPartHttpMessageReader());
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
clone.defaultCodecs().multipartReader(reader);
clone.defaultCodecs().serverSentEventEncoder(encoder);

// Clone has the customizations

HttpMessageReader<?> actualReader = clone.getReaders().stream()
.filter(r -> r instanceof MultipartHttpMessageReader)
.findFirst()
.get();

Encoder<?> actualEncoder = clone.getWriters().stream()
.filter(writer -> writer instanceof ServerSentEventHttpMessageWriter)
.map(writer -> ((ServerSentEventHttpMessageWriter) writer).getEncoder())
.findFirst()
.get();


assertThat(actualReader).isSameAs(reader);
assertThat(actualEncoder).isSameAs(encoder);

// Original does not have the customizations

actualReader = this.configurer.getReaders().stream()
.filter(r -> r instanceof MultipartHttpMessageReader)
.findFirst()
.get();

actualEncoder = this.configurer.getWriters().stream()
.filter(writer -> writer instanceof ServerSentEventHttpMessageWriter)
.map(writer -> ((ServerSentEventHttpMessageWriter) writer).getEncoder())
.findFirst()
.get();


assertThat(actualReader).isNotSameAs(reader);
assertThat(actualEncoder).isNotSameAs(encoder);
}

private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) {
HttpMessageReader<?> reader = nextReader(readers);
assertThat(reader.getClass()).isEqualTo(DecoderHttpMessageReader.class);
Expand Down

0 comments on commit acfeb77

Please sign in to comment.