#java #spring #docker #spring_boot
Есть некая сущность Report и одна из ее реализаций: public class CCReport extends AbstractReport{ public CCReport(List rows, LocalDate from, LocalDate to) { super(rows, from, to); } @Override public Class getRowClass() { return CCReportRow.class; } } Есть некий интерфейс сервиса: public interface ReportService { T createReport(LocalDate from, LocalDate to); } У него есть несколько реализаций в зависимости от типа Report: @Service @RequiredArgsConstructor public class CCReportService implements ReportService { private final CCReportsExportRepository repository; @Override public CCReport createReport(LocalDate from, LocalDate to) { return repository.generateReport(from, to); } } Далее есть абстрактная реализация слушателя RabbitMq: @Slf4j @RequiredArgsConstructor public abstract class AbstractReportTaskListener implements ReportTaskListener { protected final ReportService reportService; //-------------------// @Override public void processReportTask(SingleReportRequest reportRequest) { Report report = reportService.createReport(reportRequest.getFrom(), reportRequest.getTo()); //-------------------// } } И непосредственно сама реализация этого слушателя: @Component public class RabbitCCReportTaskListener extends AbstractReportTaskListener { public RabbitCCReportTaskListener( ReportService reportService, ReportMailService mailService, ReportToExcelService excelService, ReportsNameGenerator nameGenerator, WebDavStorageService webDavStorageService) { super(reportService, mailService, excelService, nameGenerator, webDavStorageService); } @RabbitListener(queues = RabbitConfig.CC_QUEUE, concurrency = "2-2", autoStartup = "true") @Override public void processReportTask(SingleReportRequest reportRequest) { super.processReportTask(reportRequest); } } При запуске всего этого добра через gradle bootRun все запускается без проблем, однако, если создаю docker-образ вылетает ошибка: *********************** APPLICATION FAILED TO START Description: Parameter 0 of constructor in com.reports.service.RabbitCCReportTaskListener required a single bean, but 2 were found: - CCReportService: defined in URL [jar:file:/app/reports.jar!/BOOT-INF/classes!/reports/service/CCReportService.class] - SRReportService: defined in URL [jar:file:/app/reports.jar!/BOOT-INF/classes!/reports/service/SRReportService.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed В конце концов приходится явно описывать бины через @Qualifier и тогда начинает работать. Подскажите, с чем может быть связано такое поведение? UPD: Вот ссылка на SO, где уже описывали подобный вопрос. Плюс есть несколько статей по запросу "spring generic bean autowire"
Ответы
Ответ 1
Это случается из-за Type Erasure: при компиляции ReportServiceвырождается в ReportService , и здесь возникает неоднозначность в рантайме, т.к. таких бинов уже 2. Чтобы избежать ситуации используйте либо конкретный наследник ReportService либо @Qualifier в конструкторе конкретного наследника AbstractReportTaskListener. В докер упакованы все jar-файлы проекта и все зависимости. Локально, вероятно, не все скомпилировано, попробуйте пересобрать проект начисто.
Комментариев нет:
Отправить комментарий