ash
ash

Reputation: 61

How to ignore unmapped target properties using @InheritInverseConfiguration and unmappedTargetPolicy = ReportingPolicy.ERROR

I use MapStruct mapper to do the following things:

  1. map entity to DTO
  2. map DTO to entity for create and update operations

I set unmappedTargetPolicy = ReportingPolicy.ERROR in MapperConfig to be notified if something is not mapped.

Entity to DTO mapping maps all DTO's target fields automatically. I want to apply exactly the same set of fields in inverse mapping (DTO to entity). So it's OK to ignore unmapped target fields in this given case. I use @InheritInverseConfiguration for the inverted mapping. It works but I have to explicitly add @Mapping(target = "field1", ignore = true) to skip entity's target fields not existing in DTO.

How to avoid adding ignore mappings manually for @InheritInverseConfiguration? I can think of applying unmappedTargetPolicy = ReportingPolicy.IGNORE on mapping method level and/or @InheritInverseConfiguration level. I didn't find such possibility in MapStruct annotations.

@MapperConfig(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR,
        typeConversionPolicy = ReportingPolicy.ERROR)
public interface CommonMapperConfig {
}


@Mapper(config = CommonMapperConfig.class)
public interface AnimalMapper {

    AnimalDto getAnimal(Animal animal);

    @InheritInverseConfiguration
    @Mapping(target = "id", ignore = true)
    // todo how to avoid explicitly ignore of field?
    @Mapping(target = "field1", ignore = true)
    @Mapping(target = "field2", ignore = true)
    Animal createAnimal(AnimalDto animalDto);

    @InheritConfiguration
    void updateAnimal(AnimalDto animalDto, @MappingTarget Animal animal);

}

Update 1. I found a workaround based on an example in git https://github.com/mapstruct/mapstruct-examples/blob/master/mapstruct-suppress-unmapped/src/main/java/org/mapstruct/jpa/SourceTargetMapper.java . The trick is to use additional mapper with unmappedTargetPolicy = ReportingPolicy.IGNORE.

Interesting thing is the

@Mapper(config = CommonMapperConfig.class, uses = AnimalMapper.ChangeAnimalMapper.class)
public abstract class AnimalMapper {

    @Autowired
    ChangeAnimalMapper changeAnimalMapper;

    public abstract AnimalDto getAnimal(Animal animal);

    public Animal createAnimal(AnimalDto animalDto) {
        return changeAnimalMapper.createAnimal(animalDto);
    }

    public void updateAnimal(AnimalDto animalDto, @MappingTarget Animal animal) {
        changeAnimalMapper.updateAnimal(animalDto, animal);
    }

    /**
     * Internal mapper to avoid unmapped target errors for inverse mappings
     */
    @Mapper(config = CommonMapperConfig.class, unmappedTargetPolicy = ReportingPolicy.IGNORE)
    public interface ChangeAnimalMapper {

        @InheritInverseConfiguration
        @Mapping(target = "id", ignore = true)
        Animal createAnimal(AnimalDto animalDto);

        @InheritConfiguration
        void updateAnimal(AnimalDto animalDto, @MappingTarget Animal animal);

    }

}

Upvotes: 3

Views: 4162

Answers (1)

Paul Marcelin Bejan
Paul Marcelin Bejan

Reputation: 1675

On mapping method level you can add:

@BeanMapping(unmappedTargetPolicy = ReportingPolicy.IGNORE)

Documentation:

Upvotes: 0

Related Questions