Feedback from a 152k-line Java 8 to 25 migration: the silent behavioural changes that cost the most, and which have no recipe
维护者通常 1 天内回复
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 32/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 领域
- build-system, tooling
调研方向
首先阅读四个迁移缺口,以及 rewrite-migrate-java、rewrite-spring、rewrite-hibernate 和 rewrite-static-analysis 中现有的 META-INF/rewrite/*.yml 文件。明确应首先拆分出哪一项;完成意味着针对所选迁移案例,有一个已达成共识且范围明确的 recipe 或 diagnostic,并且具备覆盖能力。
由索引模型根据 Issue 内容生成。
描述
Context
I ran a controlled A/B experiment migrating a 152,000-line application (Spring 3.0.5 to 6.2,
Hibernate 3.5.5 to 6.6, Java 8 to 25, JUnit 4/3 to 5) twice: once using OpenRewrite heavily, once
with OpenRewrite forbidden and everything done by hand. Both arms succeeded and both landed at the
same place.
The useful finding for you is where the time actually went, because it was not where I
expected. Recipes handled the mechanical work well - the two arms converged to within 1% on
namespace rewriting (396 vs 392 jakarta imports in .java, 201 vs 202 in AspectJ ITDs). The
dominant cost in both arms was diagnosing silent behavioural change: things that compile
fine, produce no warning, and fail at runtime.
Below are the four that cost the most. Each is verified to have no recipe and no detection in
rewrite-migrate-java 3.42.1, rewrite-spring 6.37.1, rewrite-hibernate 2.25.0 or
rewrite-testing-frameworks 3.44.0, by grepping every META-INF/rewrite/*.yml. I am filing them
together because they are one theme; happy to split them, and happy to contribute any of them.
I have opened the Spring 6 trailing-slash case separately as
- openrewrite/rewrite-spring#1142, since that one already has a recipe that is simply unreachable.
1. Surefire 3 silently ignores forkMode — 158 failing tests from one cause
forkMode was removed in maven-surefire-plugin 3.0.0-M8. It is not an error and produces no
warning; the parameter is ignored. A suite relying on forkMode=always for isolation then leaks
static state between test classes.
This was the single largest failure cluster of the entire migration - 158 tests - and it
presented as a mass application regression rather than as a build-configuration change.
- This was requested in openrewrite/rewrite#2644 and closed with:
Closing - this recipe request for Surefire plugin migration would belong in
rewrite-static-analysisorrewrite-migrate-javarather than the corerewriterepo.
Consider filing there if still desired.
So: filing it here as invited. The mapping is documented and mechanical -
forkMode=always to reuseForks=false with forkCount=1, forkMode=once to
reuseForks=true, forkMode=never to forkCount=0. It matters much more now than in 2023,
because the JUnit 5 recipes bump surefire to 3.x, so the migration itself introduces the
breakage.
2. GenerationType.AUTO changes meaning between Hibernate 3/4 and 5+
Under Hibernate 3 with a MySQL or HSQLDB dialect, AUTO meant a native identity column. From
Hibernate 5 it prefers a sequence or table generator, which defers the INSERT past
persist(). Code that reads the generated identifier straight after persist() breaks, and
the failures point at the application rather than at the ORM.
No recipe changes it (GenerationType appears only inside an unrelated example). Both arms
independently hand-edited the same 19 entities to GenerationType.IDENTITY.
Belongs in rewrite-hibernate, as part of the MigrateToHibernate5x/6x chain: rewrite AUTO to
IDENTITY when a MySQL/HSQLDB-family dialect is configured, or - more conservatively - mark every
@GeneratedValue(strategy = AUTO) for review.
3. @ModelAttribute parameters became data-bound from URI template variables
Since Spring 3.1, URI template variables are bound onto @ModelAttribute arguments. On an
entity-backed @ModelAttribute this silently overwrites the identifier from the path, and
Hibernate then rejects the update ("identifier of an instance was altered"). The fix is
@ModelAttribute(binding = false) or an @InitBinder exclusion.
86 parameters needed it here. No recipe addresses it. Belongs in rewrite-spring.
4. No AspectJ support, and no warning that files are being skipped
OpenRewrite has no .aj parser, so AspectJ inter-type declarations are invisible to every
recipe. I could not find an existing issue for this - ".aj" parser and inter-type declaration
both return zero results across the org.
Concretely: 197 .aj files, of which 47 contained 201 javax.* import lines that every
jakarta recipe silently left untouched, and 72 were test ITDs that declare @RunWith,
@ContextConfiguration and the @Test methods themselves. The consequence was decisive - the
OpenRewrite arm abandoned the JUnit 5 objective entirely because the declarations it needed to
change were unreachable, while the hand-editing arm completed it across 86 files.
A full AspectJ parser is obviously a large ask and I am not asking for it. But detecting .aj
files in the source set and reporting "N files are outside the reach of every recipe" is small,
and would convert a silent and misleading success into a known gap. As it stands rewrite:run
reports success on a project where a substantial share of the relevant declarations were never
examined.
Why I think this is worth your time
Where recipes applied, they were clearly better than non-deterministic LLM inference work: faster, more consistent, and they
produced a reviewable diff. The reason the recipe-using experiment did not win overall is that the
mechanical share of a fifteen-year framework migration is smaller than it looks, and none of the
four items above are covered. Items 1 and 2 in particular are narrow, mechanical, and would have
removed the two largest failure clusters I hit.
- 主要语言
- Java
- 星标
- 160
- 派生
- 133
- 平均合并
- 5 小时 51 分钟
- 30 天内合并 PR
- 86
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
openrewrite/rewrite-migrate-java 的其他 Issue
-
good first issue
难度 4/5 3-5 天 新手友好度 30/100
openrewrite/rewrite-migrate-java#1330 · 2 条评论 ·
维护者通常 1 天内回复
-
bug
难度 3/5 1-2 天 新手友好度 72/100
openrewrite/rewrite-migrate-java#1319 ·
维护者通常 1 天内回复
-
bug
难度 3/5 1-2 天 新手友好度 55/100
openrewrite/rewrite-migrate-java#1314 ·
维护者通常 1 天内回复
-
bug
难度 3/5 1-2 天 新手友好度 55/100
openrewrite/rewrite-migrate-java#1310 ·
维护者通常 1 天内回复
-
bug
难度 4/5 3-5 天 新手友好度 55/100
openrewrite/rewrite-migrate-java#1307 ·
维护者通常 1 天内回复
查看 openrewrite/rewrite-migrate-java 的全部 Issue
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
AllTheMods/AllTheModium#238 ·
-
难度 2/5 1-3 小时 新手友好度 82/100
apache/stormcrawler#2264 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 77/100
commons-app/apps-android-commons#7115 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
objectionary/lints#1596 ·
维护者通常 2 天内回复