Polish Jackson 3 support

- Improve Javadoc.

- Suppress warnings for "removal".

- Update copyright headers.

- Migrate several tests from:
  - MappingJackson2MessageConverter to JacksonJsonMessageConverter
  - Jackson2JsonEncoder to JacksonJsonEncoder
  - Jackson2JsonDecoder to JacksonJsonDecoder
  - Jackson2SmileEncoder to JacksonSmileEncoder
  - Jackson2ObjectMapperBuilder to JsonMapper and XmlMapper
  - MappingJackson2JsonView to JacksonJsonView
  - MappingJackson2HttpMessageConverter to JacksonJsonHttpMessageConverter
  - MappingJackson2XmlHttpMessageConverter to JacksonXmlHttpMessageConverter
This commit is contained in:
Sam Brannen
2025-05-14 16:55:27 +02:00
parent ea340fbe69
commit 01fea5e7ed
88 changed files with 402 additions and 346 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.core.Ordered;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.reactive.result.view.HttpMessageWriterView;
import org.springframework.web.reactive.result.view.UrlBasedViewResolver;
@@ -85,7 +85,7 @@ class ViewResolverRegistryTests {
@Test
void defaultViews() {
View view = new HttpMessageWriterView(new Jackson2JsonEncoder());
View view = new HttpMessageWriterView(new JacksonJsonEncoder());
this.registry.defaultViews(view);
assertThat(this.registry.getDefaultViews()).containsExactly(view);

View File

@@ -41,7 +41,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.MimeType;
@@ -114,7 +114,7 @@ class WebFluxConfigurationSupportTests {
assertThat(adapter).isNotNull();
List<HttpMessageReader<?>> readers = adapter.getMessageReaders();
assertThat(readers).hasSize(15);
assertThat(readers).hasSizeGreaterThanOrEqualTo(15);
ResolvableType multiValueMapType = forClassWithGenerics(MultiValueMap.class, String.class, String.class);
@@ -169,7 +169,7 @@ class WebFluxConfigurationSupportTests {
assertThat(handler.getOrder()).isEqualTo(0);
List<HttpMessageWriter<?>> writers = handler.getMessageWriters();
assertThat(writers).hasSize(15);
assertThat(writers).hasSizeGreaterThanOrEqualTo(15);
assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM);
assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);
@@ -197,7 +197,7 @@ class WebFluxConfigurationSupportTests {
assertThat(handler.getOrder()).isEqualTo(100);
List<HttpMessageWriter<?>> writers = handler.getMessageWriters();
assertThat(writers).hasSize(15);
assertThat(writers).hasSizeGreaterThanOrEqualTo(15);
assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM);
assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);
@@ -326,7 +326,7 @@ class WebFluxConfigurationSupportTests {
@Override
protected void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
registry.defaultViews(new HttpMessageWriterView(new Jackson2JsonEncoder()));
registry.defaultViews(new HttpMessageWriterView(new JacksonJsonEncoder()));
}
@Bean

View File

@@ -47,7 +47,7 @@ import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.JacksonJsonDecoder;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -343,7 +343,7 @@ class DefaultClientResponseTests {
given(mockExchangeStrategies.messageReaders()).willReturn(List.of(
new DecoderHttpMessageReader<>(new ByteArrayDecoder()),
new DecoderHttpMessageReader<>(new Jackson2JsonDecoder())));
new DecoderHttpMessageReader<>(new JacksonJsonDecoder())));
WebClientResponseException ex = defaultClientResponse.createException().block();
assertThat(ex.getResponseBodyAs(Map.class)).containsExactly(entry("name", "Jason"));
@@ -361,7 +361,7 @@ class DefaultClientResponseTests {
given(mockExchangeStrategies.messageReaders()).willReturn(List.of(
new DecoderHttpMessageReader<>(new ByteArrayDecoder()),
new DecoderHttpMessageReader<>(new Jackson2JsonDecoder())));
new DecoderHttpMessageReader<>(new JacksonJsonDecoder())));
WebClientResponseException ex = defaultClientResponse.createException().block();
assertThat(ex.getResponseBodyAs(Map.class)).isNull();

View File

