2011-11-22 109 views
4

我開發一些應用程序,它由三層組成:分層架構中的CDI。如何使用CDI註釋注入服務對象?

  1. 數據庫訪問層(JPA + Hibernate作爲提供商)
  2. 業務邏輯層
  3. 表示層(JSF 2.0)

在我開始之前,我閱讀了David Geary和Cay S. Horstmann撰寫的Core JavaServer Faces(第3版)一書中的一些章節。在本書中,作者強烈建議使用@Named註釋而不是@ManagedBean。好吧,我想我可以試試。用戶登錄

我也瞭解了一些新的註解,即@Inject -

然後我剛好實現一些基本的功能着手層建築我的應用程序。我認爲僅僅在接口上注入一層到另一層可能會很舒服。但我擔心我誤解了一些東西,所以我帶着我的問題來找你。

讓我介紹我的代碼的某些部分:

CredentialsBean.java

@Named("userCredentials") 
public class CredentialsBean { 
    @Inject 
    AccountService accountService; 

    private String login; 
    private String password; 

    public String verify() 
    { 
     if (accountService.verifyCredentials(login, password)) 
      return "success"; 
     else 
      return "failure"; 
    } 
    // getters and setters 
} 

AccountService.java

public interface AccountService { 
    public Boolean verifyCredentials(String login, String password); 
} 

AccountServiceImpl.java:

public class AccountServiceImpl implements AccountService { 
    @Inject 
    AccountDAO dao; 

    @Override 
    public Boolean verifyCredentials(String login, String password) { 
     // some logic 
    } 
} 

AccountDAO.java

public interface AccountDAO { 
    public Account getAccount(String login); 
} 

AccountDAOImpl.java

public class AccountDAOImpl implements AccountDAO { 
    @PersistenceContext(unitName = "MyApp") 
    protected EntityManager em; 

    public EntityManager getEntityManager() { 
     return em; 
    } 

    @Override 
    public Account getAccount(String login) { 
     // some data processing 
    } 
} 

這最後一堂課上的一些Java類操作與@Entity註釋,請不要介意。

我有一種感覺,我的解決方案出了問題。

基本錯誤是事實,即使我提供一些數據與<h:form><h:inputText>標籤創建的形式,調試verify()方法時,我所看到的,loginpasswordnull,那麼什麼是錯在這裏,但我有不知道是什麼。

我也擔心我是否理解@Inject。我可以像上面提供的那樣使用它來使用接口來連接圖層嗎?


好的。我發現我在登錄和密碼字段中得到空值的原因,但我還不知道解決方案。 發生這種情況是因爲在以某種神奇方式執行期間,創建了多個(至少兩個)CredentialsBean實例。檢查Eclipse調試器。首先得到它的字段設置正確,但第二個沒有,並且這第二個值被髮送到服務層。 我想知道這是不是一個範圍問題。我不應該把@SessionScoped放在CredentialsBean中嗎?

+0

您的實現類沒有'@ Named'註釋。這是故意的還是過分簡化了代碼片段? – BalusC

+0

他們有嗎?我認爲只有用於在JSF頁面和應用程序邏輯之間傳輸信息的bean才需要它。我錯了嗎? – rivasket

+0

'@Stateless'也可以,如果它應該是一個EJB。容器應該怎樣知道你有哪些實現需要注入? – BalusC

回答

1

您對@Inject的理解是正確的,這正是它的目的所在。機會是你的注入點是空的,因爲你沒有一個bean存檔(你需要一個名爲beans.xml的文件在WEB-INF或META-INF中,如果它是一個jar,它可以是空的)。這是注射點無效的常見原因。

+0

不幸的是,這是不正確的解決方案。從eclipse項目配置開始,我在WebContent/WEB-INF目錄中有beans.xml。我仍然在登錄和密碼上得到空值。有任何想法嗎? – rivasket

+0

我不明白你是如何得到空值而不是例外。 – LightGuard

2

我認爲問題出在您的CredintialsBean類。您沒有爲bean指定範圍,因此它使用了默認範圍(有關更多信息,請參閱What is the default scope of a Named CDI bean?)。

如果您在類中添加類似@RequestScoped的內容,它應該可以工作。確保使用javax.enterprise.context.RequestScoped而不是javax.faces版本。