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 calling InjectorHolder.getInjector().inject(this);
in its constructor.
For example:
class MyPojo {
@SpringBean
MyDumbDAO dao;
MyPojo() {
InjectorHolder.getInjector().inject(this);
}
void justDoIt() {
dao.duh(); // dao is there!
}
}
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 with new
(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.
@SpringBean
only injects dependencies into classes that inherit from Wicket's Component
. @Autowired
only injects dependencies into classes created by Spring itself. That means you can't automatically inject a dependency into an object you create with new
.
(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 actually org.apache.wicket.Application
.) For example:
public class MyApplication extends AuthenticatedWebApplication implements
ApplicationContextAware {
private ApplicationContext ctx;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.ctx = applicationContext;
}
public static MyApplication get() {
return (MyApplication) WebApplication.get();
}
public static Object getSpringBean(String bean) {
return get().ctx.getBean(bean);
}
public static <T> T getSpringBean(Class<T> bean) {
return get().ctx.getBean(bean);
}
....
}
In my Spring application context:
<!-- Set up wicket application -->
<bean id="wicketApplication" class="uk.co.humboldt.Project.MyApplication"/>
My helper object then looks up the service on demand:
public class HelperObject {
private Service getService() {
return MyApplication.getSpringBean(Service.class);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With