NullPointerException при попытке доступа к @Inject bean в конструкторе
У меня есть сеанс bean:
@Named
@SessionScoped
public class SessionBean implements Serializable {
private String someProperty;
public String getSomeProperty() {
return someProperty;
}
}
Я хотел бы добавить это в запрос bean и инициализировать его:
@Named
@RequestScoped
public class RequestBean {
@Inject
private SessionBean sessionBean;
public RequestBean() {
System.out.println(sessionBean.getProperty());
}
}
Однако это вызывает следующее исключение:
java.lang.NullPointerException
at com.example.RequestBean.<init>(RequestBean.java:42)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at org.jboss.weld.introspector.jlr.WeldConstructorImpl.newInstance(WeldConstructorImpl.java:206)
at org.jboss.weld.injection.ConstructorInjectionPoint.newInstance(ConstructorInjectionPoint.java:117)
at org.jboss.weld.bean.ManagedBean.createInstance(ManagedBean.java:336)
at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.produce(ManagedBean.java:200)
at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:292)
...
Как это вызвано и как я могу его решить?
Ответы
Ответ 1
Ожидается, что введенная зависимость доступна до создания bean. Вы ожидаете, что он работает следующим образом:
RequestBean requestBean;
requestBean.sessionBean = sessionBean; // Injection.
requestBean = new RequestBean(); // Constructor invoked.
Это, однако, неверно и технически невозможно. Зависимости вводятся после построения.
RequestBean requestBean;
requestBean = new RequestBean(); // Constructor invoked.
requestBean.sessionBean = sessionBean; // Injection.
Вместо этого вы должны использовать метод @PostConstruct
, если вы намереваетесь выполнять бизнес-логику на основе вложенных зависимостей непосредственно после построения bean.
удалите конструктор и добавьте этот метод:
@PostConstruct
public void init() {
System.out.println(sessionBean.getSomeProperty());
}
Ответ 2
Ответ BalusC верен, но отражает фазу назначения создания объекта, которая не выполнялась в это время. Но в любом случае CDI
bean должен быть доступен, если вы grep
его программно с помощью:
javax.enterprise.inject.spi.CDI.current().select(SessionBean.class).get()