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.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit acfeb77

Please sign in to comment.