Avoid uncompilable output when migrating JobBuilderFactory/StepBuilderFactory#1036
Merged
Conversation
…lderFactory` When a class injects `JobBuilderFactory` or `StepBuilderFactory` via a multi-arg constructor or exposes the factory through accessor methods, the existing recipe deleted the field while leaving the constructor body assignment, accessor methods, and (for `StepBuilderFactory`) the constructor parameter dangling. The result was uncompilable code. Three changes: 1. Before deleting a `JobBuilderFactory`/`StepBuilderFactory` field, both visitors now scan the class for type-aware references to the field outside the methods they rewrite (constructors and methods containing `.get(...)`). If references exist (getters, setters, helper methods), the field is preserved and constructor parameter removal is also skipped so the field, parameter, and body assignment stay wired up. 2. When a `JobBuilderFactory`/`StepBuilderFactory` parameter is dropped from a method, any matching `this.<field> = <removedParam>;` body assignment is removed in lockstep rather than being left referencing the removed parameter. 3. `MigrateStepBuilderFactory.AddJobRepositoryVisitor.visitMethodDeclaration` now also rewrites constructors that take a `StepBuilderFactory` parameter, mirroring the existing constructor handling in `MigrateJobBuilderFactory`. Closes #788 Closes #789
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a class injects
JobBuilderFactoryorStepBuilderFactoryvia a multi-arg constructor, or exposes the factory through accessor methods, the current recipes produce uncompilable code:The field is deleted while getters, setters, and helper methods still reference it.
MigrateJobBuilderFactoryalready has a constructor carve-out that drops theJobBuilderFactoryparameter, but the matchingthis.<field> = <param>;body assignment is left behind — orphaning both sides after field deletion.MigrateStepBuilderFactoryhas no constructor carve-out, so theStepBuilderFactoryparameter survives even when the rest of the file has been migrated, leaving a reference to a class that no longer exists in Spring Batch 5.This affects classes that follow the standard Spring constructor-injection pattern — exactly the shape called out in Deprecated StepBuilderFactory/JobBuilderFactory types left alone when it's not used in same Java file #788 and Migration to Spring Batch 5.2 : StepBuilderFactory/JobBuilderFactory partially migrated when used as constructor arguments #789.
Changes
Field deletion is now usage-aware (both recipes). Before deleting a
JobBuilderFactory/StepBuilderFactoryfield, each visitor scans the class for type-aware references to the field outside the methods it will rewrite (constructors and methods containing.get(...)). The check usesJ.Identifier.getFieldType()and confirms the declaring type matches the enclosing class, so local variables and parameters that happen to share the field's simple name are not false positives. If outside references exist (getters, setters, helper methods), the field is preserved and constructor parameter removal is skipped — the field, parameter, and body assignment remain wired up for the developer to clean up.Constructor body cleanup moves in lockstep with parameter removal (both recipes). When a
JobBuilderFactory/StepBuilderFactoryparameter is dropped from a method declaration, any matchingthis.<field> = <removedParam>;body assignment is removed rather than being left referencing a parameter that no longer exists.MigrateStepBuilderFactorygets a constructor carve-out.AddJobRepositoryVisitor.visitMethodDeclarationnow rewrites constructors that take aStepBuilderFactoryparameter, mirroring the existing behavior inMigrateJobBuilderFactory. Gated by the field-preservation guard above.Tests
Five new tests across
MigrateJobBuilderFactoryTestandMigrateStepBuilderFactoryTest:Field preserved when getters/setters reference it; the
.get(...)chain still rewrites.Constructor body assignment removed when its parameter is removed (no accessors present).
StepBuilderFactoryconstructor parameter removed and body assignment cleaned up.StepBuilderFactoryfield preserved when accessor methods reference it.Local variable shadowing the field's simple name does not trigger preservation — the tightened type-aware check ignores it.
Closes Deprecated StepBuilderFactory/JobBuilderFactory types left alone when it's not used in same Java file #788
Closes Migration to Spring Batch 5.2 : StepBuilderFactory/JobBuilderFactory partially migrated when used as constructor arguments #789