Skip to content

@InheritInverseConfiguration ignores "ignore = true" for nested source fields #3997

@s10997589-lab

Description

@s10997589-lab

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions