13

I've a session scoped bean:

@Named
@SessionScoped
public class SessionBean implements Serializable {

    private String someProperty;

    public String getSomeProperty() {
        return someProperty;
    }

}

I'd like to inject this in a request scoped bean and initialize with it:

@Named
@RequestScoped
public class RequestBean {

    @Inject
    private SessionBean sessionBean;  

    public RequestBean() {
        System.out.println(sessionBean.getProperty());
    }

}

However, it throws the following exception:

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)
    ...

How is this caused and how can I solve it?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
eric.itzhak
  • 15,752
  • 26
  • 89
  • 142
  • The dependency can only be injected once the instantiation is done, but you are using it within the constructor. Try executing the code at post-construction. – Bhesh Gurung May 06 '13 at 13:43
  • I believe you didn't understood the "post-construction" part. You should use a `@PostConstruct` method and absolutely not invoke it from inside the constructor. – BalusC May 06 '13 at 13:45

2 Answers2

27

You're expecting that the injected dependency is available before the bean is constructed. You're expecting that it works like this:

RequestBean requestBean;
requestBean.sessionBean = sessionBean; // Injection.
requestBean = new RequestBean(); // Constructor invoked.

This is however not true and technically impossible. The dependencies are injected after construction.

RequestBean requestBean;
requestBean = new RequestBean(); // Constructor invoked.
requestBean.sessionBean = sessionBean; // Injection.

You should be using a @PostConstruct method instead if you intend to perform business logic based on injected dependencies directly after bean's construction.

Remove the constructor and add this method:

@PostConstruct
public void init() {
    System.out.println(sessionBean.getSomeProperty());
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I edited the question, tried using PostConstruct and still same result. – eric.itzhak May 06 '13 at 13:46
  • 2
    You're still using the constructor. Remove it. Re-read the first part of the answer. I would also suggest to take a JSF pause and [learn some basic Java](http://docs.oracle.com/javase/tutorial/) before continuing with JSF. – BalusC May 06 '13 at 13:46
1

BalusC's reply is correct, but is does reflect the assignment phase of a object creation, that did not run at this time. But anyway the CDI bean should be accessible if you grep it programatically via:

javax.enterprise.inject.spi.CDI.current().select(SessionBean.class).get()
Mathieu VIALES
  • 4,526
  • 3
  • 31
  • 48
Groovieman
  • 31
  • 5