Skip to content

Ambiguous mapping error in @SubclassMapping #3355

Description

@bwgjoseph

Expected behavior

I'm expecting MapStruct to call my method which I define what mapping to call

Actual behavior

It was not able to generate the mapping implementation class

Steps to reproduce the problem

I have the following classes

@Mapper(
        componentModel = MappingConstants.ComponentModel.SPRING,
        subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION
)
public abstract class AddressMapper {
    @SubclassMapping(source = AddressDO.class, target = AddressResponseDto.class)
    abstract AddressResponseDto toD(AddressDO addressDO);

    AddressResponseDto toDto(AddressDO addressDo) {
        if (addressDo.getBuilding() != null) {
            return toHomeDto(addressDo);
        } else {
            return toOfficeDto(addressDo);
        }
    }

    @Mapping(source = "auditable", target = ".")
    abstract HomeAddressResponseDto toHomeDto(AddressDO addressDO);
    @Mapping(source = "auditable", target = ".")
    abstract OfficeAddressResponseDto toOfficeDto(AddressDO addressDO);
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
    @Type(value = HomeAddressResponseDto.class, name = "home"),
    @Type(value = OfficeAddressResponseDto.class, name = "office")
})
public interface AddressResponseDto {}

When I try to compile, it complains the Ambiguous mapping

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile (default-compile) on project mapstruct-with-subclass: Compilation failure      
[ERROR] /Z:/mapstruct-with-subclass/src/main/java/com/bwgjoseph/mapstructwithsubclass/AddressMapper.java:[22,33] Ambiguous mapping methods found for mapping SubclassMapping for com.bwgjoseph.mapstructwithsubclass.AddressDO to com.bwgjoseph.mapstructwithsubclass.AddressResponseDto: com.bwgjoseph.mapstructwithsubclass.AddressResponseDto toDto(com.bwgjoseph.mapstructwithsubclass.AddressDO addressDo), com.bwgjoseph.mapstructwithsubclass.HomeAddressResponseDto toHomeDto(com.bwgjoseph.mapstructwithsubclass.AddressDO addressDO), com.bwgjoseph.mapstructwithsubclass.OfficeAddressResponseDto toOfficeDto(com.bwgjoseph.mapstructwithsubclass.AddressDO addressDO). See https://mapstruct.org/faq/#ambiguous for more info.

I have tried to use @BeanMapping but it doesn't work

@BeanMapping(qualifiedByName = "toDto")
@SubclassMapping(source = AddressDO.class, target = AddressResponseDto.class)
abstract AddressResponseDto toD(AddressDO addressDO);

@Named("toDto")
AddressResponseDto toDto(AddressDO addressDo) {
    if (addressDo.getBuilding() != null) {
        return toHomeDto(addressDo);
    } else {
        return toOfficeDto(addressDo);
    }
}

I'm guessing that it might work with #3120 merged in 1.6.0?

Changed to use interface is also the same

image

My use case is that I have to map a single domain class, into the respective different response class based on some property. Appreciate if there's any workaround for this.

Thanks!

MapStruct Version

1.5.5-Final

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions