2013-05-20 62 views
1

我有一個EJB服務。嘗試訪問託管bean構造函數中的@EJB bean時出現NullPointerException

@Stateless 
public class SomeService {} 

我想在viewscoped豆與它注入這個和初始化:

@ManagedBean 
@ViewScoped 
public class ViewBean implements Serializable { 

    @EJB 
    private SomeService someService; 

    public ViewBean() { 
     System.out.println(someService.getEntity()); 
    } 

} 

然而,它拋出以下異常:

com.sun.faces.mgbean.ManagedBeanCreationException: Cant instantiate class: com.example.ViewBean. 
    at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:193) 
    at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:102) 
    at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:409) 
    at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:269) 
    at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244) 
    at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116) 
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) 
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) 
    [snip] 
Caused by: java.lang.NullPointerException 
    at com.example.ViewBean.<init>(ViewBean.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 java.lang.Class.newInstance0(Class.java:374) 
    at java.lang.Class.newInstance(Class.java:327) 
    at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:188) 
    ... 62 more 

這是怎麼引起的我該如何解決它?

回答

3

換句話說,你希望是EJB注入在幕後的工作原理如下:

ViewBean viewBean; 
viewBean.someService = new SomeService(); // EJB injected, so that constructor can access it. 
viewBean = new ViewBean(); // ViewBean constructed. 

然而,這在技術上是不可能的。當實例完全沒有被構建時,不可能分配一個實例變量。

執行基於注入的依賴項的任務的規範方法是在構建之後直接使用@PostConstruct註釋的方法。

因此,要解決您的具體問題,只需更換

public ViewBean() { 

通過

@PostConstruct 
public void init() { // Note: Method name is fully free to your choice. 

這樣的過程將在幕後大致如下:

ViewBean viewBean; 
viewBean = new ViewBean(); // ShiftBean constructed. 
viewBean.someService = new SomeService(); // EJB injected. 
viewBean.init(); // PostConstruct invoked. 

請注意具體問題與視圖範圍完全無關。使用請求,會話或應用程序範圍的bean時,您會遇到完全相同的問題。這是另一個證據,表明你從來沒有通過使用不同的範圍進行測試,從而將它排除在原因之外。

+0

感謝您的解釋BalusC,PostConstruct的工作,但我需要將EJB標記爲暫時的,否則我會得到一個java.io.NotSerializableException。最可能的原因是EntityManager不可序列化。 我以前曾試過PostConstruct,如果使用RequestScoped也不會引發異常。只有在使用ViewScoped時纔會得到NotSerializableException。 – ChrisM

+0

這不應該是強制性的。顯然你的設計中有更多的東西被破壞了。 'NotSerializableException'消息中提到了哪個類? – BalusC

+0

謝謝你的擡頭。有更多的東西被破壞了,所以我剝離了這個項目來調查,發現原因是設置爲客戶端的上下文參數javax.faces.STATE_SAVING_METHOD。我有http://stackoverflow.com/a/8072445/1754901中描述的響應緩衝區溢出(> 2KB)問題,並使用瞭解決該問題的建議5,但現在導致了NotSerializableException。所以我已經刪除了javax.faces.STATE_SAVING_METHOD,並且提出了建議#4(設置爲64KB)。現在所有的例外都沒有了,也不需要暫時的了。 – ChrisM

相關問題