Question

i have a strange behaviour in my app: I use a SessionScope bean (Bean A) to hold users preferences. In my other Bean (Bean B), which is in RequestScope, I inject the SessionScope bean.

Bean B has a @PostConstruct method to retrieve a list of values from the database depending on the value in Bean A. The application gets confused when the user changes the value in Bean A and its value in Bean B is not correct at the time @PostConstruct method is invoked. I tested it with logs.

I think all setter methods will be updated before Invoke Application Phase?

Here is a code sample:

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();
}

Sample logs:

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]

As you can see... the first two logs are correct... if the user changes preferences (updates the SessionBean), the view will be rerendered with JSF and the last two logs are not in correct order and my app gets confused.

Thank you for help.

Was it helpful?

Solution

The @PostConstruct is not executed during invoke action phase. It is executed directly after bean's construction. The PostConstruct should only be used to preinitialize some stuff depending on injected dependencies directly after bean's construction. Because your bean is request scoped instead of conversation scoped (or view scoped), it will be constructed on every single request.

You need to do the updating/refreshing job in the real action method instead, which is the method you've specified in the <h:commandButton>/<h:commandLink>. E.g.

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

with

public void submit() {
    // ...

    retrieveAllSubAccount();
}

I also suggest to put your bean in the CDI conversation scope or JSF view scope, so that it don't unnecessarily get reconstructed on every postback to the same view.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top