Как я могу получить Spring bean, введенный в моем классе модели Wicket?
В пользовательском классе Wicket, в отличие от следующего, я использую службу bean, которую следует ввести Spring, как определено в аннотации SpringBean (из проекта wicket- spring).
public class ReportExportFileModel extends AbstractReadOnlyModel<File> {
@SpringBean(name = "reportService")
ReportService reportService;
ReportDto reportDto;
ReportExportFileModel(ReportDto reportDto) {
this.reportDto = reportDto;
}
@Override
public File getObject() {
try {
return reportService.generatePentahoReport(reportDto);
} catch (ReportGenerationException e) {
// ...
}
}
}
Однако это не работает: reportService.generatePentahoReport()
не работает с NullPointerException, потому что bean по какой-то причине не был добавлен Spring.
Любопытно, что я использовал тот же самый код модели, что и анонимный внутренний класс на странице Wicket, и там не было проблем.
Как я могу это исправить?
Ответы
Ответ 1
Работа с калиткой зависимостей работает с классами, реализующими IComponentInstantiationListener. Эти слушатели на уровне приложений вызывается всякий раз, когда создается экземпляр компонента. Это крюк, используемый для инъекции компонентов в зависимости.
В классах моделей такой механизм отсутствует. Любая модель может напрямую реализовать IModel, поэтому нет абстрактного базового класса, который может вызвать слушателей, в отличие от Component.
Я использую следующий базовый класс для моих вложенных моделей (Wicket 1.5):
public abstract class InjectedDetachableModel<T> extends LoadableDetachableModel<T> {
public InjectedDetachableModel() {
Injector.get().inject(this);
}
public InjectedDetachableModel(T a_entity) {
super(a_entity);
Injector.get().inject(this);
}
}
Edit:
Резюме соответствующих различий между 1.4 и 1.5, взятых из Руководство по миграции Wicket 1.5:
Калитка 1.4
@Override
protected void init()
{
// initialize Spring
addComponentInstantiationListener(new SpringComponentInjector(this, applicationContext));
}
и
InjectorHolder.getInjector().inject(Object object)
Калитка 1.5:
@Override
protected void init()
{
// initialize Spring
getComponentInstantiationListeners().add(new SpringComponentInjector(this, applicationContext))
}
и
Injector.get().inject(Object object)
Ответ 2
По-видимому Spring beans автоматически не вводится в другие классы, кроме Pages. Я также воспользовался этим свой класс WebRequestCycle.
Одним из простых решений является запуск инъекции вручную с помощью InjectorHolder.getInjector().inject(this)
.
Итак, запись такого конструктора заставляет модель работать по назначению:
ReportExportFileModel(ReportDto reportDto) {
this.reportDto = reportDto;
InjectorHolder.getInjector().inject(this);
}
Изменить: ах, сразу после публикации этого вопроса, я нашел еще один вопрос SOa с более точным объяснением о том, что происходит:
@SpringBean работает только в любом подклассе Component.