Есть некая сущность Report и одна из ее реализаций:
public class CCReport extends AbstractReport<CCReportRow> {
public CCReport(List<CCReportRow> rows, LocalDate from, LocalDate to) {
super(rows, from, to);
}
@Override
public Class<CCReportRow> getRowClass() {
return CCReportRow.class;
}
}
Есть некий интерфейс сервиса:
public interface ReportService<T extends Report> {
T createReport(LocalDate from, LocalDate to);
}
У него есть несколько реализаций в зависимости от типа Report
:
@Service
@RequiredArgsConstructor
public class CCReportService implements ReportService<CCReport> {
private final CCReportsExportRepository repository;
@Override
public CCReport createReport(LocalDate from, LocalDate to) {
return repository.generateReport(from, to);
}
}
Далее есть абстрактная реализация слушателя RabbitMq:
@Slf4j
@RequiredArgsConstructor
public abstract class AbstractReportTaskListener<T extends Report> implements ReportTaskListener<T> {
protected final ReportService<T> reportService;
//-------------------//
@Override
public void processReportTask(SingleReportRequest<T> reportRequest) {
Report report = reportService.createReport(reportRequest.getFrom(), reportRequest.getTo());
//-------------------//
}
}
И непосредственно сама реализация этого слушателя:
@Component
public class RabbitCCReportTaskListener extends AbstractReportTaskListener<CCReport> {
public RabbitCCReportTaskListener(
ReportService<CCReport> 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"
Это случается из-за Type Erasure: при компиляции ReportService<CCReport>
вырождается в ReportService<Report>
, и здесь возникает неоднозначность в рантайме, т.к. таких бинов уже 2. Чтобы избежать ситуации используйте либо конкретный наследник ReportService либо @Qualifier в конструкторе конкретного наследника AbstractReportTaskListener.
В докер упакованы все jar-файлы проекта и все зависимости. Локально, вероятно, не все скомпилировано, попробуйте пересобрать проект начисто.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Проблема в следующем, при выполнении кода метод (метод 1) вызывает другой метод (метод 2), но что-бы не увеличивать код нужно вызвать из "метода...
Немного не понимаю механизм подключения библиотеки, хочу подключить AGAVU, подскажите как ее добавить: достаточно в Maven добавить новую Dependency...
Скажите пожалуйста, как сгенерировать файл под jsch, я пробовал с помощью PuttyGen, но addIdentity вылетает с exception с сообщением, что файл-ключ "не правильный"?
Встретил пример, проверка числа i на нечетность и никак не могу понять как работает данная проверкаКонкретно не понятен блок (i&1)