Skip to content

#4060 Report compilation error for SET_TO_DEFAULT without accessible no-args constructor#4061

Merged
hduelme merged 2 commits into
mapstruct:mainfrom
seonwooj0810:fix/issue-4060-set-to-default-constructor-check
Jun 7, 2026
Merged

#4060 Report compilation error for SET_TO_DEFAULT without accessible no-args constructor#4061
hduelme merged 2 commits into
mapstruct:mainfrom
seonwooj0810:fix/issue-4060-set-to-default-constructor-check

Conversation

@seonwooj0810

Copy link
Copy Markdown
Contributor

Fixes #4060

Problem

When updating an existing bean with NullValuePropertyMappingStrategy.SET_TO_DEFAULT, MapStruct resets a null source property by creating a fresh default instance via the parameterless constructor (new Target()). For target property types that do not expose an accessible no-args constructor (e.g. LocalDate, LocalDateTime, Instant, BigDecimal, BigInteger, Comparable), this generated uncompilable code such as:

target.setLocalDate( new LocalDate() );

As requested in the issue, MapStruct should report a compilation error during annotation processing rather than emitting code that fails to compile.

Change

  • Type#hasAccessibleParameterlessConstructor() — new helper that returns true only when new Type() would actually compile (an implicit default constructor, or a declared non-private no-args constructor). Unlike the existing hasAccessibleConstructor(), it returns false for types that only expose parameterized constructors (e.g. BigDecimal).
  • PropertyMapping#assignToPlainViaSetter(...) — for the SET_TO_DEFAULT case, when the default instance would be built through a parameterless constructor (no factory/builder) and the target type lacks an accessible one, report GENERAL_NO_SUITABLE_CONSTRUCTOR (the message referenced in the issue). Types that are initialized differently — those with an implementation type (collections/maps), arrays, Optional, or a sensible default — are intentionally excluded.

Test evidence

Added org.mapstruct.ap.test.bugs._4060.Issue4060Test:

  • setToDefaultWithoutParameterlessConstructorFails — asserts the expected compilation errors for LocalDate, BigDecimal and Comparable<String>.
  • setToDefaultWithParameterlessConstructorResetsToNewInstance — verifies the existing reset-to-new-instance behaviour still works for constructible types.

Local run (JDK toolchain, processor module):

  • Issue4060Test — 4 tests, 0 failures.
  • Related regression tests pass: Issue1790Test, Issue3884Test, JSpecifySafetyGuardTest, NullValuePropertyMappingTest, NullValuePropertyMappingClearTest.
  • checkstyle:check on the processor module passes.

Verification done

  1. No in-flight PR (gh pr list --search for 4060 / SET_TO_DEFAULT constructor) and no self-claim comments on the issue.
  2. Fix touches .java files only.
  3. Reproduced the bug against main (453602e): without the change the erroneous mapper compiles and emits new LocalDate(); with the change the documented compilation error is raised.
  4. No parent epic — issue is standalone and labelled bug, hack.commit.push.

…cessible no-args constructor

When NullValuePropertyMappingStrategy.SET_TO_DEFAULT resets a null source
property, MapStruct generates new Target() to create the default instance.
For target types without an accessible parameterless constructor (e.g.
LocalDate, BigDecimal, Comparable) this produced uncompilable code such as
target.setLocalDate( new LocalDate() ). Detect this during annotation
processing and raise GENERAL_NO_SUITABLE_CONSTRUCTOR instead.

@hduelme hduelme left a comment

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.

@seonwooj0810 nice implementation.
I left two comments: one regarding the error message and one suggesting a small test improvement.

Comment thread processor/src/test/java/org/mapstruct/ap/test/bugs/_4060/Issue4060Test.java Outdated
Address review feedback:
- Introduce PROPERTYMAPPING_NO_ACCESSIBLE_PARAMETERLESS_CONSTRUCTOR with a
  message that names the actual problem (no accessible parameterless
  constructor) and suggests fixes (change the
  nullValuePropertyMappingStrategy or define a defaultValue /
  defaultExpression), instead of reusing GENERAL_NO_SUITABLE_CONSTRUCTOR.
- Cover abstract class and enum target property types in
  ErroneousSetToDefaultMapper.
@hduelme

hduelme commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

@seonwooj0810 Thanks for making the adjustments, and thanks again for the contribution!

@hduelme hduelme merged commit 750ff53 into mapstruct:main Jun 7, 2026
7 of 8 checks passed
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.

Missing accessable Constrctor check for updating existing bean

2 participants