@PostConstruct вызывается до того, как другой компонент SessionScoped обновляется в JSF2 / CDI?
В моем приложении странное поведение: я использую компонент SessionScope (компонент A) для хранения пользовательских настроек. В моем другом компоненте (компоненте B), который находится в RequestScope, я внедряю компонент SessionScope.
В компоненте B есть метод @PostConstruct для получения списка значений из базы данных в зависимости от значения в компоненте A. Приложение сбивается с толку, когда пользователь изменяет значение в компоненте A, а его значение в компоненте B неверно в то время @ Метод PostConstruct вызывается. Я проверил это с журналами.
Я думаю, что все методы установки будут обновлены до фазы вызова приложения?
Вот пример кода:
Бин А:
@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;
}
Бин Б:
@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, а последние два журнала не в правильном порядке, и мое приложение запутается.
Спасибо за помощь.
1 ответ
@PostConstruct
не выполняется во время фазы действия invoke. Он выполняется сразу после постройки бобов. PostConstruct
должен использоваться только для предварительной инициализации некоторых вещей в зависимости от введенных зависимостей непосредственно после построения bean-компонента. Поскольку ваш bean-компонент является областью запроса, а не областью диалога (или областью просмотра), он будет создан для каждого отдельного запроса.
Вместо этого вам нужно выполнить обновление / обновление в методе реальных действий, который вы указали в <h:commandButton>
/<h:commandLink>
, Например
<h:commandButton value="Submit" action="#{bean.submit}" />
с
public void submit() {
// ...
retrieveAllSubAccount();
}
Я также предлагаю поместить ваш bean-компонент в область диалога CDI или область просмотра JSF, чтобы он без необходимости не восстанавливался при каждой обратной передаче в одно и то же представление.