AutoParams icon indicating copy to clipboard operation
AutoParams copied to clipboard

Prevent infinite recursion in BuilderCustomizer

Open amondnet opened this issue 2 months ago • 1 comments

Summary

Fixes #278 by automatically applying RecursionGuard to BuilderCustomizer to prevent StackOverflowError when generating objects with self-referencing fields.

Problem

When using @Customization(BuilderCustomizer.class) with Lombok @Builder classes that have self-referencing fields (e.g., Category parent or Set<Category> children), the builder would enter an infinite recursion loop and throw StackOverflowError.

The issue occurred because:

  • BuilderInvoker.setProperty() calls context.resolve() for each builder property
  • For self-referencing types, this creates an infinite loop: Category → parent (Category) → parent (Category) → ...
  • The default RecursionGuard in DefaultObjectGenerator was bypassed when BuilderCustomizer was applied via @Customization

Solution

Modified BuilderCustomizer.customize() to automatically wrap the generator with RecursionGuard:

@Override
public ObjectGenerator customize(ObjectGenerator generator) {
    return new RecursionGuard().customize(invoker.customize(generator));
}

This ensures:

  • Recursion depth is limited to 1 by default
  • Self-referencing fields are set to null to break the recursion
  • No StackOverflowError occurs

Changes

  • BuilderCustomizer.java: Apply RecursionGuard automatically in customize() method
  • SpecsForBuilderCustomizer.java: Add test cases for self-referencing types:
    • Category with parent and children fields (from issue #278)
    • Node with left and right fields (binary tree structure)

Test Plan

  • [x] All existing tests pass
  • [x] New tests verify self-referencing types don't cause StackOverflowError
  • [x] Full build succeeds
  • [x] Commit message validation passes

Documentation

Updated BuilderCustomizer Javadoc to document the automatic recursion guard behavior and its implications for self-referencing types.

amondnet avatar Oct 19 '25 11:10 amondnet

Fixed the nullable annotation issues in 10578ee:

  1. Changed children parameter from @NonNull to @Nullable in both HierarchyEntity and Category
  2. Added null check before calling children.addAll() to safely handle null values

This ensures the test code properly handles cases where RecursionGuard sets the children field to null.

amondnet avatar Oct 19 '25 11:10 amondnet