javaspringjavabeansmapstruct

Spring Boot does not find Mapper bean


I have the next mapper:

@Mapper
@Component
public interface PriceEntityMapper {

    @Mapping(source="brandId", target="brandId")
    @Mapping(source="startDate", target="startDate", qualifiedByName = "timestampToLocalDateTime")
    @Mapping(source="endDate", target="endDate", qualifiedByName = "timestampToLocalDateTime")
    @Mapping(source="priceList", target="priceList")
    @Mapping(source="productId", target="productId")
    @Mapping(source="priority", target="priority")
    @Mapping(source="price", target="price")
    @Mapping(source="curr", target="currency")
    Price priceEntityToPrice(PriceEntity priceEntity);

    @Named("timestampToLocalDateTime")
    default LocalDateTime timestampToLocalDateTime(Timestamp timestamp) {
        return timestamp.toLocalDateTime();
    }
}

and next implementation:

@Service
public class PriceServiceImpl implements PriceService {

    private final PriceRepository priceRepository;
    private final PriceEntityMapper priceEntityMapper;

    @Autowired
    public PriceServiceImpl(PriceRepository priceRepository, PriceEntityMapper priceEntityMapper) {
        this.priceRepository = priceRepository;
        this.priceEntityMapper = priceEntityMapper;
    }

    @Override
    public Price getPrice(LocalDateTime applicationDate, Integer productId, Integer brandId) {
        try {

            //PriceEntity priceEntity = priceRepository.findByBrandIdAndProductIdAndStartDateLessThanEqualApplicationDateAndEndDateGreaterThanEqualApplicationDate(brandId, productId, Timestamp.valueOf(applicationDate));
            return priceEntityMapper.priceEntityToPrice(new PriceEntity());

        } catch (Exception e) {

            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Price not found", e);
        }
    }
}

well, when I am trying to run the app give me the next error:

Parameter 1 of constructor in com.dharian.application.service.PriceServiceImpl required a bean of type 'com.dharian.infraestructure.mapper.PriceEntityMapper' that could not be found.

But I have the annotation @Mapper and @Component, also I have

@SpringBootApplication
@ComponentScan({"com.dharian.infraestructure", "com.dharian.application"})
public class PruebatecnicaApplication {
    public static void main(String[] args) {
        SpringApplication.run(PruebatecnicaApplication.class, args);
    }
}

For scanning the packages. It doesn't work.

what can it be?

I tried @ComponentScan, changed autowired and changed annotation over the Mapper class.


Solution

  • Instead of using @Component you have to declare it as a bean in MapStruct way:

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

    Only now initialise it with @Autowired and it will be created as a bean.

    Otherwise, you have to declare the mapper directly:

    PriceEntityMapper mapper = Mappers.getMapper(PriceEntityMapper.class)
    

    For more information see documentation for MapStruct Configuration options -> mapstruct.defaultComponentModel section:

    enter image description here