@@ -143,7 +143,8 @@ public class WebClientProxyRegistryIntegrationTests {
private static class ManualListingConfig extends BaseEchoConfig {
}
private static class ManualListingRegistrar extends AbstractHttpServiceRegistrar {
static class ManualListingRegistrar extends AbstractHttpServiceRegistrar {
public ManualListingRegistrar() {
setDefaultClientType(ClientType.WEB_CLIENT);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -57,7 +57,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.JacksonJsonDecoder;
import org.springframework.http.codec.multipart.FormFieldPart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.LinkedMultiValueMap;
@@ -81,7 +81,7 @@ import static org.springframework.web.reactive.function.BodyExtractors.toMono;
class DefaultServerRequestTests {
private final List<HttpMessageReader<?>> messageReaders = Arrays.asList(
new DecoderHttpMessageReader<>(new Jackson2JsonDecoder()),
new DecoderHttpMessageReader<>(new JacksonJsonDecoder()),
new DecoderHttpMessageReader<>(StringDecoder.allMimeTypes()));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -45,7 +45,7 @@ import org.springframework.core.codec.Decoder;
import org.springframework.http.MediaType;
import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.http.codec.json.JacksonJsonDecoder;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
@@ -71,7 +71,7 @@ import static org.springframework.web.testfixture.http.server.reactive.MockServe
*/
class MessageReaderArgumentResolverTests {
private AbstractMessageReaderArgumentResolver resolver = resolver(new Jackson2JsonDecoder());
private AbstractMessageReaderArgumentResolver resolver = resolver(new JacksonJsonDecoder());
private BindingContext bindingContext;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -44,7 +44,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.ObjectUtils;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
@@ -79,7 +79,7 @@ class MessageWriterResultHandlerTests {
writerList.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
writerList.add(new ResourceHttpMessageWriter());
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new JacksonJsonEncoder()));
}
else {
writerList = Arrays.asList(writers);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -51,7 +51,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -497,7 +497,7 @@ class RequestMappingMessageConversionIntegrationTests extends AbstractRequestMap
@GetMapping("/publisher")
@SuppressWarnings("deprecation")
Publisher<ByteBuffer> getPublisher() {
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
JacksonJsonEncoder encoder = new JacksonJsonEncoder();
return encoder.encode(Mono.just(new Person("Robert")), DefaultDataBufferFactory.sharedInstance,
ResolvableType.forClass(Person.class), JSON, Collections.emptyMap()).map(DataBuffer::toByteBuffer);
}

View File

@@ -37,7 +37,7 @@ import org.springframework.http.ProblemDetail;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
@@ -76,7 +76,7 @@ class ResponseBodyResultHandlerTests {
writerList.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
writerList.add(new ResourceHttpMessageWriter());
writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
writerList.add(new EncoderHttpMessageWriter<>(new JacksonJsonEncoder()));
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
this.resultHandler = new ResponseBodyResultHandler(writerList, resolver);
}
@@ -148,11 +148,13 @@ class ResponseBodyResultHandlerTests {
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(expectedMediaType);
assertResponseBody(exchange,
"{\"type\":\"about:blank\"," +
"\"title\":\"Bad Request\"," +
"\"status\":400," +
"\"instance\":\"/path\"}");
assertResponseBody(exchange,"""
{\
"status":400,\
"instance":"\\/path",\
"title":"Bad Request",\
"type":"about:blank"\
}""");
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -27,14 +27,15 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Single;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.SerializationFeature;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
@@ -49,7 +50,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.codec.json.JacksonJsonEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.ErrorResponse;
@@ -90,7 +91,7 @@ class ResponseEntityResultHandlerTests {
new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()),
new ResourceHttpMessageWriter(),
new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()),
new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()),
new EncoderHttpMessageWriter<>(new JacksonJsonEncoder()),
new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
return new ResponseEntityResultHandler(writerList, resolver);
@@ -239,11 +240,13 @@ class ResponseEntityResultHandlerTests {
assertThat(exchange.getResponse().getHeaders().size()).isEqualTo(3);
assertThat(exchange.getResponse().getHeaders().get("foo")).containsExactly("bar");
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PROBLEM_JSON);
assertResponseBody(exchange,
"{\"type\":\"about:blank\"," +
"\"title\":\"Bad Request\"," +
"\"status\":400," +
"\"instance\":\"/path\"}");
assertResponseBody(exchange,"""
{\
"instance":"\\/path",\
"status":400,\
"title":"Bad Request",\
"type":"about:blank"\
}""");
}
@Test
@@ -258,11 +261,13 @@ class ResponseEntityResultHandlerTests {
assertThat(exchange.getResponse().getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
assertThat(exchange.getResponse().getHeaders().size()).isEqualTo(2);
assertThat(exchange.getResponse().getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PROBLEM_JSON);
assertResponseBody(exchange,
"{\"type\":\"about:blank\"," +
"\"title\":\"Bad Request\"," +
"\"status\":400," +
"\"instance\":\"/path\"}");
assertResponseBody(exchange,"""
{\
"instance":"\\/path",\
"status":400,\
"title":"Bad Request",\
"type":"about:blank"\
}""");
}
@Test
@@ -436,10 +441,9 @@ class ResponseEntityResultHandlerTests {
MediaType halFormsMediaType = MediaType.parseMediaType("application/prs.hal-forms+json");
MediaType halMediaType = MediaType.parseMediaType("application/hal+json");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
ObjectMapper objectMapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
JacksonJsonEncoder encoder = new JacksonJsonEncoder();
encoder.registerObjectMappersForType(Person.class, map -> map.put(halMediaType, objectMapper));
EncoderHttpMessageWriter<?> writer = new EncoderHttpMessageWriter<>(encoder);