MapStruct · open · 2026-06-21
PR #4074 — #4000: Fix property name resolution for fluent setters whose second character is upper case
MapStruct가 Lombok @Builder 스타일 fluent setter의 속성명을 JavaBean accessor와 다르게 해석해, 두 번째 글자가 대문자인 필드가 매핑에서 조용히 누락되던 버그를 DefaultAccessorNamingStrategy 한 분기 수정으로 해결했습니다.
증상
소스에 private String xNameField가 있고 타겟에 Lombok @Builder가 자동 생성하는 Builder.xNameField(...) fluent setter가 있는 단순 매핑에서, 해당 필드가 결과 코드에 아예 누락됐습니다. @Mapping(target = "xNameField", source = "xNameField")를 명시하면 오히려 did you mean "XNameField"?
오류가 떴고, source = "XNameField"로 대문자를 박으면 정상 동작하는 모순 상태.
원인
DefaultAccessorNamingStrategy#getPropertyName(...)은 메서드 종류에 따라 속성명을 두 갈래로 추출합니다.
- JavaBean accessor (
getXNameField()등):methodName.substring(3)→IntrospectorUtils.decapitalize(...).XNameField는 두 글자 모두 대문자라 그대로 유지 → 속성명XNameField. - fluent setter (
xNameField(...)) 분기: 메서드명을 raw 그대로 반환 → 속성명xNameField.
결과적으로 같은 필드인데도 소스 쪽 속성명(XNameField)과 타겟 builder 쪽 속성명(xNameField)이 어긋나 자동 매칭이 실패하고 필드가 silent하게 누락됐습니다.
수정
fluent setter 분기에서도 JavaBean 쪽과 같은 decapitalize 규칙을 적용. xNameField → 첫 글자 capitalize → XNameField → decapitalize → XNameField로 정규화해 양쪽 속성명이 같은 값으로 모입니다. 일반적인 fluent setter(settlementDate(...) 등 두 번째 글자가 소문자인 케이스)는 SettlementDate → settlementDate로 결과가 바뀌지 않아 회귀 없음.
회귀 테스트
기존 fluent setter 검증 테스트 _1799 패턴을 그대로 복사해 processor/src/test/java/org/mapstruct/ap/test/bugs/_4000/에 4개 파일을 추가했습니다.
Source—private String xNameField+getXNameField()Target— Lombok 스타일Builder.xNameField(...)fluent setterIssue4000Mapper—@Mapper인터페이스Issue4000Test—@ProcessorTest로 매핑 결과 검증
로컬에서 builder / superbuilder / _1799 영역 82개 테스트 모두 통과. NEXT_RELEASE_CHANGELOG.md의 ### Bugs 섹션에도 항목 추가.