Skip to content

Fix StackOverflow when exporting POJOs with custom converters#899

Open
utafrali wants to merge 2 commits intoapache:mainfrom
utafrali:fix/issue-889-bug-pojo-export-with-custom-converter-st
Open

Fix StackOverflow when exporting POJOs with custom converters#899
utafrali wants to merge 2 commits intoapache:mainfrom
utafrali:fix/issue-889-bug-pojo-export-with-custom-converter-st

Conversation

@utafrali
Copy link
Copy Markdown
Contributor

Purpose of the pull request

Closes #889

Fixes the stack overflow error that happens when exporting POJOs with custom converters.

What's changed?

The issue was @EqualsAndHashCode trying to hash the entire object graph, including parent references. Since WriteSheetHolder has parentWriteWorkbookHolder and WriteTableHolder has parentWriteSheetHolder, these circular references caused infinite recursion during equals/hashcode generation.

Excluded those parent fields from the @EqualsAndHashCode annotation. This breaks the circular dependency without affecting the equality logic for these holders. Also added tests for the ZonedDateTime converter to make sure custom converters work properly with the fix.

Checklist

  • I have read the Contributor Guide.
  • I have written the necessary doc or comment.
  • I have added the necessary unit tests and all cases have passed.

utafrali and others added 2 commits April 17, 2026 19:26
Exclude circular reference fields from @EqualsAndHashCode to prevent infinite recursion during POJO export. Closes apache#889
Copy link
Copy Markdown
Contributor

@skytin1004 skytin1004 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@utafrali I tried ZonedDateTimeConverterTest locally with -Dmaven.test.skip=false, but it still fails with StackOverflowError.

The failing test is ZonedDateTimeConverterTest.writePojoWithZonedDateTimeAndCustomConverter.

From the stack trace, this PR removes the sheet/table parent reference cycles, but another cycle is still left:

WriteWorkbookHolder.hashCode() -> WorkbookWriteHandlerContext.hashCode() -> WriteWorkbookHolder.hashCode()

workbookWriteHandlerContext is currently excluded only from toString, not from hashCode, because the annotation is lombok.ToString.Exclude.

So the hashCode recursion is still reachable through this field.

This might be addressing the recursion symptom, but I wonder if there is a more fundamental issue in how equals/hashCode is defined for these holder/context objects.

For now, I think the priority is to make sure the test passes and the recursion path is fully removed.

Could you please check this path and rerun the test with -Dmaven.test.skip=false?

@Getter
@Setter
@EqualsAndHashCode
@EqualsAndHashCode(exclude = {"parentWriteWorkbookHolder", "hasBeenInitializedTable"})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This excludes the sheet's parent workbook holder from equals/hashCode, which makes sense. But I still see a StackOverflowError when I run the new test locally.

The remaining loop seems to be:

WriteWorkbookHolder.hashCode() -> WorkbookWriteHandlerContext.hashCode() -> WriteWorkbookHolder.hashCode()

Could you check this path too?

row.setAmount(new BigDecimal("1234.5"));
row.setCreatedAt(ZonedDateTime.of(2026, 3, 24, 15, 30, 45, 0, ZoneId.of("Asia/Shanghai")));

Assertions.assertDoesNotThrow(() -> FesodSheet.write(out, MixedMetadataRow.class)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran this test locally with -Dmaven.test.skip=false, but it still fails with StackOverflowError.

So this is a good reproducer, but the current fix does not make it pass yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]POJO Export with custom converter StackOverflow Repro

3 participants