I have a problem with injecting a bean into a helper class. It works basically like this: I create an object in the page constructor that does some work, returns some data and I show these on the page. In this helper object, a service should be injected via @Autowired
annotation. However, I always get a null pointer exception when I use it. I also tried @SpringBean
but it didn't help. On the other hand, when I inject this service directly into the page with @SpringBean
, it's accessible and works fine. Do you know where the problem is?
This is the page:
public class Page extends BasePage {
public Page() {
HelperObject object = new HelperObject(new Application("APP_NAME"));
String result = object.getData();
add(new Label("label", result));
}
}
Helper object:
public class HelperObject {
private Application app;
@Autowired
private Service service;
public HelperObject(Application app) {
this.app = app;
}
public String getData() {
// use service, manipulate data, return a string
}
}
You can inject dependencies into non-Spring-non-Wicket-new-created objects using
@SpringBean
by callingInjectorHolder.getInjector().inject(this);
in its constructor.For example:
Note that it will only work if called within a Wicket-managed request. If not (ie, if it's a Quartz job, or a Filter executed before Wicket's), the
Application
instance will not be available, and the injector won't know how to get the dependencies.Another solution is to use Spring's
@Configurable
. It uses AspectJ to intercept creation of annotated objects, and inject its dependencies, even if you instantiate them directly withnew
(or some other framework, like Hibernate, creates them internally). But this requires runtime or build-time (works better for me) bytecode manipulation, which may be too much magic for some people.The best practice would be to create your objects via a factory bean (that has those properties injected by Spring, and have that factory inject those properties to objects it spawns - pure IoC).
You should really avoid using SpringContext all over the place (or any other similar solution for that matter). Here is a partial list of reasons:
@SpringBean
only injects dependencies into classes that inherit from Wicket'sComponent
.@Autowired
only injects dependencies into classes created by Spring itself. That means you can't automatically inject a dependency into an object you create withnew
.(Edit: you can also add a
@SpringBean
injection to your class by injecting in the constructor:InjectorHolder.getInjector().inject(this);
)My normal workaround for this is to use my application class to help. (I'm a little puzzled by your use of
new Application(...)
. I assume this isn't actuallyorg.apache.wicket.Application
.) For example:In my Spring application context:
My helper object then looks up the service on demand: