NullValuePropertyMappingStrategy.IGNORE is ignored on final Lists
Author: domi-87Created Nov 14, 2022Updated Sep 10, 2026
Labelsbug
Expected behavior
I would expect that if "nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE" is set, the target.list.clear() is called only if source.list is not NULL. I would expect the same behavior for conditionalExpression. Again, clear() is called first and only then the conditionalExpression.
public ListHolder mapToListHolder(ListHolder target, ListHolderDTO source) {
if ( source == null ) {
return target;
}
if ( target.getStrings() != null ) {
List<String> list = source.getStrings();
if ( list != null ) {
target.getStrings().clear();
target.getStrings().addAll( list );
}
}
return target;
}Actual behavior
If the target property is a final list, clear is always called first. Regardless of whether the source property is NULL or not.
public ListHolder mapToListHolder(ListHolder target, ListHolderDTO source) {
if ( source == null ) {
return target;
}
if ( target.getStrings() != null ) {
target.getStrings().clear();
List<String> list = source.getStrings();
if ( list != null ) {
target.getStrings().addAll( list );
}
}
return target;
}Steps to reproduce the problem
import java.util.ArrayList;
import java.util.List;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import ch.epictec.etac.system.mapper.MapStructMCVE.ListHolder;
import ch.epictec.etac.system.mapper.MapStructMCVE.ListHolderDTO;
import lombok.Data;
@Mapper
public interface MapStructMCVE {
@Data
public class ListHolderDTO {
private List<String> strings;
}
@Data
public class ListHolder {
private final List<String> strings = new ArrayList<>();
}
@Mapping(target = "strings", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
ListHolder mapToListHolder(@MappingTarget ListHolder target, ListHolderDTO source);
/*
* Actual behavior
*/
// public ListHolder mapToListHolder(ListHolder target, ListHolderDTO source) {
// if ( source == null ) {
// return target;
// }
//
// if ( target.getStrings() != null ) {
// target.getStrings().clear();
// List<String> list = source.getStrings();
// if ( list != null ) {
// target.getStrings().addAll( list );
// }
// }
//
// return target;
// }
/*
* Expected behavior
*/
// public ListHolder mapToListHolder(ListHolder target, ListHolderDTO source) {
// if ( source == null ) {
// return target;
// }
//
// if ( target.getStrings() != null ) {
// List<String> list = source.getStrings();
// if ( list != null ) {
// target.getStrings().clear();
// target.getStrings().addAll( list );
// }
// }
//
// return target;
// }
}
MapStruct Version
MapStruct 1.5.3
Source: mapstruct/mapstruct