`WebClient` with default codecs drops `ProblemDetail` extension members
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
- #37507 de @zsewasdsdsd — cerrado sin fusionar
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 70/100
Línea de trabajo
La brecha está en JacksonJsonDecoder dentro de org.springframework.http.codec.json, que, a diferencia de JacksonJsonEncoder, nunca registra ProblemDetailJacksonMixin ni en el constructor por defecto ni en el constructor que recibe un JsonMapper.Builder. Empieza comparando ambas clases lado a lado; luego revisa los tests de codec existentes para la decodificación de ProblemDetail para ver dónde debería ir un test espejo para el decoder. Se considera terminado cuando un WebClient construido con los codecs por defecto conserva los miembros de extensión en getProperties(), reproducido con el ejemplo en noojung/webclient-problemdetail-mixin-repro. Ten en cuenta que ya se abrió un PR (#37507) que se cerró sin fusionar, así que revisa el hilo antes de duplicarlo.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Overview
While checking that RestClient and WebClient decode ProblemDetail responses correctly, I noticed that a WebClient created with the default codecs (WebClient.create() or WebClient.builder()) drops RFC 9457 extension members: getProperties() returns null, while the standard members are decoded correctly.
This worked with Spring Framework 6.2 (Spring Boot 3.5), so it looks like a regression introduced with the Jackson 3 codecs.
Versions tested
- Spring Framework 7.0.9 (Spring Boot 4.1.1, Jackson 3): extension members are lost
- Spring Framework 6.2.11 (Spring Boot 3.5.6, Jackson 2): works as expected
Reproducer
With the sample server running on port 8080, GET /orders/42 returns HTTP 404 with Content-Type: application/problem+json and the following body:
{
"type": "https://example.com/problems/order-not-found",
"title": "Order Not Found",
"status": 404,
"detail": "Order 42 does not exist",
"instance": "/orders/42",
"errorCode": "ORDER_NOT_FOUND",
"orderId": 42
}
The extension members are lost when decoding the response:
WebClient webClient = WebClient.create("http://localhost:8080");
// Also reproduces with:
// WebClient.builder().baseUrl("http://localhost:8080").build();
WebClientResponseException.NotFound exception = assertThrows(
WebClientResponseException.NotFound.class,
() -> webClient.get()
.uri("/orders/42")
.retrieve()
.bodyToMono(Order.class)
.block());
ProblemDetail problemDetail = exception.getResponseBodyAs(ProblemDetail.class);
assertThat(problemDetail).isNotNull();
assertThat(problemDetail.getProperties())
.containsEntry("errorCode", "ORDER_NOT_FOUND")
.containsEntry("orderId", 42);
// 6.2.11: passes
// 7.0.9: fails because getProperties() returns null
A complete sample (Spring MVC server + WebClient/RestClient tests) is available here: https://github.com/noojung/webclient-problemdetail-mixin-repro
Running ./gradlew test starts the server automatically and fails webClientCreateShouldPreserveProblemDetailProperties and webClientBuilderShouldPreserveProblemDetailProperties.
For comparison, RestClient.create() and the WebClient.Builder auto-configured by Spring Boot both keep the extension members, since JacksonJsonHttpMessageConverter registers the mixin and Boot configures the codecs with a JsonMapper that has it (spring-projects/spring-boot#47298).
Analysis
JacksonJsonEncoder and JacksonJsonHttpMessageConverter register ProblemDetailJacksonMixin in their default and JsonMapper.Builder-based constructors, but JacksonJsonDecoder does not. Since FAIL_ON_UNKNOWN_PROPERTIES is disabled by default in Jackson 3, the extension members are ignored without any error.
With Jackson 2, the default Jackson2JsonDecoder created its mapper through Jackson2ObjectMapperBuilder, which registers the mixin.
Workaround
WebClient webClient = WebClient.builder()
.codecs(configurer -> configurer.defaultCodecs().jacksonJsonDecoder(new JacksonJsonDecoder(
JsonMapper.builder().addMixIn(ProblemDetail.class, ProblemDetailJacksonMixin.class))))
.build();
Related issues
- #35597
- spring-projects/spring-boot#47298
Would registering ProblemDetailJacksonMixin in the default and JsonMapper.Builder-based constructors of JacksonJsonDecoder, the same way as in JacksonJsonEncoder, be the right fix? If so, I would be happy to submit a pull request.
- Lenguaje dominante
- Java
- Estrellas
- 60.3k
- Forks
- 38.7k
- Merge medio
- 1 d 8 h
- PR fusionados (30 d)
- 36
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de spring-projects/spring-framework
-
`YamlProcessor.getFlattenedMap` with `includeEmpty` returns a `null` key for an empty root mappingQuizá libre de nuevo @erfannvb la tomó hace 7 días y no hay ningún pull request abierto. Abiertostatus: waiting-for-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
spring-projects/spring-framework#37522 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
StandardApiVersionDeprecationHandler generates nonconforming Sunset HTTP datesQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abiertostatus: waiting-for-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
spring-projects/spring-framework#37486 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
-
FastByteArrayOutputStream input stream rejects valid skip(long) argumentsQuizá libre de nuevo @hickey-ai la tomó hace 10 días y no hay ningún pull request abierto. Abiertostatus: waiting-for-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
spring-projects/spring-framework#37471 · 6 comentarios ·
Los mantenedores suelen responder en 1 día
-
LinkedCaseInsensitiveMap.keySet().remove returns false after removing a null-valued entryQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abiertostatus: waiting-for-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
spring-projects/spring-framework#37470 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
ServerSentEventHttpMessageReader does not recognize data fields without a colonQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abiertoin: web status: waiting-for-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
spring-projects/spring-framework#37461 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de spring-projects/spring-framework
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
apache/rocketmq-dashboard#7361 ·
Los mantenedores suelen responder en 3 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Los mantenedores suelen responder en 1 día
-
Type/Improvement
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
ballerina-platform/static-code-analysis-tool#140 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
atomityhq/blog-cms#82 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
ready-for-triage triaged
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
RedHatInsights/notifications-backend#5080 · 2 comentarios ·
Los mantenedores suelen responder en 1 día