-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Expected behavior
When mapping from a DTO back to an entity using @InheritInverseConfiguration, any field marked with @mapping(ignore = true) such as client, name, or address, should stay null. This should also hold when the source fields are nested and explicitly referenced with 'source.', for example source.client.id or source.address.city. The mapper should not create any objects or set values for these ignored fields. In MapStruct 1.3.0.Final, ignored fields were respected and left untouched, even with nested source paths.
Actual behavior
In MapStruct 1.4.2.Final and later, using @InheritInverseConfiguration with nested source fields prefixed by 'source.' results in completely ignoring the ignore = true annotations. The generated mapper creates intermediate objects for these ignored fields and sets some of their values, even though the fields were explicitly marked as ignored. As a result, client and address are no longer null after mapping. One observation is that removing the 'source.' prefix, such as using 'client.id' instead of 'source.client.id', seems to solve the issue, but this may not reflect the intended behavior of the mapper.
Steps to reproduce the problem
Mapper:
@Mapper
public interface CommandeMapper {
CommandeMapper INSTANCE = Mappers.getMapper(CommandeMapper.class);
@Mapping(target = "clientId", source = "source.client.id")
@Mapping(target = "nom", source = "source.name")
@Mapping(target = "ville", source = "source.address.city")
CommandeDto toDto(Commande source);
@InheritInverseConfiguration
@Mapping(target = "client", ignore = true)
@Mapping(target = "name", ignore = true)
@Mapping(target = "address", ignore = true)
Commande toEntity(CommandeDto dto);
}
Mapper Implementation:
@generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2026-02-17T09:06:33+0100",
comments = "version: 1.7.0.Beta1, compiler: javac, environment: Java 21.0.1 (Eclipse Adoptium)"
)
public class CommandeMapperImpl implements CommandeMapper {
@Override
public CommandeDto toDto(Commande source) {
if ( source == null ) {
return null;
}
CommandeDto commandeDto = new CommandeDto();
commandeDto.setClientId( sourceClientId( source ) );
commandeDto.setNom( source.getName() );
commandeDto.setVille( sourceAddressCity( source ) );
commandeDto.setId( source.getId() );
return commandeDto;
}
@Override
public Commande toEntity(CommandeDto dto) {
if ( dto == null ) {
return null;
}
Commande commande = new Commande();
commande.setClient( commandeDtoToClient( dto ) );
commande.setAddress( commandeDtoToAddress( dto ) );
commande.setId( dto.getId() );
return commande;
}
private Long sourceClientId(Commande commande) {
Client client = commande.getClient();
if ( client == null ) {
return null;
}
return client.getId();
}
private String sourceAddressCity(Commande commande) {
Address address = commande.getAddress();
if ( address == null ) {
return null;
}
return address.getCity();
}
protected Client commandeDtoToClient(CommandeDto commandeDto) {
if ( commandeDto == null ) {
return null;
}
Client client = new Client();
client.setId( commandeDto.getClientId() );
return client;
}
protected Address commandeDtoToAddress(CommandeDto commandeDto) {
if ( commandeDto == null ) {
return null;
}
Address address = new Address();
address.setCity( commandeDto.getVille() );
return address;
}
}
MapStruct Version
MapStruct 1.4.2.Final and later