In a custom Wicket class, not unlike the following, I'm using a service bean which should be injected by Spring, as defined with the SpringBean annotation (from the wicket-spring project).
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) {
// ...
}
}
}
However, this doesn't work: reportService.generatePentahoReport()
fails with NullPointerException, because the bean has not been injected by Spring for some reason.
Curiously, I've used the exact same Model code as anonymous inner class on a Wicket Page, and there was no problem there.
How can I fix this?
The wicket dependency-injection works with classes implementing IComponentInstantiationListener. These application-level listeners are called whenever a Component is instantiated. This is the hook used for dependency injection of components.
The model classes do not have such a mechanism in place. Any model can directly implement IModel so there is no abstract base class which can call the listeners, unlike Component.
I use the following base class for my injected models (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: Summary of relevant differences between 1.4 and 1.5, taken from Wicket 1.5 migration guide:
@Override
protected void init()
{
// initialize Spring
addComponentInstantiationListener(new SpringComponentInjector(this, applicationContext));
}
and
InjectorHolder.getInjector().inject(Object object)
@Override
protected void init()
{
// initialize Spring
getComponentInstantiationListeners().add(new SpringComponentInjector(this, applicationContext))
}
and
Injector.get().inject(Object object)