diff --git a/spring-web/src/main/java/org/springframework/web/client/DefaultRestClientBuilder.java b/spring-web/src/main/java/org/springframework/web/client/DefaultRestClientBuilder.java index a0009ec1aac6..6944cae9aef8 100644 --- a/spring-web/src/main/java/org/springframework/web/client/DefaultRestClientBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/client/DefaultRestClientBuilder.java @@ -19,6 +19,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -63,6 +64,7 @@ * * @author Arjen Poutsma * @author Hyoungjune Kim + * @author Sebastien Deleuze * @since 6.1 */ final class DefaultRestClientBuilder implements RestClient.Builder { @@ -358,6 +360,14 @@ public RestClient.Builder requestFactory(ClientHttpRequestFactory requestFactory @Override public RestClient.Builder messageConverters(Consumer>> configurer) { configurer.accept(initMessageConverters()); + validateConverters(this.messageConverters); + return this; + } + + @Override + public RestClient.Builder messageConverters(List> messageConverters) { + validateConverters(messageConverters); + this.messageConverters = Collections.unmodifiableList(messageConverters); return this; } @@ -413,6 +423,11 @@ else if (jsonbPresent) { return this.messageConverters; } + private void validateConverters(@Nullable List> messageConverters) { + Assert.notEmpty(messageConverters, "At least one HttpMessageConverter is required"); + Assert.noNullElements(messageConverters, "The HttpMessageConverter list must not contain null elements"); + } + @Override public RestClient.Builder clone() { diff --git a/spring-web/src/main/java/org/springframework/web/client/RestClient.java b/spring-web/src/main/java/org/springframework/web/client/RestClient.java index 8daef751c67d..c80ac5ae5a03 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestClient.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestClient.java @@ -73,6 +73,7 @@ * * * @author Arjen Poutsma + * @author Sebastien Deleuze * @since 6.1 */ public interface RestClient { @@ -399,11 +400,22 @@ Builder defaultStatusHandler(Predicate statusPredicate, /** * Configure the message converters for the {@code RestClient} to use. - * @param configurer the configurer to apply + * @param configurer the configurer to apply on the list of default + * {@link HttpMessageConverter} pre-initialized * @return this builder + * @see #messageConverters(List) */ Builder messageConverters(Consumer>> configurer); + /** + * Set the message converters for the {@code RestClient} to use. + * @param messageConverters the list of {@link HttpMessageConverter} to use + * @return this builder + * @since 6.2 + * @see #messageConverters(Consumer) + */ + Builder messageConverters(List> messageConverters); + /** * Configure the {@link io.micrometer.observation.ObservationRegistry} to use * for recording HTTP client observations. diff --git a/spring-web/src/test/java/org/springframework/web/client/RestClientBuilderTests.java b/spring-web/src/test/java/org/springframework/web/client/RestClientBuilderTests.java index 001ed2214487..4247390169a8 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestClientBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestClientBuilderTests.java @@ -18,8 +18,11 @@ import java.lang.reflect.Field; import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; import org.springframework.http.client.ClientHttpRequestInitializer; @@ -32,11 +35,13 @@ import org.springframework.web.util.DefaultUriBuilderFactory; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.fail; /** * @author Arjen Poutsma + * @author Sebastien Deleuze */ public class RestClientBuilderTests { @@ -103,6 +108,35 @@ void defaultUri() { assertThat(fieldValue("baseUrl", defaultBuilder)).isEqualTo(baseUrl.toString()); } + @Test + void messageConvertersList() { + StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); + RestClient.Builder builder = RestClient.builder(); + builder.messageConverters(List.of(stringConverter)); + + assertThat(builder).isInstanceOf(DefaultRestClientBuilder.class); + DefaultRestClientBuilder defaultBuilder = (DefaultRestClientBuilder) builder; + + assertThat(fieldValue("messageConverters", defaultBuilder)) + .asInstanceOf(InstanceOfAssertFactories.LIST) + .containsExactly(stringConverter); + } + + @Test + void messageConvertersListEmpty() { + RestClient.Builder builder = RestClient.builder(); + List> converters = Collections.emptyList(); + assertThatIllegalArgumentException().isThrownBy(() -> builder.messageConverters(converters)); + } + + @Test + void messageConvertersListWithNullElement() { + RestClient.Builder builder = RestClient.builder(); + List> converters = new ArrayList<>(); + converters.add(null); + assertThatIllegalArgumentException().isThrownBy(() -> builder.messageConverters(converters)); + } + @Nullable private static Object fieldValue(String name, DefaultRestClientBuilder instance) { try {