2016-03-25 32 views
0

我使用JSF 2.2和CDI。我創建了下面的例子來向你展示我的問題的核心。你可以看到如下:@對象的注入和對象的兩種不同行爲

  • 兩個XHTML頁面,
  • 會話範圍的CDI豆(LoginController),這是XHTML的第1頁控制器,
  • 視圖範圍的CDI豆(DataController),這是控制器對於xhtml頁面2,
  • 請求範圍CDI bean(DataServiceImpl),它是DataController bean的服務。

這是一個用例和數據的流程:

XHTML第2頁 - >的DataController控制器 - >調用dataService.addData()send()方法(其位於DataController類) - >執行addData()方法(它位於DataServiceImpl類)

我的問題的心臟:

  • 如果我注入LoginControllerDataServiceImpl類,loginController對象不起作用(即,它返回null)[下面代碼中的選項1]。
  • 如果我將LoginController注入DataController類,loginController對象正常工作(即它返回我想要的)[下面代碼中的選項2]。

我的問題是:爲什麼這個注入的對象有兩種不同的方式取決於注入的位置?

這是我的XHTML 1頁的部分:

<h:form>    

    <p:growl id="growl" showDetail="false" /> 

    <h:inputText id="username" value="#{userLogin.username}" label="Username" required="true" requiredMessage="Username: This field is required." title="Enter your username." pt:placeholder="Username" /> 
    <h:inputSecret id="password" value="#{userLogin.password}" label="Password" required="true" requiredMessage="Password: This field is required." title="Enter your password." pt:placeholder="Password" /> 
    <p:commandButton value="Login" action="#{loginController.login}" update="growl" />     

</h:form> 

這是我的XHTML 2頁的部分:

<h:form>  

    <p:growl id="growl" showDetail="false" /> 

    <p:panelGrid id="panel" columns="2" styleClass="ui-noborder" columnClasses="rightalign,leftalign"> 
     <p:outputLabel for="data" value="Data:" /> 
     <p:inputText id="data" value="#{data.text}" required="true" requiredMessage="Data: This field is required." /> 
     <p:commandButton id="buttonSend" value="Send" action="#{dataController.send()}" update="messages" />       
    </p:panelGrid>            

</h:form> 

這是會話範圍的CDI豆:

@Named 
@SessionScoped 
public class LoginController implements Serializable { 

    private static final long serialVersionUID = -6322113716363932422L; 

    public String login(){  

     if(userService.login(userLogin)){ 

      currentUser=userService.getCurrnetUser(userLogin.getUsername()); 
      return "home?faces-redirect=true";   
     } 
     else{ 

      facesContext.addMessage(null, new FacesMessage("Data entered are incorrect")); 
      return null; 
     } 
    } 

    public String logout(){ 

     currentUser=null; 
     return "login?faces-redirect=true"; 
    } 

    public boolean isLoggedIn() { 

      return currentUser!=null; 
    } 

    @Produces 
    @LoggedIn 
    public UserAccount getCurrentUser(){ 

     return currentUser; 
    } 

    @Inject 
    private FacesContext facesContext; 

    @Inject 
    private UserServiceImpl userService; 

    @Named 
    @Produces 
    @RequestScoped 
    private UserAccount userLogin=new UserAccount(); 

    private UserAccount currentUser; 
} 

這是視圖範圍的CDI bean:

@Named 
@ViewScoped 
public class DataController implements Serializable { 

    private static final long serialVersionUID = 1383572529241805730L; 

    public void send(){ 

     /* OPTION 2 
     * If I inject the LoginController here 
     * instead of in DataServiceImpl bean, the loginController object 
     * works fine (i.e. it isn't null and returns the name of the user). 
     */ 
     String name=loginController.getCurrentUser().getName(); 

     dataService=new DataServiceImpl(); 
     dataService.addData(data.getText); 
    } 

    @Named 
    @Produces 
    @RequestScoped 
    private Data data=new Data(); 

    @Inject 
    private DataService dataService; 

    @Inject 
    private LoginController loginController;  
} 

這是請求範圍CDI豆:

@Named 
@RequestScoped 
public class DataServiceImpl implements DataService { 

    @Override 
    public void addData(String data) { 

     /* OPTION 1 
     * If I inject the LoginController here 
     * instead of DataController bean, the loginController object 
     * doesn't work (i.e. returns null. I get the NullPointerException exception 
     * in line below due to the loginController object which is null) 
     */ 
     String name=loginController.getCurrentUser().getName(); 

     //Proccess some data 
    } 

    @Inject 
    private LoginController loginController; 
} 
+0

我認爲bean的範圍與注入行爲有很大關係。 –

+0

這可能是對的。我也測試瞭如果我改變'DataController' bean的範圍會發生什麼。如果我使用'@ RequestScoped'註釋代替'DataController' bean的'@ ViewScoped'註釋,它和以前一樣。也許CDI不支持我發明的這種用例。 – Robert

回答

0

我真的不明白你的設計,這可能是問題的一部分。

您不應該將控制器注入另一個控制器,或者將控制器注入到服務中。

看到你的LoginController產生一個@LoggedIn UserAccount,爲什麼不簡單地注入,而不是注入loginController並呼籲loginController.getCurrentUser().getName()

+0

在這種情況下注入控制器到服務 - 我不應該或我不能?看到我的實驗結果 - 我想我不能,但我想知道爲什麼。如果CDI不支持/提供這樣的用例,那對我來說就足夠了。你是對的 - 我可以在'DataController' bean或'DataServiceImpl' bean中注入:'@LoggedIn UserAccount currentUser',而不是'LoginController'。這是更好的靈魂,但它與注入'LoginController'(即如果我在'DataServiceImpl' bean中調用'currentUser.getName()','currnetUser'對象爲'null')一樣。 – Robert

相關問題