I have two ManagedBeans (SessionHandler and OrderHandler). Both are session scoped.
SessionHandler:
@ManagedBean(name="session")
@SessionScoped
public class SessionHandler {
private Account account;
public String login() {
try {
// ... login method ...
return("bookinglist.xhtml?faces-redirect=true");
}
catch (Exception e) {
// ... exception handling ...
}
}
// ... getter & setter ...
}
OrderHandler:
@ManagedBean(name="order")
@SessionScoped
public class OrderHandler {
@ManagedProperty(value="#{session.account}")
Account account; // getter and setter
public OrderHandler() {
this.createList();
}
private void createList() {
// method creates an ArrayList of bookings
// it uses this.account.getId() for a SQL statement
}
}
In bookinglist.xhtml I want to display a welcome text and my list:
<p>Welcome, #{sessions.account.name}!</p>
<ui:repeat value="#{order.bookingList}" var="item">
<!-- ... items ... --->
</ui:repeat>
The welcome text is displayed, but my list is empty because in my sql statement the accountID is null. A statement with accountID = 1 (as example) works. Later in the booking process I can use the accountID (without doing anything to redeclare or overwrite it).
I guess the problem is, that the property isn't available immediately after the login... But I don't know why. Can someone help me?
When using @ManagedProperty
, one important fact to keep in mind of is that such property will be injected once after bean constructor is called. The reason is because JSF can only inject a property when the bean is fully constructed.
In effect, it means that, from your current code, account
will be injected after createList()
is called. If you debug OrderHandler
, you will very likely see the following execution sequence:
// bean instantiation step
-> OrderHandler constructor called
-> createList called
// bean property injection step
-> Account injected
To solve this, you need to call createList()
after constructor is finished, and account
is already injected. You can achieve that with a method with @PostConstruct
annotation:
@PostConstruct
private void init() {
// this will be called after constructor call, and property injection
this.createList();
}
You can read more about @PostConstruct
annotation here:
http://docs.oracle.com/javaee/7/api/javax/annotation/PostConstruct.html