Skip to content

NullValuePropertyMappingStrategy.IGNORE does not ignore target collection even when source one is null (only when collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE) #3104

@mmalygin

Description

@mmalygin

Expected behavior

When NullValuePropertyMappingStrategy.IGNORE is used, mapstruct must ignore updating a target field when a source field is null. This should work for all fields including collections ones.

Actual behavior

My setup is the following:

main entity object:

import java.util.List;
import lombok.Data;

@Data
public class MainEntity {
    private String name;
    private List<ChildEntity> childList;
}

child entity object:

import lombok.Data;

@Data
public class ChildEntity {
    private String myField;
}

main dto object:

import java.util.List;
import lombok.Data;

@Data
public class MainDto {
	private String name;
	private List<ChildDto> childList;
}

child dto object:

import lombok.Data;

@Data
public class ChildDto {
	private String myField;
}

My mapper is

@Mapper(collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE)
public interface EntityMapper {
	@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
	void update(@MappingTarget MainEntity target, MainDto source);
}

Actual generated code is

public class EntityMapperImpl implements EntityMapper {

    @Override
    public void update(MainEntity target, MainDto source) {
        if ( source == null ) {
            return;
        }

        if ( source.getName() != null ) {
            target.setName( source.getName() );
        }
        target.setChildList( childDtoListToChildEntityList( source.getChildList() ) );
    }

    protected ChildEntity childDtoToChildEntity(ChildDto childDto) {
        if ( childDto == null ) {
            return null;
        }

        ChildEntity childEntity = new ChildEntity();

        childEntity.setMyField( childDto.getMyField() );

        return childEntity;
    }

    protected List<ChildEntity> childDtoListToChildEntityList(List<ChildDto> list) {
        if ( list == null ) {
            return null;
        }

        List<ChildEntity> list1 = new ArrayList<ChildEntity>( list.size() );
        for ( ChildDto childDto : list ) {
            list1.add( childDtoToChildEntity( childDto ) );
        }

        return list1;
    }
}

As you can see childList in target is set to value returned from childDtoListToChildEntityList function which always returns null when the source list is null. So the target childList will be null. This is incorrect, the list must remain unchanged.

Note that this issue is only actual when collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE

Steps to reproduce the problem

Use the above setup.

MapStruct Version

1.5.3.Final

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions