且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在我的自定义Wicket模型类中注入一个Spring bean?

更新时间:2023-10-09 22:37:58

小窗口依赖注入与实现IComponentInstantiationListener的类一起工作。每当组件被实例化时调用这些应用程序级别的监听器。这是用于依赖注入组件的钩子。



模型类没有这样的机制。任何模型都可以直接实现IModel,所以没有抽象的基类可以调用监听器,不像Component。



我为我注入的模型使用了以下基类(Wicket 1.5 ):

  public abstract class InjectedDetachableModel< T>扩展LoadableDetachableModel< T> {

public InjectedDetachableModel(){
Injector.get()。inject(this);
}

public InjectedDetachableModel(T a_entity){
super(a_entity);
Injector.get()。inject(this);
}
}

修改
Wicket 1.5迁移指南获取的1.4和1.5之间的相关差异摘要:



Wicket 1.4



  @Override 
protected void init ()
{
//初始化Spring
addComponentInstantiationListener(new SpringComponentInjector(this,applicationContext));
}

  InjectorHolder.getInjector()。inject(Object object)



Wicket 1.5:



  @Override 
protected void init()
{
// initialize Spring
getComponentInstantiationListeners()。add(new SpringComponentInjector(this,applicationContext))
}

  Injector.get()。inject(Object object)
/ pre>

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:

Wicket 1.4

@Override
protected void init()
{
    // initialize Spring
    addComponentInstantiationListener(new SpringComponentInjector(this, applicationContext));
}

and

InjectorHolder.getInjector().inject(Object object)

Wicket 1.5:

@Override
protected void init()
{
    // initialize Spring
    getComponentInstantiationListeners().add(new SpringComponentInjector(this, applicationContext))
}

and

Injector.get().inject(Object object)