f:ValueChangeListener nullifying EJB injection
It loads stateList fine, but when I change the value of a state, it calls the backbean but addressBO is null. How can I fix it? Any other way to do it?
Thanks in advance.
<h:selectOneMenu id="stateList" value="#{newUserController.address.stateID}">
<f:selectItems value="#{addressController.stateList}" />
<f:valueChangeListener type="controller.address.AddressController"/>
<f:ajax event="change" render="cidadeList"/>
</h:selectOneMenu>
<h:selectOneMenu id="cityList" value="#{newUserController.address.cityID}">
<f:selectItems value="#{addressController.cityList}" />
</h:selectOneMenu>
BackBean
package controller.address;
@ManagedBean
@RequestScoped
public class AddressController implements ValueChangeListener {
@EJB
private AddressBO addressBO;
@PostConstruct
public void firstT开发者_StackOverflow中文版hingToDo() {
stateList = enderecoBO.loadStateListSelectItem();
}
@Override
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException {
String state = (String) event.getNewValue();
cityList = addressBO.loadCityList(state);
}
}
The other backbean that set's the value of address and user that is not appearing in this case.
package controller.user;
@ManagedBean
@RequestScoped
public class NewUserController {
private Address address;
private User user;
@EJB
private NewUserBO newUserBO;
public void registerNewUser() {
newUserBO.register(user, address);
}
public Address getAddress() {
return this.address;
}
public void setAddress(Address address) {
this.address = address;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
}
The first problem is that you're creating a brand new instance of the class in the <f:valueChangeListener>
tag. This is not the same instance as referenced by @ManagedBean
and managed bean related annotations won't be invoked on that as well. You would rather like to use valueChangeListener="#{addressController.processValueChange}"
on the <h:selectOneMenu>
instead. But that doesn't immediately solve everything. The change is big that the second list don't behave as expected.
The second problem is that the value change listener method is invoked during Validations phase. This is the wrong moment to change/load model values. You should do this during Invoke Action phase. Use the listener
attribute of <f:ajax>
.
So:
<h:selectOneMenu id="stateList" value="#{newUserController.address.stateID}">
<f:selectItems value="#{addressController.stateList}" />
<f:ajax listener="#{addressController.changeState}" render="cidadeList" />
</h:selectOneMenu>
with
@ManagedBean
@RequestScoped
public class AddressController {
@EJB
private AddressBO addressBO;
@PostConstruct
public void init() {
stateList = enderecoBO.loadStateListSelectItem();
}
public void changeState(AjaxBehaviorEvent event) {
String state = (String) ((UIInput) event.getComponent()).getValue();
cityList = addressBO.loadCityList(state);
}
// ...
}
精彩评论