Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapstruct extending multiple interfaces containing method with the same signature

I use 2 libraries in my project which require mappers with the different interfaces:

public interface FirstLibraryMapper<T, M> {

    M mapToDto(T domain);

    List<M> mapToDto(List<T> domains);

}

public interface SecondLibraryMapper<T, M> {

    M mapToDto(T domain);

}

I want to create a single mapper bean using mapstruct that will be injected in libraries components by interface because both interfaces have a method with exact signature:

@Mapper
public interface MyMapper extends FirstLibraryMapper<MyDomain, MyDto>, SecondLibraryMapper<MyDomain, MyDto> {

}

When I try to compile, I get this error:

Ambiguous mapping methods found for mapping collection element to MyDto: MyDto mapToDto(MyDomain arg0), MyDto mapToDto(MyDomain arg0).

I was able to bypass this issue by using @Named and @IterableMapping but it feels wrong and clunky. Why can't mapstruct processor ignore the second method if it has an exact signature as the first one? Should I rise an issue on their github page? Or am I wrong in that case?

like image 403
Pashchenko Denis Avatar asked Jan 17 '26 23:01

Pashchenko Denis


2 Answers

Problem solved by overriding method in result mapper which is still a bit clunky but seems to do the trick.

@Mapper
public interface MyMapper extends FirstLibraryMapper<MyDomain, MyDto>, SecondLibraryMapper<MyDomain, MyDto> {

    @Override
    MyDto mapToDto(MyDomain domain);

}
like image 186
Pashchenko Denis Avatar answered Jan 20 '26 12:01

Pashchenko Denis


Did you consider combining both mappers under some sort of Facade pattern?

@Mapper
public interface MyFirstMapper extends FirstLibraryMapper<MyDomain, MyDto> {
}

@Mapper
public interface MySecondMapper extends SecondLibraryMapper<MyDomain, MyDto> {
}

@Service
public class MyMapperFacade extends FirstLibraryMapper<MyDomain, MyDto>, SecondLibraryMapper<MyDomain, MyDto> {

    @Autowired
    private MyFirstMapper firstMapper;

    @Autowired
    private MySecondMapper secondMapper;

    @Override
    public MyDto mapToDto(MyDomain domain) {
        return firstMapper.mapToDto(domain); // always delegate to FirstLibraryMapper
    }
}
like image 31
Nikolai Shevchenko Avatar answered Jan 20 '26 11:01

Nikolai Shevchenko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!