1
votes

I have two domain entities:

class Identity {
   Long id;
   Set<Business> businesses;
}

class Business {
   Long id;
   String name;
}

I then have two DTOs that extend a base DTO:

class BaseDto {
   String id;
}

class IdentityDto extends BaseDto {
   Set<BaseDto> businesses;
}

class BusinessDto extends BaseDto {
   String name;
}

Then I created a mapper that maps a list of my domain entities to either a Set of the specific dto, or a set of the more generic base dto. This is because when I am getting a list of businesses, I want the full business dto, but when I get an identity, I just what the base info in it's list of businesses.

But when I try to create the mapper for the identity I get the following error:

Ambiguous mapping methods found for mapping property
"Set<Business> businesses" to Set<BaseDto>:

Set<BusinessDto> BusinessMapper.toSet(Set<Business> businesses),
Set<BaseDto> BusinessMapper.toBaseSet(Set<Business> businesses).

I thought that mapstruct used the most specific method, so should know to use the toIdentifierSet method in this case.

How do I make mapstruct know which method to use?

1

1 Answers

3
votes

There is no most specific method here as you are trying to map into Set<BaseDto>.

You can use Mapping method selection based on qualifiers.

You can define some annotations:

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface BaseInfo {
}

Then in your BusinessMapper

@Mapper
public interface BusinessMapper {

    Set<BusinessDto> toSet(Set<Business> businesses);

    @BaseInfo
    Set<BaseDto> toBaseSet(Set<Business> businesses);
}

Then in your identifier

@Mapper
public interface IdentifierMapper {

    @Mapping(target = "businesses", qualifiedBy = BaseInfo.class)
    IdentityDto map(Identity source);
}

In case you want to explicitly pick always you can add another annotation BusinessInfo and then annotate the other method. Then you would need to pick a method each time.