`WebClient` with default codecs drops `ProblemDetail` extension members
维护者通常 1 天内回复
还没有人认领这个 Issue。
- #37507 来自 @zsewasdsdsd —— 已关闭,未合并
评估
调研方向
问题出在 org.springframework.http.codec.json 下的 JacksonJsonDecoder:与 JacksonJsonEncoder 不同,它在默认构造函数和接收 JsonMapper.Builder 的构造函数中都没有注册 ProblemDetailJacksonMixin。先并排比较这两个类,然后查看现有的 ProblemDetail 解码编解码器测试,以确定解码器的镜像测试应放在哪里。完成标准是:使用默认编解码器构建的 WebClient 能在 getProperties() 中保留扩展成员,并用 noojung/webclient-problemdetail-mixin-repro 中的示例复现。注意,PR(#37507)已经开过但未合并即被关闭,因此在重复提交之前请先查看该讨论串。
由索引模型根据 Issue 内容生成。
描述
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.
- 主要语言
- Java
- 星标
- 60.3k
- 派生
- 38.7k
- 平均合并
- 1 天 9 小时
- 30 天内合并 PR
- 34
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
spring-projects/spring-framework 的其他 Issue
-
`YamlProcessor.getFlattenedMap` with `includeEmpty` returns a `null` key for an empty root mapping可能重新可做 @erfannvb 于 7 天前认领,目前没有进行中的 PR。 未关闭status: waiting-for-triage
难度 2/5 1-3 小时 新手友好度 78/100
spring-projects/spring-framework#37522 · 1 条评论 ·
维护者通常 1 天内回复
-
StandardApiVersionDeprecationHandler generates nonconforming Sunset HTTP dates可能重新可做 关联的 PR 已关闭且未合并。 未关闭status: waiting-for-triage
难度 2/5 1-3 小时 新手友好度 68/100
spring-projects/spring-framework#37486 · 4 条评论 ·
维护者通常 1 天内回复
-
FastByteArrayOutputStream input stream rejects valid skip(long) arguments可能重新可做 @hickey-ai 于 10 天前认领,目前没有进行中的 PR。 未关闭status: waiting-for-triage
难度 2/5 1-3 小时 新手友好度 82/100
spring-projects/spring-framework#37471 · 6 条评论 ·
维护者通常 1 天内回复
-
LinkedCaseInsensitiveMap.keySet().remove returns false after removing a null-valued entry可能重新可做 关联的 PR 已关闭且未合并。 未关闭status: waiting-for-triage
难度 2/5 1-3 小时 新手友好度 78/100
spring-projects/spring-framework#37470 · 3 条评论 ·
维护者通常 1 天内回复
-
ServerSentEventHttpMessageReader does not recognize data fields without a colon可能重新可做 关联的 PR 已关闭且未合并。 未关闭in: web status: waiting-for-triage
难度 2/5 1-3 小时 新手友好度 76/100
spring-projects/spring-framework#37461 · 1 条评论 ·
维护者通常 1 天内回复
查看 spring-projects/spring-framework 的全部 Issue
相似的 Issue
-
:Search Relevance/Vectors >test-failure needs:risk Team:Search Relevance
难度 2/5 1-3 小时 新手友好度 61/100
elastic/elasticsearch#163668 · 3 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
agent:working bug follow-up lane:auto
难度 2/5 1-3 小时 新手友好度 72/100
Sanne/incus-spawn#1765 · 2 条评论 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
Mend: dependency security vulnerability untriaged
难度 2/5 1-3 小时 新手友好度 63/100
opensearch-project/data-prepper#7219 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 83/100
维护者通常 1 天内回复