Подтвердить что ты не робот

Как я могу получить 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, и там не было проблем.

Как я могу это исправить?

4b9b3361

Ответ 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.