2012-01-06 46 views
0

我在我的應用程序中有一個奇怪的行爲: 我使用SessionScope bean(Bean A)來保存用戶首選項。在RequestScope中的其他Bean(Bean B)中,我注入了SessionScope bean。在其他SessionScoped Bean在JSF2/CDI中更新之前調用@PostConstruct?

豆B有@PostConstruct方法來從數據庫中檢索根據應用會很困惑,在豆A.價值,當用戶改變bean中的價值及其在豆B值是不正確的值的列表在@PostConstruct方法被調用時。我用日誌測試了它。

我認爲在調用應用程序階段之前,所有的setter方法都會被更新?

下面是一個代碼示例:

豆答:

@Named 
@SessionScoped 
public class SessionBean implements Serializable { 
private static final long serialVersionUID = -4214048619877179708L; 

@Inject private Logger log; 
private BankAccount selectedBankAccount; 

public BankAccount getSelectedBankAccount() { 
    return selectedBankAccount; 
} 

public void setSelectedBankAccount(BankAccount selectedBankAccount) { 
    log.info("ba: " + selectedBankAccount); 
    this.selectedBankAccount = selectedBankAccount; 
} 

豆B:

@RequestScoped 
public class SubAccountListProducer { 
    @Inject private SessionBean sessionBean; 
    @Inject private EntityManager em; 

@PostConstruct 
public void retrieveAllSubAccount() { 
    CriteriaBuilder cb = em.getCriteriaBuilder(); 
    CriteriaQuery<SubAccount> criteria = cb.createQuery(SubAccount.class); 
    Root<SubAccount> account = criteria.from(SubAccount.class); 
    log.info("retrieveAllSubAccount: " + sessionBean.getSelectedBankAccount()); 
    criteria.select(account).where(cb.equal(account.get("bankAccount"), sessionBean.getSelectedBankAccount())); 
    criteria.select(account).orderBy(cb.desc(account.get("name"))); 
    entityList = em.createQuery(criteria).getResultList(); 
} 

抽樣日誌:

ba: BankAccount [accountId=123456789, bankName=Ing DiBa, blz=50010517] 
retrieveAllSubAccount: BankAccount [accountId=123456789, bankName=Ing DiBa, blz=50010517] 
retrieveAllSubAccount: BankAccount [accountId=123456789, bankName=Ing DiBa, blz=50010517] 
ba: BankAccount [accountId=987654321, bankName=Barclaycard Barclays Bank, blz=20130600] 

正如你可以看到..前兩個日誌是正確的...如果用戶更改首選項(更新SessionBean),該視圖將使用JSF重新展現,並且最後兩個日誌的順序不正確,我的應用程序會感到困惑。

謝謝你的幫助。

回答

2

@PostConstruct過程中調用動作階段不執行。它在bean的構建後直接執行。 PostConstruct應該只用於預先初始化一些東西,這取決於bean構建後直接注入的依賴關係。由於您的bean是請求作用域而不是對話作用域(或視圖作用域),因此它將在每個請求上構建。

您需要在實際操作方法中執行更新/刷新作業,而不是您在<h:commandButton>/<h:commandLink>中指定的方法。例如。

<h:commandButton value="Submit" action="#{bean.submit}" /> 

public void submit() { 
    // ... 

    retrieveAllSubAccount(); 
} 

我也建議把你的bean在CDI談話範圍或JSF的視圖範圍內,這樣纔不會不必要地得到重建的每個回發到相同的觀點。

+0

謝謝BalusC。我猜到了,並從該方法中刪除@PostConstruct,並從視圖的getter中調用它作爲快速解決方法。這現在起作用。實際上,我通過一個maven原型得到了這個結果,並且會告訴jboss這些人不推薦這樣做。 – SpecialAgent 2012-01-06 13:31:59

+0

不,@ @ PostConstruct在那裏很好。你只是誤解了它的用途。它是在bean的構建之後直接預先初始化的。每個HTTP請求都構造一個請求作用域bean。這一切都是通過規範。如果要調用表單提交操作(例如,保存已編輯的項目並重新加載列表以供顯示),則需要執行指定操作方法中的作業。 – BalusC 2012-01-06 13:35:44