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)
Apparently Spring beans don't get automatically injected to other classes than Pages . I've run to this also with my custom WebRequestCycle class.
One easy solution is to trigger the injection manually using InjectorHolder.getInjector().inject(this)
.
So, writing the constructor like this makes the model work as intended:
ReportExportFileModel(ReportDto reportDto) {
this.reportDto = reportDto;
InjectorHolder.getInjector().inject(this);
}
Edit : ah, right after posting this, I found another SO question with a more accurate explanation of what's going on:
@SpringBean works only in any subclass of Component.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.