Thanks to visit codestin.com
Credit goes to github.com

Skip to content

@InheritConfiguration unexpected behavior #3858

@nikolaizhnikolov

Description

@nikolaizhnikolov

Expected behavior

Hello, we've had a problem in our project with unexpected mapstruct annotation behaviour, which lead to problems. We caught it early and updated our code and testing. However, initially we were led to believe things are working as expected. This is a sample of the code we had:

@Mapper(config = DefaultMapperConfig.class,
    collectionMappingStrategy = CollectionMappingStrategy.ACCESSOR_ONLY
)
public abstract class GroupMapper { 

    @Mapping(target = "name", source = "name")
    @Mapping(target = "parentGroupName", source = "parentGroup.name")
    // other mappings...
    public abstract GroupDto toDto(Group group);

    @InheritConfiguration(source = "toDto")
    @Mapping(target = "name", source = "groupNameDto.name")
    public abstract GroupDto toDto(Group group, GroupNameDto groupNameDto);
}

When trying to use this code this is what we expected:

  • We can reuse the toDto configuration, because the full code has a lot of custom mappings, that we don't want to repeat.
  • We will add new methods using other dtos to do partial updates of our groups, as they are large and complex, and a single update is hard to maintain.
  • The existing mappings will be reused from the Group group parameter, and anything that comes from the GroupNameDto groupNameDto can be accessed using the full qualifier (so nothing will clash)
  • If this is not possible a compilation error will disallow this usage

Actual behavior

What actually happened:

  • The mappings were inherited in an unexpected way
    • Direct mappings e.g. from the Group to the Dto were fine
    • More complex mappings e.g. accessing the parent Group (which is a different object of the same type nested inside the Group) were completely lost. Even when we tried modifying the original toDto method with the full path e.g. group.parentGroup.name we couldn't get it to work.
  • In the documentation we couldn't find a specific mention of the intended behavior. But testing showed that things will work fine as long as there are no additional parameters. So for our case it wasn't possible to partially update our group with different dtos while reusing the original dto method.
  • Our testing looked fine, because we didn't test ALL the fields for the new methods. Once it hit our testing environment we saw the inconsistencies and went back to the mapstruct implementation and saw its being generated wrong.

Our recommendation is to disallow compilation in the cases where @InheritConfiguration is used with incompatible parameters. Let me know your thoughts.

Steps to reproduce the problem

@MapperConfig(
    componentModel = "spring",
    collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE,
    injectionStrategy = InjectionStrategy.CONSTRUCTOR,
    builder = @Builder(disableBuilder = true),
    subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION
)
public interface DefaultMapperConfig {
}

MapStruct Version

1.6.3

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions