mapstruct / mapstruct/mapstruct

Mapping with "." (target this) can't find correct mapper

Open
#3,475 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Java
Stars
7.7k
Forks
1.1k
PR merge metrics
No merged PRs in 30d

Description

Expected behavior

Want to map inner object to current target.
Inner object mapping to current target defined in other mapper.

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, uses = SubSourceToSubTargetMapper.class)
public interface SourceToTargetMapper {

    @Mapping(target = "subObject", source = ".")
    Target sourceToTargetMapper(SubSource source);

    @Mapping(target = ".", source = "subObject")
    SubSource targetToSubSource(Target target);

    @Mapping(target = "subObject", source = "subObject")
    Source targetToSource(Target target);
}

Expected all 3 mapping will use SubSourceToSubTargetMapper mapper.
Possible it is some workaround to use external method? Tried @Named in SubSourceToSubTargetMapper and adding qualifiedByName in @Mapping(target = ".", source = "subObject") didn't help. Single found solution is to duplicate mapping in targetToSubSource.

Actual behavior

Case with with target = "." targetToSubSource() ignores SubSourceToSubTargetMapper.

Generated Impl code:

@Component
public class SourceToTargetMapperImpl implements SourceToTargetMapper {

    @Autowired
    private SubSourceToSubTargetMapper subSourceToSubTargetMapper;

    @Override
    public Target sourceToTargetMapper(SubSource source) {
        if ( source == null ) {
            return null;
        }

        Target target = new Target();

        target.setSubObject( subSourceToSubTargetMapper.sourceToTargetMapper( source ) );

        return target;
    }

    @Override
    public SubSource targetToSubSource(Target target) {
        if ( target == null ) {
            return null;
        }

        SubSource subSource = new SubSource();

        return subSource;
    }

    @Override
    public Source targetToSource(Target target) {
        if ( target == null ) {
            return null;
        }

        Source source = new Source();

        source.setSubObject( subSourceToSubTargetMapper.targetToSource( target.getSubObject() ) );
        source.setName( target.getName() );

        return source;
    }
}

Source targetToSource(Target target) found correct mapping method source.setSubObject() for same types pair.

Steps to reproduce the problem

Beans for mapping:

import lombok.Data;

@Data
public class Source {
    String name;
    String sourceSpecific;
    SubSource subObject;
}
import lombok.Data;

@Data
public class SubSource {
    String subSourceName;
}
import lombok.Data;

@Data
public class Target {
    String name;
    String targetSpecific;
    SubTarget subObject;
}
import lombok.Data;

@Data
public class SubTarget {
    String subTargetName;
}

Mappers:

import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingConstants;

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface SubSourceToSubTargetMapper {

    @Mapping(target = "subTargetName", source = "subSourceName")
    SubTarget sourceToTargetMapper(SubSource source);

    @InheritInverseConfiguration
    SubSource targetToSource(SubTarget target);
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingConstants;

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, uses = SubSourceToSubTargetMapper.class)
public interface SourceToTargetMapper {

    @Mapping(target = "subObject", source = ".")
    Target sourceToTargetMapper(SubSource source);

    @Mapping(target = ".", source = "subObject")
    SubSource targetToSubSource(Target target);

    @Mapping(target = "subObject", source = "subObject")
    Source targetToSource(Target target);
}
MapStruct Version

1.5.5.Final

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the supplied SourceToTargetMapper and SubSourceToSubTargetMapper reproducer, then inspect the generated SourceToTargetMapperImpl for handling of target="." and the uses mapper. Compare that path with the working source.setSubObject() mapping; done means targetToSubSource delegates the inner-object mapping to SubSourceToSubTargetMapper rather than returning an empty SubSource.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.