Why CDI don't inject my backing bean (session scope) in this ActionListener? The loginBean instance is always null. I have the impression that CDI does not manage the listener instances : it's right?
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
public class CancelListener implements javax.faces.event.ActionListener {
private LoginBean loginBean;
@Inject
public void setLoginBean(LoginBean loginBean) {
this.loginBean = loginBean;
}
@Override
public void processAction( ActionEvent event ) throws AbortProcessingException {
loginBean.setLogin( "" );
loginBean.setPassword( "" );
}
}
Here the definition of my LoginBean class.
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.inject.Named;
@Named
@SessionScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = -5433850275008415405L;
private String login = "james@mi6.uk";
private String password = "007";
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
And my listener is connected to the button with this code :
<h:commandButton value="Cancel" immediate="true">
<f:actionListener type="mypackage.CancelListener" />
</h:commandButton>
I know that i can use a method directly on the backing bean (connected with actionListener tag attribute), but I would like to understand how to make my class compatible with CDI and how to force the injection in this case. Thanks in advance.
You haven't explained why you need to use a bean that implements the ActionListener
interface, instead of using a method qualifier as actionListener
attribute inside the UIComponent.
As you seem to have already tried, making CancelListener
a CDI bean is not enough for having it instantiated correctly: LoginBean will be null.
However, using the binding
attribute will force JSF to dynamically instantiate the bean, and this will make the trick:
<h:commandButton value="Cancel" immediate="true">
<f:actionListener binding="#{cancelListener}" type="mypackage.CancelListener" />
</h:commandButton>
As mentioned above, the class implementing ActionListener
must be a CDI bean as well:
@Named
@SessionScoped
public class CancelListener implements Serializable, javax.faces.event.ActionListener {
@Inject
private LoginBean loginBean;
@Override
public void processAction(ActionEvent event) throws AbortProcessingException {
System.out.println(this.toString());
System.out.println(loginBean.toString());
}
}
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?