开发者

f:ValueChangeListener nullifying EJB injection

开发者 https://www.devze.com 2023-03-18 11:48 出处:网络
It loads stateList fine, but when I change the value of a state, it calls the backbean but addressBO is null.

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

    // ... 
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号