Search code examples
jsfsetpropertyactionlistener

setPropertyActionListener not working after a action


I have a grid with a list of objects and I am trying to create a basic CRUD. Updates and deletes are going quite fine and without any problems, however, when I try to perform a edit on the selected object the setPropertyActionListener that I've set isn't performing as expected. I've searched on several threads but no success.

Here goes my code:

On my crud-aplicacoes.html I gotta a grid and this is the code of my button where I set my setPropertyActionListener and also my action which goes to action ="editar-aplicacao" that is another page. I'm getting my property aplicacaoSelecionada always null.

<p:commandButton icon="ui-icon-pencil"
                        title="#{msg['label.button.editar']}" action="editar-aplicacao"
                        actionListener="#{aplicacoesMB.editarAplicacao}">
                        <f:setPropertyActionListener
                            target="#{aplicacoesMB.aplicacaoSelecionada}" value="#{app}" />

                    </p:commandButton>

My managed bean:

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;

import org.primefaces.model.DualListModel;

import br.com.cnen.enums.SituacaoAplicacaoeEnum;
import br.com.cnen.vo.AplicacaoVO;
import br.com.cnen.vo.PerfilVO;
import br.com.cnen.web.facade.AplicacoesFacade;

@RequestScoped
@ManagedBean(name = "aplicacoesMB")
public class AplicacoesMB extends BeanAbstract {


    private static final long serialVersionUID = 1L;

    private List<AplicacaoVO> listaAplicacoes;

    private AplicacaoVO aplicacaoSelecionada;

    private PerfilVO perfilSelecionado;

    private boolean edicaoExibicao;

    @Inject
    private AplicacoesFacade facadeAplicacao;

    private List<PerfilVO> source;
    private List<PerfilVO> target;
    private DualListModel<PerfilVO> dualListPerfil;

    @PostConstruct
    public void carregarAplicacoes() {
        listaAplicacoes = facadeAplicacao.listarTodos();
        this.edicaoExibicao = false;
        dualListPerfil = new DualListModel<PerfilVO>();
    }

    public List<PerfilVO> perfis() {
        return facadeAplicacao.carregarComboPerfis();
    }

    public List<SituacaoAplicacaoeEnum> comboStatus() {
        List<SituacaoAplicacaoeEnum> lista = new ArrayList<SituacaoAplicacaoeEnum>();
        for (SituacaoAplicacaoeEnum current : SituacaoAplicacaoeEnum.values()) {
            lista.add(current);
        }
        return lista;
    }

    public String editarAplicacao() {
        this.edicaoExibicao = false;
        pickList();
        return "editar-aplicacao";
    }

    public String visualizarAplicacao() {
        this.edicaoExibicao = true;
        return "editar-aplicacao";
    }

    public void excluirAplicacao() {
        facadeAplicacao.remover(this.aplicacaoSelecionada);
        this.carregarAplicacoes();
        this.addMensagem("A exclusão foi realizada com sucesso.", FacesMessage.SEVERITY_INFO);
    }

    public void bloquearAplicacao() {
        this.aplicacaoSelecionada.setSituacao(SituacaoAplicacaoeEnum.BLOQUEADO);
        facadeAplicacao.bloquear(this.aplicacaoSelecionada);
        this.addMensagem("O bloqueio foi realizado com sucesso!", FacesMessage.SEVERITY_INFO);
    }

    public void desbloquearAplicacao() {
        this.aplicacaoSelecionada
                .setSituacao(SituacaoAplicacaoeEnum.DESBLOQUEADO);
        facadeAplicacao.desbloquear(this.aplicacaoSelecionada);
        this.addMensagem("O desbloqueio com sucesso!", FacesMessage.SEVERITY_INFO);
    }

    public void alterarAplicacao(){
        facadeAplicacao.alterar(aplicacaoSelecionada);
        this.addMensagem("O atualização foi realizada com sucesso!", FacesMessage.SEVERITY_INFO);
    }

    public void addPerfil(){

    }

    public void pickList(){
        source = facadeAplicacao.carregarComboPerfis();
        target = new ArrayList<PerfilVO>();

        if(aplicacaoSelecionada!=null)
            target = aplicacaoSelecionada.getListaPerfis();
        dualListPerfil = new DualListModel<PerfilVO>(source, target);
    }

    /**
     * 
     * Getts and setters
     * 
     */
    public List<AplicacaoVO> getListaAplicacoes() {
        return listaAplicacoes;
    }

    public AplicacaoVO getAplicacaoSelecionada() {
        return aplicacaoSelecionada;
    }

    public void setAplicacaoSelecionada(AplicacaoVO aplicacaoSelecionada) {
        this.aplicacaoSelecionada = aplicacaoSelecionada;
        System.out.println("-> "+ aplicacaoSelecionada.getAplicaoId());
    }

    public PerfilVO getPerfilSelecionado() {
        return perfilSelecionado;
    }

    public void setPerfilSelecionado(PerfilVO perfilSelecionado) {
        this.perfilSelecionado = perfilSelecionado;
    }

    public boolean isEdicaoExibicao() {
        return edicaoExibicao;
    }

    public List<PerfilVO> getSource() {
        return source;
    }

    public void setSource(List<PerfilVO> source) {
        this.source = source;
    }

    public List<PerfilVO> getTarget() {
        return target;
    }

    public void setTarget(List<PerfilVO> target) {
        this.target = target;
    }

    public DualListModel<PerfilVO> getDualListPerfil() {
        return dualListPerfil;
    }

    public void setDualListPerfil(DualListModel<PerfilVO> dualListPerfil) {
        this.dualListPerfil = dualListPerfil;
    }


}

On my editarAplicacao() I can't access the property because it is always going null. Any thoughts on this issue?


Solution

  • Your concrete problem is caused by (ab)using actionListener instead of action to perform a business action. All actionListeners are invoked in the very same order as they have been attached on the component and then finally the action is invoked.

    In other words, the <f:setPropertyActionListener> is in your particular case invoked after #{aplicacoesMB.editarAplicacao}, which totally explains the symptom you're seeing of the property not being set.

    Fix actionListener to be action.

    action="#{aplicacoesMB.editarAplicacao}"
    

    Additionally, you can also get rid of <f:propertyActionListener> altogether and pass the property as action method argument.

    action="#{aplicacoesMB.editarAplicacao(app)}"
    

    with

    public String editarAplicacao(AplicacaoVO aplicacaoSelecionada) {
        // ...
    }
    

    See also: