2012-01-06 4 views
0

У меня странное поведение в моем приложении: Я использую компонент SessionScope (Bean A), чтобы удержать предпочтения пользователей. В моем другом Bean (Bean B), который находится в RequestScope, я добавляю компонент SessionScope.@PostConstruct, вызываемый перед другим SessionScoped Bean, обновленным в JSF2/CDI?

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

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

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

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

Благодарим за помощь.

ответ

2

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

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

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

с

public void submit() { 
    // ... 

    retrieveAllSubAccount(); 
} 

Я также предлагаю, чтобы положить фасоль в рамках КДИ разговора или JSF зрения объема, так что он не излишне получить перестраивается на каждом постбэка в ту же точку зрения.

+0

Спасибо BalusC. Я догадался, что и удалил @PostConstruct из этого метода и вызвал его из геттера для представления в качестве быстрой работы. Это работает сейчас. На самом деле я получил это по архетипу maven и расскажу ребятам из jboss, что это не рекомендуется. – SpecialAgent

+0

Нет, '@ PostConstruct' там в порядке. Вы просто не понимаете, для чего это нужно использовать. Это должно быть preinitialize вещи непосредственно после строительства фасоли. Объект, обработанный запросом, создается по каждому HTTP-запросу. Это все по спецификации. Если вы хотите вызвать действие отправки формы (например, сохранить отредактированный элемент и перезагрузить список для отображения), вам необходимо выполнить задание в указанном выше методе действий. – BalusC

Смежные вопросы