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 → XNameFielddecapitalizeXNameField로 정규화해 양쪽 속성명이 같은 값으로 모입니다. 일반적인 fluent setter(settlementDate(...) 등 두 번째 글자가 소문자인 케이스)는 SettlementDatesettlementDate로 결과가 바뀌지 않아 회귀 없음.

회귀 테스트

기존 fluent setter 검증 테스트 _1799 패턴을 그대로 복사해 processor/src/test/java/org/mapstruct/ap/test/bugs/_4000/에 4개 파일을 추가했습니다.

  • Sourceprivate String xNameField + getXNameField()
  • Target — Lombok 스타일 Builder.xNameField(...) fluent setter
  • Issue4000Mapper@Mapper 인터페이스
  • Issue4000Test@ProcessorTest로 매핑 결과 검증

로컬에서 builder / superbuilder / _1799 영역 82개 테스트 모두 통과. NEXT_RELEASE_CHANGELOG.md### Bugs 섹션에도 항목 추가.

관련 자료