javaspringspring-bootmapstructmapper

MapStruct Can Not Build Implementation Code For @Mapping Definition


Mapstruct works fine in project but there is a problem with @Mapping annotation.

Working Spring Boot version 2.2.0.RELEASE

Here is dependency details :

implementation 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.mapstruct:mapstruct'
annotationProcessor 'org.mapstruct:mapstruct-processor'
implementation 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0"

Here is example about the problem.

UserEntity.java

public class UserEntity {

    private String username;
    private Integer userAge;
    private UserAddressEntity userAddressEntity;
}

UserAddressEntity.java

public class UserAddressEntity {
    private String userAddress;
    private Integer userPhone;
}

UserAddressDTO

public class UserAddressDTO {
    private String userAddress;
    private Integer userPhone;
}

TargetDTO (I want to convert UserEntity to this DTO)

public class TargetDTO {

    private String username;
    private Integer userAge;
    private UserAddressDTO userAddressDto; 
}

Here is mapper class :

@Mapper(componentModel = "spring")
public interface UserEntityMapper  {


    @Mapping(source = "userAddressEntity", target = "userAddressDto")
    List<TargetDTO> fromEntityToDto(List<UserEntity> userEntityList);
}

In this interface, Mapstruct can not create implementation for @Mapping. I changed implemenetation like this:

@Mapper(componentModel = "spring")
public interface UserEntityMapper  {


    @Mapping(source = "userAddressEntity.userAddress", target = "userAddressDto.userAddress")
    @Mapping(source = "userAddressEntity.userPhone", target = "userAddressDto.userPhone")
    List<TargetDTO> fromEntityToDto(List<UserEntity> userEntityList);
}

It is still not working.

All other fields are mapping successfully only the definition in @Mapping is not working.

But, when I removed @Mapping and I changed TargetDto like this, it works :

public class TargetDTO {
  
    private String username;
    private Integer userAge;
    private UserAddressDTO userAddressEntity; // I just updated property naming
}

But why is it not working with @Mapping. This is the problem.

Also I tried "uses" definition and seperated problematic mapper but it also could not map UserAddressEntity to UserAddressDTO :

@Mapper(componentModel = "spring", **uses = UserAddressMapper.class**)
public interface UserEntityMapper  {


    @Mapping(source = "userAddressEntity", target = "userAddressDto")
    List<TargetDTO> fromEntityToDto(List<UserEntity> userEntityList);
}

What is the problem with @Mapping usage? When code is compiling Mapstruct can create Implementation class and build implementation code for all other fields but it can not create implementation code for @Mapping in the Implementation class. I tried many ways and it does not work in anyway.


Solution

  • @Mapping is not directly applicable to methods for mapping collections. Instead, you should define a mapping method for individual objects.

    @Mapper(componentModel = "spring")
    public interface UserEntityMapper {
    
      @Mapping(source = "userAddressEntity", target = "userAddressDto")
      TargetDTO fromEntityToDto(UserEntity userEntityList);
    
      List<TargetDTO> fromEntitiesToDtos(List<UserEntity> userEntityList);
    }
    

    MapStruct will invoke the fromEntityToDto method for each element when performing collection mapping.