2011-10-04 42 views
1

我有一個JSF2項目(GlassJish 3.1上的Mojarra)。是否執行此JSF模式中斷依賴注入?

我有一個ViewScoped豆,通過一個工具類,像這樣引用服務:

@ManagedBean 
@ApplicationScoped 
public static class ServicesUtil { 
    @EJB 
    UserService userService; 
    @EJB 
    EmailService emailService; 
    /** getters/setters **/ 
} 

@ManagedBean 
@ViewScoped 
public class UserHandler { 
    public String method() { 
    ServicesUtil.getUserService().doUserStuff(); 
    return "newPage"; 
    } 
} 

我的問題是,因爲ServicesUtil是ApplicationScoped,意思是隻存在整個應用程序的每個服務的一個實例?這是不好的做法?如果正確完成,GlassFish中的CDI是否會根據需要創建新實例?

同樣,如果服務被注入UserHandler,而不是應用程序可擴展性更高?

我們添加ServicesUtil圖層的原因是我的一位同事說,他在ViewScope時偶爾會遇到注入在Handler中工作的問題。在ViewScoped bean中使用@EJB是否有困難?

任何幫助,非常感謝!

Rob

回答

2

您使用的模式似乎沒有多大意義。將EJB注入到視圖範圍的bean中應該沒有問題。

根據您使用的EJB類型(無狀態,有狀態或單例),可以有不同的事情。

如果userService和emailService是無狀態的(它們很可能應該是),那麼通過使用首先注入到應用程序範圍的bean中的bean將無濟於事。也就是說,注入的內容不是bean本身,而是一個代理,並且每個請求都被路由到不同的實際bean實例(請參閱http://en.wikipedia.org/wiki/Enterprise_JavaBean#Stateless_Session_Beans)。

如果userService和emailService是有狀態的,那麼您確實會在這裏獲得一個實例,但我非常懷疑您需要在應用程序中的每個用戶之間共享實際值。但即使你想要,一次只有一個用戶(線程)可以訪問有狀態bean。

如果這些服務是單例,那麼您可以立即將它們注入到視圖範圍的bean中。絕對沒有理由通過應用程序範圍的bean進行訪問。

此外,ServicesUtil.getUserService()是一個靜態方法,所以使用它來獲得注入服務是脆弱的。如果你想使用這個(你不應該,但是假設)ServicesUtil應該注入UserHandler

然後,你似乎混淆了CDI和JSF託管的bean。我同意這是令人困惑的,但目前它是這樣。 @ViewScoped在組合遇見CDI bean時不起作用。從您的代碼中,不清楚@ManagedBean是JSF變體還是Java EE/CDI變體。在這種情況下,如果您想使用視圖範圍,它應該是javax.faces.bean.ManagedBean

+0

嗨,你能否詳細說明這個問題:「@ViewScoped不能與CDI bean結合使用」 - 我不明白你的意思。我目前使用javax.faces.bean.ManagedBean和javax.ejb.EJB註釋。再次感謝! –

+1

他意味着當您使用'javax.annotation.ManagedBean'(或'javax.inject.Named')時它將不起作用。 – BalusC

+0

目前看着相同的模式。注入viewscoped bean會保持ejb ref,並且如果服務器死亡並且會話故障轉移到新的jvm(如果HA不重要,則不會出現問題)會出錯。上面的模式是注入和服務定位模式之間的一個很好的中間模式,即使用'@ EJB'來注入應用程序,然後使用request/viewscoped bean中的這些模式。 – andyfinch