@PostConstruct вызывается до того, как другой компонент SessionScoped обновляется в JSF2 / CDI? - PullRequest
0 голосов
/ 06 января 2012

У меня странное поведение в приложении: я использую компонент SessionScope (компонент A) для хранения пользовательских настроек.В моем другом Bean-компоненте (Bean B), который находится в RequestScope, я внедряю bean-компонент SessionScope.

Bean B имеет метод @PostConstruct для получения списка значений из базы данных в зависимости от значения в Bean A.Приложение сбивается с толку, когда пользователь изменяет значение в Bean A, и его значение в Bean B неверно во время вызова метода @PostConstruct.Я проверил это с помощью журналов.

Я думаю, что все методы установки будут обновлены до фазы вызова приложения?

Вот пример кода:

Bean A:

@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;
}

Bean 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, а последние два журнала не в правильном порядке, и мое приложение запуталось.

Спасибо за помощь.

1 Ответ

2 голосов
/ 06 января 2012

@PostConstruct не выполняется во время фазы действия вызова. Он выполняется сразу после постройки бобов. PostConstruct следует использовать только для предварительной инициализации некоторых вещей в зависимости от введенных зависимостей непосредственно после создания компонента. Поскольку ваш бин является областью запроса, а не областью диалога (или областью просмотра), он будет создан для каждого отдельного запроса.

Вместо этого вам нужно выполнить обновление / обновление в методе реальных действий, который вы указали в <h:commandButton> / <h:commandLink>. Э.Г.

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

с

public void submit() {
    // ...

    retrieveAllSubAccount();
}

Я также предлагаю поместить ваш bean-компонент в область диалога CDI или область просмотра JSF, чтобы он без необходимости не восстанавливался при каждой обратной передаче в одно и то же представление.

...