Expected behavior
MapStruct should report a compilation error during annotation processing when SET_TO_DEFAULT requires instantiation of a type that cannot be constructed through an accessible no-args constructor, rather than generating invalid code.
Maybe something like
|
GENERAL_NO_SUITABLE_CONSTRUCTOR( "%s does not have an accessible constructor." ), |
Actual behavior
When updating an existing bean with NullValuePropertyMappingStrategy.SET_TO_DEFAULT, MapStruct generates code that attempts to instantiate target property types using a no-args constructor.
However, for types that do not have an accessible no-args constructor (e.g. Comparable, LocalDate, LocalDateTime, Instant, BigDecimal, and BigInteger), MapStruct still generates instantiation code such as:
target.localDate = new LocalDate();
target.comparable = new Comparable<String>();
Steps to reproduce the problem
Example
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
@Mapper
public interface UpdateMapper {
class Target {
public Comparable<String> comparable;
public LocalDate localDate;
public LocalDateTime localDateTime;
public Instant instant;
public BigDecimal bigDecimal;
public BigInteger bigInteger;
}
class Source {
public Comparable<String> comparable;
public LocalDate localDate;
public LocalDateTime localDateTime;
public Instant instant;
public BigDecimal bigDecimal;
public BigInteger bigInteger;
}
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
void update(@MappingTarget Target target, Source from);
}
generates
import javax.annotation.processing.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2026-06-02T22:45:28+0200",
comments = "version: 1.6.3, compiler: javac, environment: Java 21.0.5 (Eclipse Adoptium)"
)
public class UpdateMapperImpl implements UpdateMapper {
@Override
public void update(Target target, Source from) {
if ( from == null ) {
return;
}
if ( from.comparable != null ) {
target.comparable = from.comparable;
}
else {
target.comparable = new Comparable<String>();
}
if ( from.localDate != null ) {
target.localDate = from.localDate;
}
else {
target.localDate = new LocalDate();
}
if ( from.localDateTime != null ) {
target.localDateTime = from.localDateTime;
}
else {
target.localDateTime = new LocalDateTime();
}
if ( from.instant != null ) {
target.instant = from.instant;
}
else {
target.instant = new Instant();
}
if ( from.bigDecimal != null ) {
target.bigDecimal = from.bigDecimal;
}
else {
target.bigDecimal = new BigDecimal();
}
if ( from.bigInteger != null ) {
target.bigInteger = from.bigInteger;
}
else {
target.bigInteger = new BigInteger();
}
}
}
None of the targets has an accessible constructor.
MapStruct Version
MapStruct 1.6.3
Expected behavior
MapStruct should report a compilation error during annotation processing when
SET_TO_DEFAULTrequires instantiation of a type that cannot be constructed through an accessible no-args constructor, rather than generating invalid code.Maybe something like
mapstruct/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java
Line 167 in 453602e
Actual behavior
When updating an existing bean with
NullValuePropertyMappingStrategy.SET_TO_DEFAULT, MapStruct generates code that attempts to instantiate target property types using a no-args constructor.However, for types that do not have an accessible no-args constructor (e.g.
Comparable,LocalDate,LocalDateTime,Instant,BigDecimal, andBigInteger), MapStruct still generates instantiation code such as:Steps to reproduce the problem
Example
generates
None of the targets has an accessible constructor.
MapStruct Version
MapStruct 1.6.3