Deprecate HttpMessageConverters for Framework's
Prior to this commit, Spring Boot had an `HttpMessageConverters` class that allowed, to configure message converter instances for MVC server applications and traditional Spring HTTP clients. As of Spring Framework 7.0, Framework ships its own `HttpMessageConverters` class, aligning with the existing codecs configuration on the WebFlux side. As a result, a few methods taking `List<HttpMessageConverter>` as arguments were deprecated in favor of the new arrangement. This commit adapts to the Framework changes by deprecating Boot's `HttpMessageConverters` in favor of Framework's. This splits the client and server configuration as they are meant to be managed separately. Applications can still contribute `HttpMessageConverters` (Boot's variant) beans but the type itself is now deprecated. Instead, applications should now contribute `ClientHttpMessageConvertersCustomizer` and `ServerHttpMessageConvertersCustomizer` beans to customize message converters. Closes gh-46411
This commit is contained in:
parent
418e057afc
commit
92ee73df30
|
@ -97,13 +97,11 @@ By default, strings are encoded in `UTF-8`.
|
||||||
Any javadoc:org.springframework.http.converter.HttpMessageConverter[] bean that is present in the context is added to the list of converters.
|
Any javadoc:org.springframework.http.converter.HttpMessageConverter[] bean that is present in the context is added to the list of converters.
|
||||||
You can also override default converters in the same way.
|
You can also override default converters in the same way.
|
||||||
|
|
||||||
If you need to add or customize converters, you can use Spring Boot's javadoc:org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters[] class, as shown in the following listing:
|
If you need to add or customize converters, you can declare one or more javadoc:org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer[] or
|
||||||
|
javadoc:org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer[] as beans, as shown in the following listing:
|
||||||
|
|
||||||
include-code::MyHttpMessageConvertersConfiguration[]
|
include-code::MyHttpMessageConvertersConfiguration[]
|
||||||
|
|
||||||
For further control, you can also sub-class javadoc:org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters[] and override its `postProcessConverters` and/or `postProcessPartConverters` methods.
|
|
||||||
This can be useful when you want to re-order or remove some of the converters that Spring MVC configures by default.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[web.servlet.spring-mvc.message-codes]]
|
[[web.servlet.spring-mvc.message-codes]]
|
||||||
|
|
|
@ -16,19 +16,17 @@
|
||||||
|
|
||||||
package org.springframework.boot.docs.web.servlet.springmvc.messageconverters;
|
package org.springframework.boot.docs.web.servlet.springmvc.messageconverters;
|
||||||
|
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
public class MyHttpMessageConvertersConfiguration {
|
public class MyHttpMessageConvertersConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public HttpMessageConverters customConverters() {
|
public ClientHttpMessageConvertersCustomizer myClientConvertersCustomizer() {
|
||||||
HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();
|
return (clientBuilder) -> clientBuilder.customMessageConverter(new AdditionalHttpMessageConverter())
|
||||||
HttpMessageConverter<?> another = new AnotherHttpMessageConverter();
|
.customMessageConverter(new AnotherHttpMessageConverter());
|
||||||
return new HttpMessageConverters(additional, another);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,19 +16,21 @@
|
||||||
|
|
||||||
package org.springframework.boot.docs.web.servlet.springmvc.messageconverters
|
package org.springframework.boot.docs.web.servlet.springmvc.messageconverters
|
||||||
|
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters
|
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
import org.springframework.http.converter.HttpMessageConverter
|
import org.springframework.http.converter.HttpMessageConverters
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
class MyHttpMessageConvertersConfiguration {
|
class MyHttpMessageConvertersConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
fun customConverters(): HttpMessageConverters {
|
fun myClientConvertersCustomizer(): ClientHttpMessageConvertersCustomizer {
|
||||||
val additional: HttpMessageConverter<*> = AdditionalHttpMessageConverter()
|
return ClientHttpMessageConvertersCustomizer { clientBuilder: HttpMessageConverters.ClientBuilder ->
|
||||||
val another: HttpMessageConverter<*> = AnotherHttpMessageConverter()
|
clientBuilder
|
||||||
return HttpMessageConverters(additional, another)
|
.customMessageConverter(AdditionalHttpMessageConverter())
|
||||||
|
.customMessageConverter(AnotherHttpMessageConverter())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||||
import org.springframework.boot.graphql.autoconfigure.GraphQlAutoConfiguration;
|
import org.springframework.boot.graphql.autoconfigure.GraphQlAutoConfiguration;
|
||||||
import org.springframework.boot.graphql.autoconfigure.GraphQlCorsProperties;
|
import org.springframework.boot.graphql.autoconfigure.GraphQlCorsProperties;
|
||||||
import org.springframework.boot.graphql.autoconfigure.GraphQlProperties;
|
import org.springframework.boot.graphql.autoconfigure.GraphQlProperties;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ImportRuntimeHints;
|
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||||
|
@ -177,21 +176,20 @@ public final class GraphQlWebMvcAutoConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ConditionalOnClass({ HttpMessageConverters.class, ServerContainer.class, WebSocketHandler.class })
|
@ConditionalOnClass({ HttpMessageConverter.class, ServerContainer.class, WebSocketHandler.class })
|
||||||
@ConditionalOnProperty("spring.graphql.websocket.path")
|
@ConditionalOnProperty("spring.graphql.websocket.path")
|
||||||
static class WebSocketConfiguration {
|
static class WebSocketConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
GraphQlWebSocketHandler graphQlWebSocketHandler(WebGraphQlHandler webGraphQlHandler,
|
GraphQlWebSocketHandler graphQlWebSocketHandler(WebGraphQlHandler webGraphQlHandler,
|
||||||
GraphQlProperties properties, HttpMessageConverters converters) {
|
GraphQlProperties properties, ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||||
return new GraphQlWebSocketHandler(webGraphQlHandler, getJsonConverter(converters),
|
return new GraphQlWebSocketHandler(webGraphQlHandler, getJsonConverter(converters),
|
||||||
properties.getWebsocket().getConnectionInitTimeout(), properties.getWebsocket().getKeepAlive());
|
properties.getWebsocket().getConnectionInitTimeout(), properties.getWebsocket().getKeepAlive());
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpMessageConverter<Object> getJsonConverter(HttpMessageConverters converters) {
|
private HttpMessageConverter<Object> getJsonConverter(ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||||
return converters.getConverters()
|
return converters.orderedStream()
|
||||||
.stream()
|
|
||||||
.filter(this::canReadJsonMap)
|
.filter(this::canReadJsonMap)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.map(this::asObjectHttpMessageConverter)
|
.map(this::asObjectHttpMessageConverter)
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.http.converter.autoconfigure;
|
||||||
|
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ClientBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback interface that can be used to customize a {@link HttpMessageConverters} for
|
||||||
|
* client usage.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ClientHttpMessageConvertersCustomizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to customize a {@link HttpMessageConverters.ClientBuilder} instance.
|
||||||
|
* @param builder the builder to customize
|
||||||
|
*/
|
||||||
|
void customize(ClientBuilder builder);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.http.converter.autoconfigure;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ClientBuilder;
|
||||||
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
class DefaultClientHttpMessageConvertersCustomizer implements ClientHttpMessageConvertersCustomizer {
|
||||||
|
|
||||||
|
private final @Nullable HttpMessageConverters legacyConverters;
|
||||||
|
|
||||||
|
private final Collection<HttpMessageConverter<?>> converters;
|
||||||
|
|
||||||
|
DefaultClientHttpMessageConvertersCustomizer(@Nullable HttpMessageConverters legacyConverters,
|
||||||
|
Collection<HttpMessageConverter<?>> converters) {
|
||||||
|
|
||||||
|
this.legacyConverters = legacyConverters;
|
||||||
|
this.converters = converters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void customize(ClientBuilder builder) {
|
||||||
|
if (this.legacyConverters != null) {
|
||||||
|
this.legacyConverters.forEach(builder::customMessageConverter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.registerDefaults();
|
||||||
|
this.converters.forEach((converter) -> {
|
||||||
|
if (converter instanceof StringHttpMessageConverter) {
|
||||||
|
builder.stringMessageConverter(converter);
|
||||||
|
}
|
||||||
|
else if (converter instanceof KotlinSerializationJsonHttpMessageConverter) {
|
||||||
|
builder.customMessageConverter(converter);
|
||||||
|
}
|
||||||
|
else if (converter.getSupportedMediaTypes().contains(MediaType.APPLICATION_JSON)) {
|
||||||
|
builder.jsonMessageConverter(converter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.customMessageConverter(converter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.http.converter.autoconfigure;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ServerBuilder;
|
||||||
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
class DefaultServerHttpMessageConvertersCustomizer implements ServerHttpMessageConvertersCustomizer {
|
||||||
|
|
||||||
|
private final @Nullable HttpMessageConverters legacyConverters;
|
||||||
|
|
||||||
|
private final Collection<HttpMessageConverter<?>> converters;
|
||||||
|
|
||||||
|
DefaultServerHttpMessageConvertersCustomizer(@Nullable HttpMessageConverters legacyConverters,
|
||||||
|
Collection<HttpMessageConverter<?>> converters) {
|
||||||
|
|
||||||
|
this.legacyConverters = legacyConverters;
|
||||||
|
this.converters = converters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void customize(ServerBuilder builder) {
|
||||||
|
if (this.legacyConverters != null) {
|
||||||
|
this.legacyConverters.forEach(builder::customMessageConverter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.registerDefaults();
|
||||||
|
this.converters.forEach((converter) -> {
|
||||||
|
if (converter instanceof StringHttpMessageConverter) {
|
||||||
|
builder.stringMessageConverter(converter);
|
||||||
|
}
|
||||||
|
else if (converter instanceof KotlinSerializationJsonHttpMessageConverter) {
|
||||||
|
builder.customMessageConverter(converter);
|
||||||
|
}
|
||||||
|
else if (converter.getSupportedMediaTypes().contains(MediaType.APPLICATION_JSON)) {
|
||||||
|
builder.jsonMessageConverter(converter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.customMessageConverter(converter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -53,7 +53,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupp
|
||||||
* @see #HttpMessageConverters(HttpMessageConverter...)
|
* @see #HttpMessageConverters(HttpMessageConverter...)
|
||||||
* @see #HttpMessageConverters(Collection)
|
* @see #HttpMessageConverters(Collection)
|
||||||
* @see #getConverters()
|
* @see #getConverters()
|
||||||
|
* @deprecated since 4.0 in favor of {@link ClientHttpMessageConvertersCustomizer} and
|
||||||
|
* {@link ServerHttpMessageConvertersCustomizer}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "4.0")
|
||||||
public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>> {
|
public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>> {
|
||||||
|
|
||||||
private static final List<Class<?>> NON_REPLACING_CONVERTERS;
|
private static final List<Class<?>> NON_REPLACING_CONVERTERS;
|
||||||
|
|
|
@ -30,6 +30,8 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
* @author Dmitry Sulman
|
* @author Dmitry Sulman
|
||||||
|
* @author Brian Clozel
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration(afterName = { "org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration",
|
@AutoConfiguration(afterName = { "org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration",
|
||||||
|
@ -61,9 +64,23 @@ public final class HttpMessageConvertersAutoConfiguration {
|
||||||
static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
|
static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||||
HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
|
@SuppressWarnings("deprecation")
|
||||||
return new HttpMessageConverters(converters.orderedStream().toList());
|
ClientHttpMessageConvertersCustomizer clientConvertersCustomizer(
|
||||||
|
ObjectProvider<HttpMessageConverters> legacyConverters,
|
||||||
|
ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||||
|
return new DefaultClientHttpMessageConvertersCustomizer(legacyConverters.getIfAvailable(),
|
||||||
|
converters.orderedStream().toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
ServerHttpMessageConvertersCustomizer serverConvertersCustomizer(
|
||||||
|
ObjectProvider<HttpMessageConverters> legacyConverters,
|
||||||
|
ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||||
|
return new DefaultServerHttpMessageConvertersCustomizer(legacyConverters.getIfAvailable(),
|
||||||
|
converters.orderedStream().toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-present the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.http.converter.autoconfigure;
|
||||||
|
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ServerBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback interface that can be used to customize a {@link HttpMessageConverters} for
|
||||||
|
* server usage.
|
||||||
|
*
|
||||||
|
* @author Brian Clozel
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ServerHttpMessageConvertersCustomizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to customize a {@link ServerBuilder} instance.
|
||||||
|
* @param builder the builder to customize
|
||||||
|
*/
|
||||||
|
void customize(ServerBuilder builder);
|
||||||
|
|
||||||
|
}
|
|
@ -44,6 +44,9 @@ import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguratio
|
||||||
import org.springframework.hateoas.RepresentationModel;
|
import org.springframework.hateoas.RepresentationModel;
|
||||||
import org.springframework.hateoas.server.mvc.TypeConstrainedJacksonJsonHttpMessageConverter;
|
import org.springframework.hateoas.server.mvc.TypeConstrainedJacksonJsonHttpMessageConverter;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ClientBuilder;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ServerBuilder;
|
||||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||||
|
@ -262,14 +265,16 @@ class HttpMessageConvertersAutoConfigurationTests {
|
||||||
void whenServletWebApplicationHttpMessageConvertersIsConfigured() {
|
void whenServletWebApplicationHttpMessageConvertersIsConfigured() {
|
||||||
new WebApplicationContextRunner()
|
new WebApplicationContextRunner()
|
||||||
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
|
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
|
||||||
.run((context) -> assertThat(context).hasSingleBean(HttpMessageConverters.class));
|
.run((context) -> assertThat(context).hasSingleBean(ServerHttpMessageConvertersCustomizer.class)
|
||||||
|
.hasSingleBean(ClientHttpMessageConvertersCustomizer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void whenReactiveWebApplicationHttpMessageConvertersIsNotConfigured() {
|
void whenReactiveWebApplicationHttpMessageConvertersIsNotConfigured() {
|
||||||
new ReactiveWebApplicationContextRunner()
|
new ReactiveWebApplicationContextRunner()
|
||||||
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
|
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
|
||||||
.run((context) -> assertThat(context).doesNotHaveBean(HttpMessageConverters.class));
|
.run((context) -> assertThat(context).doesNotHaveBean(ServerHttpMessageConvertersCustomizer.class)
|
||||||
|
.doesNotHaveBean(ClientHttpMessageConvertersCustomizer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -318,15 +323,33 @@ class HttpMessageConvertersAutoConfigurationTests {
|
||||||
private void assertConverterBeanRegisteredWithHttpMessageConverters(AssertableApplicationContext context,
|
private void assertConverterBeanRegisteredWithHttpMessageConverters(AssertableApplicationContext context,
|
||||||
Class<? extends HttpMessageConverter<?>> type) {
|
Class<? extends HttpMessageConverter<?>> type) {
|
||||||
HttpMessageConverter<?> converter = context.getBean(type);
|
HttpMessageConverter<?> converter = context.getBean(type);
|
||||||
HttpMessageConverters converters = context.getBean(HttpMessageConverters.class);
|
ClientHttpMessageConvertersCustomizer clientCustomizer = context
|
||||||
assertThat(converters.getConverters()).contains(converter);
|
.getBean(ClientHttpMessageConvertersCustomizer.class);
|
||||||
|
ClientBuilder clientBuilder = HttpMessageConverters.forClient().registerDefaults();
|
||||||
|
clientCustomizer.customize(clientBuilder);
|
||||||
|
assertThat(clientBuilder.build()).contains(converter);
|
||||||
|
|
||||||
|
ServerHttpMessageConvertersCustomizer serverCustomizer = context
|
||||||
|
.getBean(ServerHttpMessageConvertersCustomizer.class);
|
||||||
|
ServerBuilder serverBuilder = HttpMessageConverters.forServer().registerDefaults();
|
||||||
|
serverCustomizer.customize(serverBuilder);
|
||||||
|
assertThat(serverBuilder.build()).contains(converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertConvertersBeanRegisteredWithHttpMessageConverters(AssertableApplicationContext context,
|
private void assertConvertersBeanRegisteredWithHttpMessageConverters(AssertableApplicationContext context,
|
||||||
List<Class<? extends HttpMessageConverter<?>>> types) {
|
List<Class<? extends HttpMessageConverter<?>>> types) {
|
||||||
List<? extends HttpMessageConverter<?>> converterInstances = types.stream().map(context::getBean).toList();
|
List<? extends HttpMessageConverter<?>> converterInstances = types.stream().map(context::getBean).toList();
|
||||||
HttpMessageConverters converters = context.getBean(HttpMessageConverters.class);
|
ClientHttpMessageConvertersCustomizer clientCustomizer = context
|
||||||
assertThat(converters.getConverters()).containsSubsequence(converterInstances);
|
.getBean(ClientHttpMessageConvertersCustomizer.class);
|
||||||
|
ClientBuilder clientBuilder = HttpMessageConverters.forClient().registerDefaults();
|
||||||
|
clientCustomizer.customize(clientBuilder);
|
||||||
|
assertThat(clientBuilder.build()).containsSubsequence(converterInstances);
|
||||||
|
|
||||||
|
ServerHttpMessageConvertersCustomizer serverCustomizer = context
|
||||||
|
.getBean(ServerHttpMessageConvertersCustomizer.class);
|
||||||
|
ServerBuilder serverBuilder = HttpMessageConverters.forServer().registerDefaults();
|
||||||
|
serverCustomizer.customize(serverBuilder);
|
||||||
|
assertThat(serverBuilder.build()).containsSubsequence(converterInstances);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
|
@ -38,7 +38,9 @@ class HttpMessageConvertersAutoConfigurationWithoutJacksonTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void autoConfigurationWorksWithSpringHateoasButWithoutJackson() {
|
void autoConfigurationWorksWithSpringHateoasButWithoutJackson() {
|
||||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(HttpMessageConverters.class));
|
this.contextRunner
|
||||||
|
.run((context) -> assertThat(context).hasSingleBean(ClientHttpMessageConvertersCustomizer.class)
|
||||||
|
.hasSingleBean(ServerHttpMessageConvertersCustomizer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import static org.mockito.Mockito.mock;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
class HttpMessageConvertersTests {
|
class HttpMessageConvertersTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -189,7 +189,7 @@ public class RestTemplateBuilder {
|
||||||
* @return a new builder instance
|
* @return a new builder instance
|
||||||
* @see #additionalMessageConverters(HttpMessageConverter...)
|
* @see #additionalMessageConverters(HttpMessageConverter...)
|
||||||
*/
|
*/
|
||||||
public RestTemplateBuilder messageConverters(Collection<? extends HttpMessageConverter<?>> messageConverters) {
|
public RestTemplateBuilder messageConverters(Iterable<? extends HttpMessageConverter<?>> messageConverters) {
|
||||||
Assert.notNull(messageConverters, "'messageConverters' must not be null");
|
Assert.notNull(messageConverters, "'messageConverters' must not be null");
|
||||||
return new RestTemplateBuilder(this.requestFactorySettings, this.detectRequestFactory, this.rootUri,
|
return new RestTemplateBuilder(this.requestFactorySettings, this.detectRequestFactory, this.rootUri,
|
||||||
copiedSetOf(messageConverters), this.interceptors, this.requestFactoryBuilder, this.uriTemplateHandler,
|
copiedSetOf(messageConverters), this.interceptors, this.requestFactoryBuilder, this.uriTemplateHandler,
|
||||||
|
@ -726,8 +726,10 @@ public class RestTemplateBuilder {
|
||||||
return copiedSetOf(Arrays.asList(items));
|
return copiedSetOf(Arrays.asList(items));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> Set<T> copiedSetOf(Collection<? extends T> collection) {
|
private <T> Set<T> copiedSetOf(Iterable<? extends T> collection) {
|
||||||
return Collections.unmodifiableSet(new LinkedHashSet<>(collection));
|
LinkedHashSet<T> set = new LinkedHashSet<>();
|
||||||
|
collection.forEach(set::add);
|
||||||
|
return Collections.unmodifiableSet(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> List<T> copiedListOf(T[] items) {
|
private static <T> List<T> copiedListOf(T[] items) {
|
||||||
|
|
|
@ -19,9 +19,7 @@ package org.springframework.boot.restclient.autoconfigure;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||||
|
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
|
||||||
import org.springframework.boot.restclient.RestClientCustomizer;
|
import org.springframework.boot.restclient.RestClientCustomizer;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -31,33 +29,26 @@ import org.springframework.web.client.RestClient;
|
||||||
* {@link RestClientCustomizer} to apply {@link HttpMessageConverter
|
* {@link RestClientCustomizer} to apply {@link HttpMessageConverter
|
||||||
* HttpMessageConverters}.
|
* HttpMessageConverters}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Brian Clozel
|
||||||
* @since 4.0.0
|
* @since 4.0.0
|
||||||
*/
|
*/
|
||||||
public class HttpMessageConvertersRestClientCustomizer implements RestClientCustomizer {
|
public class HttpMessageConvertersRestClientCustomizer implements RestClientCustomizer {
|
||||||
|
|
||||||
private final @Nullable Iterable<? extends HttpMessageConverter<?>> messageConverters;
|
private final List<ClientHttpMessageConvertersCustomizer> customizers;
|
||||||
|
|
||||||
public HttpMessageConvertersRestClientCustomizer(HttpMessageConverter<?>... messageConverters) {
|
public HttpMessageConvertersRestClientCustomizer(ClientHttpMessageConvertersCustomizer... customizers) {
|
||||||
Assert.notNull(messageConverters, "'messageConverters' must not be null");
|
this(Arrays.asList(customizers));
|
||||||
this.messageConverters = Arrays.asList(messageConverters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpMessageConvertersRestClientCustomizer(@Nullable HttpMessageConverters messageConverters) {
|
public HttpMessageConvertersRestClientCustomizer(List<ClientHttpMessageConvertersCustomizer> customizers) {
|
||||||
this.messageConverters = messageConverters;
|
Assert.notNull(customizers, "customizers must not be null");
|
||||||
|
this.customizers = customizers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
@Override
|
@Override
|
||||||
public void customize(RestClient.Builder restClientBuilder) {
|
public void customize(RestClient.Builder restClientBuilder) {
|
||||||
restClientBuilder.messageConverters(this::configureMessageConverters);
|
restClientBuilder.configureMessageConverters(
|
||||||
}
|
(builder) -> this.customizers.forEach((customizer) -> customizer.customize(builder)));
|
||||||
|
|
||||||
private void configureMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
|
||||||
if (this.messageConverters != null) {
|
|
||||||
messageConverters.clear();
|
|
||||||
this.messageConverters.forEach(messageConverters::add);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||||
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
||||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
||||||
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||||
import org.springframework.boot.restclient.RestClientCustomizer;
|
import org.springframework.boot.restclient.RestClientCustomizer;
|
||||||
import org.springframework.boot.ssl.SslBundles;
|
import org.springframework.boot.ssl.SslBundles;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -38,6 +38,7 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
import org.springframework.web.client.ApiVersionFormatter;
|
import org.springframework.web.client.ApiVersionFormatter;
|
||||||
import org.springframework.web.client.ApiVersionInserter;
|
import org.springframework.web.client.ApiVersionInserter;
|
||||||
import org.springframework.web.client.RestClient;
|
import org.springframework.web.client.RestClient;
|
||||||
|
@ -102,11 +103,11 @@ public final class RestClientAutoConfiguration {
|
||||||
static class HttpMessageConvertersConfiguration {
|
static class HttpMessageConvertersConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnBean(ClientHttpMessageConvertersCustomizer.class)
|
||||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||||
HttpMessageConvertersRestClientCustomizer httpMessageConvertersRestClientCustomizer(
|
HttpMessageConvertersRestClientCustomizer httpMessageConvertersRestClientCustomizer(
|
||||||
ObjectProvider<HttpMessageConverters> messageConverters) {
|
ObjectProvider<ClientHttpMessageConvertersCustomizer> customizerProvider) {
|
||||||
return new HttpMessageConvertersRestClientCustomizer(messageConverters.getIfUnique());
|
return new HttpMessageConvertersRestClientCustomizer(customizerProvider.orderedStream().toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
||||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
||||||
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||||
import org.springframework.boot.restclient.RestTemplateBuilder;
|
import org.springframework.boot.restclient.RestTemplateBuilder;
|
||||||
import org.springframework.boot.restclient.RestTemplateCustomizer;
|
import org.springframework.boot.restclient.RestTemplateCustomizer;
|
||||||
import org.springframework.boot.restclient.RestTemplateRequestCustomizer;
|
import org.springframework.boot.restclient.RestTemplateRequestCustomizer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,13 +52,13 @@ public final class RestTemplateAutoConfiguration {
|
||||||
RestTemplateBuilderConfigurer restTemplateBuilderConfigurer(
|
RestTemplateBuilderConfigurer restTemplateBuilderConfigurer(
|
||||||
ObjectProvider<ClientHttpRequestFactoryBuilder<?>> clientHttpRequestFactoryBuilder,
|
ObjectProvider<ClientHttpRequestFactoryBuilder<?>> clientHttpRequestFactoryBuilder,
|
||||||
ObjectProvider<ClientHttpRequestFactorySettings> clientHttpRequestFactorySettings,
|
ObjectProvider<ClientHttpRequestFactorySettings> clientHttpRequestFactorySettings,
|
||||||
ObjectProvider<HttpMessageConverters> messageConverters,
|
ObjectProvider<ClientHttpMessageConvertersCustomizer> convertersCustomizers,
|
||||||
ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers,
|
ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers,
|
||||||
ObjectProvider<RestTemplateRequestCustomizer<?>> restTemplateRequestCustomizers) {
|
ObjectProvider<RestTemplateRequestCustomizer<?>> restTemplateRequestCustomizers) {
|
||||||
RestTemplateBuilderConfigurer configurer = new RestTemplateBuilderConfigurer();
|
RestTemplateBuilderConfigurer configurer = new RestTemplateBuilderConfigurer();
|
||||||
configurer.setRequestFactoryBuilder(clientHttpRequestFactoryBuilder.getIfAvailable());
|
configurer.setRequestFactoryBuilder(clientHttpRequestFactoryBuilder.getIfAvailable());
|
||||||
configurer.setRequestFactorySettings(clientHttpRequestFactorySettings.getIfAvailable());
|
configurer.setRequestFactorySettings(clientHttpRequestFactorySettings.getIfAvailable());
|
||||||
configurer.setHttpMessageConverters(messageConverters.getIfUnique());
|
configurer.setHttpMessageConvertersCustomizers(convertersCustomizers.orderedStream().toList());
|
||||||
configurer.setRestTemplateCustomizers(restTemplateCustomizers.orderedStream().toList());
|
configurer.setRestTemplateCustomizers(restTemplateCustomizers.orderedStream().toList());
|
||||||
configurer.setRestTemplateRequestCustomizers(restTemplateRequestCustomizers.orderedStream().toList());
|
configurer.setRestTemplateRequestCustomizers(restTemplateRequestCustomizers.orderedStream().toList());
|
||||||
return configurer;
|
return configurer;
|
||||||
|
|
|
@ -24,10 +24,12 @@ import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
||||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||||
import org.springframework.boot.restclient.RestTemplateBuilder;
|
import org.springframework.boot.restclient.RestTemplateBuilder;
|
||||||
import org.springframework.boot.restclient.RestTemplateCustomizer;
|
import org.springframework.boot.restclient.RestTemplateCustomizer;
|
||||||
import org.springframework.boot.restclient.RestTemplateRequestCustomizer;
|
import org.springframework.boot.restclient.RestTemplateRequestCustomizer;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ClientBuilder;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +48,7 @@ public final class RestTemplateBuilderConfigurer {
|
||||||
|
|
||||||
private @Nullable ClientHttpRequestFactorySettings requestFactorySettings;
|
private @Nullable ClientHttpRequestFactorySettings requestFactorySettings;
|
||||||
|
|
||||||
private @Nullable HttpMessageConverters httpMessageConverters;
|
private @Nullable List<ClientHttpMessageConvertersCustomizer> httpMessageConvertersCustomizers;
|
||||||
|
|
||||||
private @Nullable List<RestTemplateCustomizer> restTemplateCustomizers;
|
private @Nullable List<RestTemplateCustomizer> restTemplateCustomizers;
|
||||||
|
|
||||||
|
@ -60,8 +62,9 @@ public final class RestTemplateBuilderConfigurer {
|
||||||
this.requestFactorySettings = requestFactorySettings;
|
this.requestFactorySettings = requestFactorySettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHttpMessageConverters(@Nullable HttpMessageConverters httpMessageConverters) {
|
void setHttpMessageConvertersCustomizers(
|
||||||
this.httpMessageConverters = httpMessageConverters;
|
@Nullable List<ClientHttpMessageConvertersCustomizer> httpMessageConvertersCustomizers) {
|
||||||
|
this.httpMessageConvertersCustomizers = httpMessageConvertersCustomizers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRestTemplateCustomizers(@Nullable List<RestTemplateCustomizer> restTemplateCustomizers) {
|
void setRestTemplateCustomizers(@Nullable List<RestTemplateCustomizer> restTemplateCustomizers) {
|
||||||
|
@ -86,8 +89,10 @@ public final class RestTemplateBuilderConfigurer {
|
||||||
if (this.requestFactorySettings != null) {
|
if (this.requestFactorySettings != null) {
|
||||||
builder = builder.requestFactorySettings(this.requestFactorySettings);
|
builder = builder.requestFactorySettings(this.requestFactorySettings);
|
||||||
}
|
}
|
||||||
if (this.httpMessageConverters != null) {
|
if (this.httpMessageConvertersCustomizers != null) {
|
||||||
builder = builder.messageConverters(this.httpMessageConverters.getConverters());
|
ClientBuilder clientBuilder = HttpMessageConverters.forClient();
|
||||||
|
this.httpMessageConvertersCustomizers.forEach((customizer) -> customizer.customize(clientBuilder));
|
||||||
|
builder = builder.messageConverters(clientBuilder.build());
|
||||||
}
|
}
|
||||||
builder = addCustomizers(builder, this.restTemplateCustomizers, RestTemplateBuilder::customizers);
|
builder = addCustomizers(builder, this.restTemplateCustomizers, RestTemplateBuilder::customizers);
|
||||||
builder = addCustomizers(builder, this.restTemplateRequestCustomizers, RestTemplateBuilder::requestCustomizers);
|
builder = addCustomizers(builder, this.restTemplateRequestCustomizers, RestTemplateBuilder::requestCustomizers);
|
||||||
|
|
|
@ -16,62 +16,35 @@
|
||||||
|
|
||||||
package org.springframework.boot.restclient.autoconfigure;
|
package org.springframework.boot.restclient.autoconfigure;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
|
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.web.client.RestClient;
|
import org.springframework.web.client.RestClient;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
|
||||||
import static org.mockito.BDDMockito.given;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link HttpMessageConvertersRestClientCustomizer}
|
* Tests for {@link HttpMessageConvertersRestClientCustomizer}
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
class HttpMessageConvertersRestClientCustomizerTests {
|
class HttpMessageConvertersRestClientCustomizerTests {
|
||||||
|
|
||||||
@Test
|
|
||||||
void createWhenNullMessageConvertersArrayThrowsException() {
|
|
||||||
assertThatIllegalArgumentException()
|
|
||||||
.isThrownBy(() -> new HttpMessageConvertersRestClientCustomizer((HttpMessageConverter<?>[]) null))
|
|
||||||
.withMessage("'messageConverters' must not be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void createWhenNullMessageConvertersDoesNotCustomize() {
|
|
||||||
HttpMessageConverter<?> c0 = mock();
|
|
||||||
assertThat(apply(new HttpMessageConvertersRestClientCustomizer((HttpMessageConverters) null), c0))
|
|
||||||
.containsExactly(c0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void customizeConfiguresMessageConverters() {
|
void customizeConfiguresMessageConverters() {
|
||||||
HttpMessageConverter<?> c0 = mock();
|
HttpMessageConverter<?> c0 = mock();
|
||||||
HttpMessageConverter<?> c1 = mock();
|
HttpMessageConverter<?> c1 = mock();
|
||||||
HttpMessageConverter<?> c2 = mock();
|
ClientHttpMessageConvertersCustomizer customizer = (clientBuilder) -> clientBuilder.customMessageConverter(c0)
|
||||||
assertThat(apply(new HttpMessageConvertersRestClientCustomizer(c1, c2), c0)).containsExactly(c1, c2);
|
.customMessageConverter(c1);
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "removal" })
|
RestClient.Builder builder = RestClient.builder();
|
||||||
private List<HttpMessageConverter<?>> apply(HttpMessageConvertersRestClientCustomizer customizer,
|
new HttpMessageConvertersRestClientCustomizer(customizer).customize(builder);
|
||||||
HttpMessageConverter<?>... converters) {
|
assertThat(builder.build()).extracting("messageConverters")
|
||||||
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(Arrays.asList(converters));
|
.asInstanceOf(InstanceOfAssertFactories.LIST)
|
||||||
RestClient.Builder restClientBuilder = mock();
|
.containsSubsequence(c0, c1);
|
||||||
ArgumentCaptor<Consumer<List<HttpMessageConverter<?>>>> captor = ArgumentCaptor.forClass(Consumer.class);
|
|
||||||
given(restClientBuilder.messageConverters(captor.capture())).willReturn(restClientBuilder);
|
|
||||||
customizer.customize(restClientBuilder);
|
|
||||||
captor.getValue().accept(messageConverters);
|
|
||||||
return messageConverters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
|
||||||
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
|
||||||
import org.springframework.boot.http.client.HttpRedirects;
|
import org.springframework.boot.http.client.HttpRedirects;
|
||||||
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
|
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
|
||||||
import org.springframework.boot.restclient.RestClientCustomizer;
|
import org.springframework.boot.restclient.RestClientCustomizer;
|
||||||
import org.springframework.boot.ssl.SslBundle;
|
import org.springframework.boot.ssl.SslBundle;
|
||||||
|
@ -42,8 +41,8 @@ import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||||
|
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.web.client.ApiVersionFormatter;
|
import org.springframework.web.client.ApiVersionFormatter;
|
||||||
import org.springframework.web.client.ApiVersionInserter;
|
import org.springframework.web.client.ApiVersionInserter;
|
||||||
|
@ -71,7 +70,6 @@ class RestClientAutoConfigurationTests {
|
||||||
@Test
|
@Test
|
||||||
void shouldSupplyBeans() {
|
void shouldSupplyBeans() {
|
||||||
this.contextRunner.run((context) -> {
|
this.contextRunner.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(HttpMessageConvertersRestClientCustomizer.class);
|
|
||||||
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class);
|
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class);
|
||||||
assertThat(context).hasSingleBean(RestClient.Builder.class);
|
assertThat(context).hasSingleBean(RestClient.Builder.class);
|
||||||
});
|
});
|
||||||
|
@ -162,21 +160,6 @@ class RestClientAutoConfigurationTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
void restClientWhenMessageConvertersDefinedShouldHaveMessageConverters() {
|
|
||||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
|
|
||||||
.withUserConfiguration(RestClientConfig.class)
|
|
||||||
.run((context) -> {
|
|
||||||
RestClient restClient = context.getBean(RestClient.class);
|
|
||||||
List<HttpMessageConverter<?>> expectedConverters = context.getBean(HttpMessageConverters.class)
|
|
||||||
.getConverters();
|
|
||||||
List<HttpMessageConverter<?>> actualConverters = (List<HttpMessageConverter<?>>) ReflectionTestUtils
|
|
||||||
.getField(restClient, "messageConverters");
|
|
||||||
assertThat(actualConverters).containsExactlyElementsOf(expectedConverters);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
void restClientWhenNoMessageConvertersDefinedShouldHaveDefaultMessageConverters() {
|
void restClientWhenNoMessageConvertersDefinedShouldHaveDefaultMessageConverters() {
|
||||||
|
@ -257,15 +240,13 @@ class RestClientAutoConfigurationTests {
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class)
|
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class)
|
||||||
.hasSingleBean(ClientHttpRequestFactorySettings.class)
|
.hasSingleBean(ClientHttpRequestFactorySettings.class)
|
||||||
.hasSingleBean(ClientHttpRequestFactoryBuilder.class)
|
.hasSingleBean(ClientHttpRequestFactoryBuilder.class);
|
||||||
.hasSingleBean(HttpMessageConvertersRestClientCustomizer.class);
|
|
||||||
RestClientBuilderConfigurer configurer = context.getBean(RestClientBuilderConfigurer.class);
|
RestClientBuilderConfigurer configurer = context.getBean(RestClientBuilderConfigurer.class);
|
||||||
assertThat(configurer).hasFieldOrPropertyWithValue("requestFactoryBuilder",
|
assertThat(configurer).hasFieldOrPropertyWithValue("requestFactoryBuilder",
|
||||||
context.getBean(ClientHttpRequestFactoryBuilder.class));
|
context.getBean(ClientHttpRequestFactoryBuilder.class));
|
||||||
assertThat(configurer).hasFieldOrPropertyWithValue("requestFactorySettings",
|
assertThat(configurer).hasFieldOrPropertyWithValue("requestFactorySettings",
|
||||||
context.getBean(ClientHttpRequestFactorySettings.class));
|
context.getBean(ClientHttpRequestFactorySettings.class));
|
||||||
assertThat(configurer).hasFieldOrPropertyWithValue("customizers", List.of(customizer1, customizer2,
|
assertThat(configurer).hasFieldOrPropertyWithValue("customizers", List.of(customizer1, customizer2));
|
||||||
context.getBean(HttpMessageConvertersRestClientCustomizer.class)));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +265,6 @@ class RestClientAutoConfigurationTests {
|
||||||
void whenServletWebApplicationRestClientIsConfigured() {
|
void whenServletWebApplicationRestClientIsConfigured() {
|
||||||
new WebApplicationContextRunner().withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class))
|
new WebApplicationContextRunner().withConfiguration(AutoConfigurations.of(RestClientAutoConfiguration.class))
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(HttpMessageConvertersRestClientCustomizer.class);
|
|
||||||
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class);
|
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class);
|
||||||
assertThat(context).hasSingleBean(RestClient.Builder.class);
|
assertThat(context).hasSingleBean(RestClient.Builder.class);
|
||||||
});
|
});
|
||||||
|
@ -297,7 +277,6 @@ class RestClientAutoConfigurationTests {
|
||||||
.withConfiguration(
|
.withConfiguration(
|
||||||
AutoConfigurations.of(RestClientAutoConfiguration.class, TaskExecutionAutoConfiguration.class))
|
AutoConfigurations.of(RestClientAutoConfiguration.class, TaskExecutionAutoConfiguration.class))
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
assertThat(context).hasSingleBean(HttpMessageConvertersRestClientCustomizer.class);
|
|
||||||
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class);
|
assertThat(context).hasSingleBean(RestClientBuilderConfigurer.class);
|
||||||
assertThat(context).hasSingleBean(RestClient.Builder.class);
|
assertThat(context).hasSingleBean(RestClient.Builder.class);
|
||||||
});
|
});
|
||||||
|
@ -396,7 +375,7 @@ class RestClientAutoConfigurationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CustomHttpMessageConverter extends StringHttpMessageConverter {
|
static class CustomHttpMessageConverter extends ByteArrayHttpMessageConverter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,12 @@
|
||||||
package org.springframework.boot.restclient.autoconfigure;
|
package org.springframework.boot.restclient.autoconfigure;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionOverrideException;
|
import org.springframework.beans.factory.support.BeanDefinitionOverrideException;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
import org.springframework.boot.http.client.autoconfigure.HttpClientAutoConfiguration;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
|
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
|
||||||
import org.springframework.boot.restclient.RestTemplateBuilder;
|
import org.springframework.boot.restclient.RestTemplateBuilder;
|
||||||
import org.springframework.boot.restclient.RestTemplateCustomizer;
|
import org.springframework.boot.restclient.RestTemplateCustomizer;
|
||||||
|
@ -36,10 +34,9 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
|
||||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||||
|
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
|
||||||
import org.springframework.mock.http.client.MockClientHttpRequest;
|
import org.springframework.mock.http.client.MockClientHttpRequest;
|
||||||
import org.springframework.mock.http.client.MockClientHttpResponse;
|
import org.springframework.mock.http.client.MockClientHttpResponse;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
@ -84,19 +81,6 @@ class RestTemplateAutoConfigurationTests {
|
||||||
.isTrue());
|
.isTrue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void restTemplateWhenMessageConvertersDefinedShouldHaveMessageConverters() {
|
|
||||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
|
|
||||||
.withUserConfiguration(RestTemplateConfig.class)
|
|
||||||
.run((context) -> {
|
|
||||||
assertThat(context).hasSingleBean(RestTemplate.class);
|
|
||||||
RestTemplate restTemplate = context.getBean(RestTemplate.class);
|
|
||||||
List<HttpMessageConverter<?>> converters = context.getBean(HttpMessageConverters.class).getConverters();
|
|
||||||
assertThat(restTemplate.getMessageConverters()).containsExactlyElementsOf(converters);
|
|
||||||
assertThat(restTemplate.getRequestFactory()).isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void restTemplateWhenNoMessageConvertersDefinedShouldHaveDefaultMessageConverters() {
|
void restTemplateWhenNoMessageConvertersDefinedShouldHaveDefaultMessageConverters() {
|
||||||
this.contextRunner.withUserConfiguration(RestTemplateConfig.class).run((context) -> {
|
this.contextRunner.withUserConfiguration(RestTemplateConfig.class).run((context) -> {
|
||||||
|
@ -297,7 +281,7 @@ class RestTemplateAutoConfigurationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CustomHttpMessageConverter extends StringHttpMessageConverter {
|
static class CustomHttpMessageConverter extends ByteArrayHttpMessageConverter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,16 @@
|
||||||
|
|
||||||
package org.springframework.boot.webmvc.test.autoconfigure;
|
package org.springframework.boot.webmvc.test.autoconfigure;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
import org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverters.ServerBuilder;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.assertj.MockMvcTester;
|
import org.springframework.test.web.servlet.assertj.MockMvcTester;
|
||||||
|
|
||||||
|
@ -36,11 +40,14 @@ class MockMvcTesterConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
MockMvcTester mockMvcTester(MockMvc mockMvc, ObjectProvider<HttpMessageConverters> httpMessageConverters) {
|
MockMvcTester mockMvcTester(MockMvc mockMvc,
|
||||||
|
ObjectProvider<ServerHttpMessageConvertersCustomizer> customizersProvider) {
|
||||||
MockMvcTester mockMvcTester = MockMvcTester.create(mockMvc);
|
MockMvcTester mockMvcTester = MockMvcTester.create(mockMvc);
|
||||||
HttpMessageConverters converters = httpMessageConverters.getIfAvailable();
|
List<ServerHttpMessageConvertersCustomizer> customizers = customizersProvider.orderedStream().toList();
|
||||||
if (converters != null) {
|
if (!customizers.isEmpty()) {
|
||||||
mockMvcTester = mockMvcTester.withHttpMessageConverters(converters);
|
ServerBuilder serverBuilder = HttpMessageConverters.forServer();
|
||||||
|
customizersProvider.orderedStream().forEach((customizer) -> customizer.customize(serverBuilder));
|
||||||
|
mockMvcTester = mockMvcTester.withHttpMessageConverters(serverBuilder.build());
|
||||||
}
|
}
|
||||||
return mockMvcTester;
|
return mockMvcTester;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ import org.springframework.boot.autoconfigure.web.format.WebConversionService;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.context.properties.PropertyMapper;
|
import org.springframework.boot.context.properties.PropertyMapper;
|
||||||
import org.springframework.boot.convert.ApplicationConversionService;
|
import org.springframework.boot.convert.ApplicationConversionService;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
import org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer;
|
||||||
import org.springframework.boot.servlet.filter.OrderedFormContentFilter;
|
import org.springframework.boot.servlet.filter.OrderedFormContentFilter;
|
||||||
import org.springframework.boot.servlet.filter.OrderedHiddenHttpMethodFilter;
|
import org.springframework.boot.servlet.filter.OrderedHiddenHttpMethodFilter;
|
||||||
import org.springframework.boot.servlet.filter.OrderedRequestContextFilter;
|
import org.springframework.boot.servlet.filter.OrderedRequestContextFilter;
|
||||||
|
@ -78,7 +78,7 @@ import org.springframework.format.FormatterRegistry;
|
||||||
import org.springframework.format.support.FormattingConversionService;
|
import org.springframework.format.support.FormattingConversionService;
|
||||||
import org.springframework.http.CacheControl;
|
import org.springframework.http.CacheControl;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverters.ServerBuilder;
|
||||||
import org.springframework.lang.Contract;
|
import org.springframework.lang.Contract;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -200,12 +200,12 @@ public final class WebMvcAutoConfiguration {
|
||||||
|
|
||||||
private final ListableBeanFactory beanFactory;
|
private final ListableBeanFactory beanFactory;
|
||||||
|
|
||||||
private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
|
|
||||||
|
|
||||||
private final ObjectProvider<DispatcherServletPath> dispatcherServletPath;
|
private final ObjectProvider<DispatcherServletPath> dispatcherServletPath;
|
||||||
|
|
||||||
private final ObjectProvider<ServletRegistrationBean<?>> servletRegistrations;
|
private final ObjectProvider<ServletRegistrationBean<?>> servletRegistrations;
|
||||||
|
|
||||||
|
private final ObjectProvider<ServerHttpMessageConvertersCustomizer> httpMessageConvertersCustomizerProvider;
|
||||||
|
|
||||||
private final @Nullable ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
|
private final @Nullable ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
|
||||||
|
|
||||||
private @Nullable ServletContext servletContext;
|
private @Nullable ServletContext servletContext;
|
||||||
|
@ -217,7 +217,8 @@ public final class WebMvcAutoConfiguration {
|
||||||
private final ObjectProvider<ApiVersionDeprecationHandler> apiVersionDeprecationHandler;
|
private final ObjectProvider<ApiVersionDeprecationHandler> apiVersionDeprecationHandler;
|
||||||
|
|
||||||
WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties,
|
WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties,
|
||||||
ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
|
ListableBeanFactory beanFactory,
|
||||||
|
ObjectProvider<ServerHttpMessageConvertersCustomizer> httpMessageConvertersCustomizerProvider,
|
||||||
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
|
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
|
||||||
ObjectProvider<DispatcherServletPath> dispatcherServletPath,
|
ObjectProvider<DispatcherServletPath> dispatcherServletPath,
|
||||||
ObjectProvider<ServletRegistrationBean<?>> servletRegistrations,
|
ObjectProvider<ServletRegistrationBean<?>> servletRegistrations,
|
||||||
|
@ -227,7 +228,7 @@ public final class WebMvcAutoConfiguration {
|
||||||
this.resourceProperties = webProperties.getResources();
|
this.resourceProperties = webProperties.getResources();
|
||||||
this.mvcProperties = mvcProperties;
|
this.mvcProperties = mvcProperties;
|
||||||
this.beanFactory = beanFactory;
|
this.beanFactory = beanFactory;
|
||||||
this.messageConvertersProvider = messageConvertersProvider;
|
this.httpMessageConvertersCustomizerProvider = httpMessageConvertersCustomizerProvider;
|
||||||
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
|
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
|
||||||
this.dispatcherServletPath = dispatcherServletPath;
|
this.dispatcherServletPath = dispatcherServletPath;
|
||||||
this.servletRegistrations = servletRegistrations;
|
this.servletRegistrations = servletRegistrations;
|
||||||
|
@ -242,10 +243,8 @@ public final class WebMvcAutoConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("removal")
|
public void configureMessageConverters(ServerBuilder builder) {
|
||||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
this.httpMessageConvertersCustomizerProvider.forEach((customizer) -> customizer.customize(builder));
|
||||||
this.messageConvertersProvider
|
|
||||||
.ifAvailable((customConverters) -> converters.addAll(customConverters.getConverters()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -58,7 +58,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Role;
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverters.ServerBuilder;
|
||||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
@ -174,13 +174,12 @@ public class WebMvcEndpointManagementContextConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("removal")
|
public void configureMessageConverters(ServerBuilder builder) {
|
||||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
builder.configureMessageConverters((converter) -> {
|
||||||
for (HttpMessageConverter<?> converter : converters) {
|
|
||||||
if (converter instanceof JacksonJsonHttpMessageConverter jacksonJsonHttpMessageConverter) {
|
if (converter instanceof JacksonJsonHttpMessageConverter jacksonJsonHttpMessageConverter) {
|
||||||
configure(jacksonJsonHttpMessageConverter);
|
configure(jacksonJsonHttpMessageConverter);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configure(JacksonJsonHttpMessageConverter converter) {
|
private void configure(JacksonJsonHttpMessageConverter converter) {
|
||||||
|
|
|
@ -46,7 +46,6 @@ import org.springframework.aop.support.AopUtils;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
|
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters;
|
|
||||||
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
|
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
|
||||||
import org.springframework.boot.servlet.filter.OrderedFormContentFilter;
|
import org.springframework.boot.servlet.filter.OrderedFormContentFilter;
|
||||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||||
|
@ -185,8 +184,7 @@ class WebMvcAutoConfigurationTests {
|
||||||
void handlerAdaptersCreated() {
|
void handlerAdaptersCreated() {
|
||||||
this.contextRunner.run((context) -> {
|
this.contextRunner.run((context) -> {
|
||||||
assertThat(context).getBeans(HandlerAdapter.class).hasSize(4);
|
assertThat(context).getBeans(HandlerAdapter.class).hasSize(4);
|
||||||
assertThat(context.getBean(RequestMappingHandlerAdapter.class).getMessageConverters()).isNotEmpty()
|
assertThat(context.getBean(RequestMappingHandlerAdapter.class).getMessageConverters()).isNotEmpty();
|
||||||
.isEqualTo(context.getBean(HttpMessageConverters.class).getConverters());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue