简体   繁体   中英

JSF/CDI dependency injection into ActionListener

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM