Problemas com <p:ajax [RESOLVIDO]

23 respostas
jonas.cant

Tenho o seguinte combobox:

<h:form id="formConCliente">
				<p:panel header="Testando">			
					<h:outputLabel for="pais" value="País:" />
					<p:selectOneMenu id="pais" value="#{paisController.pais}">
						<f:selectItem itemLabel="Selecione..." itemValue="" />
						<f:selectItems value="#{paisController.listaPaisesCombo}" />
						<p:ajax listener="#{paisController.actionCarregaUFs}" />
					</p:selectOneMenu>
				</p:panel>
			</h:form>

Código do bean:

package control;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;

import model.Pais;
import model.UnidadeFederacao;
import dao.PaisDao;
import dao.PaisDaoImp;
import dao.UnidadeFederacaoDao;
import dao.UnidadeFederacaoDaoImp;

@ManagedBean
@ViewScoped
public class PaisController implements Serializable {

	private Pais pais;
	private DataModel listaPaises;
	private List<Pais> filteredPaises;
	private Boolean isInsercao;
	private Boolean isAlteracao;
	private List<SelectItem> ufs = new ArrayList<SelectItem>();
	private List<SelectItem> listaPaisesCombo;			

	public List<Pais> getFilteredPaises() {
		return filteredPaises;
	}

	public void setFilteredPaises(List<Pais> filteredPaises) {
		this.filteredPaises = filteredPaises;
	}

	public DataModel getListarPaises() {
		List<Pais> lista = new PaisDaoImp().list();
		listaPaises = new ListDataModel(lista);
		return listaPaises;
	}
	
	public void setListaPaisesCombo(List<SelectItem> listaPaisesCombo) {
		this.listaPaisesCombo = listaPaisesCombo;
	}	

	public List<SelectItem> getListaPaisesCombo() {
		List<SelectItem> listaCombo = new ArrayList<SelectItem>();
		List<Pais> lista = new PaisDaoImp().list();
		
		PaisDao pd = new PaisDaoImp();
				
		for (int i = 1; i <= lista.size(); i++) {
			SelectItem item = new SelectItem();			
			item.setLabel(lista.get(i - 1).getNome());	
			//item.setValue(pd.findById(lista.get(i - 1).getCodigo()));
			item.setValue(lista.get(i - 1));
			
			listaCombo.add(item);
		}
		
		listaPaisesCombo = listaCombo;
		
		return listaPaisesCombo;
	}
	
	public List<SelectItem> getUFsByPais() {		
		List<SelectItem> listaCombo = new ArrayList<SelectItem>();						
		List<UnidadeFederacao> lista = new PaisDaoImp().getUFsByPais(this.pais.getCodigo());
		
		UnidadeFederacaoDao uf = new UnidadeFederacaoDaoImp();
		
		for (int i = 1; i <= lista.size(); i++) {
			SelectItem item = new SelectItem();			
			item.setLabel(lista.get(i - 1).getNome());						
			item.setValue(uf.findById(lista.get(i - 1).getCodigo()));
			listaCombo.add(item);			
		}
		
		return listaCombo;
	}
	
	public void actionCarregaUFs() {
		System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

		//this.ufs = this.getUFsByPais();
	}	
	

	public Pais getPais() {
		return pais;
	}

	public void setPais(Pais pais) {
		this.pais = pais;
	}

	public String prepararAdicionarPais() {
		pais = new Pais();
		isInsercao = true;
		isAlteracao = false;
		return "gerenciarPais";
	}

	public String prepararAlterarPais() {
		pais = (Pais) (listaPaises.getRowData());
		isInsercao = false;
		isAlteracao = true;
		return "gerenciarPais";
	}

	public String excluirPais() {
		Pais paisTemp = (Pais) (listaPaises.getRowData());
		PaisDao dao = new PaisDaoImp();
		dao.remove(paisTemp);
		return "index";
	}

	public String adicionarPais() {
		PaisDao dao = new PaisDaoImp();
		dao.save(pais);
		return "index";
	}

	public String alterarPais() {
		PaisDao dao = new PaisDaoImp();
		dao.update(pais);
		return "index";
	}

	public Boolean getIsInsercao() {
		return isInsercao;
	}

	public void setIsInsercao(Boolean insercao) {
		this.isInsercao = insercao;
	}

	public Boolean getIsAlteracao() {
		return isAlteracao;
	}

	public void setIsAlteracao(Boolean alteracao) {
		this.isAlteracao = alteracao;
	}

	public List<SelectItem> getUfs() {
		return ufs;
	}

	public void setUfs(List<SelectItem> ufs) {
		this.ufs = ufs;
	}
	
}

Meu problema é bem estranho: por padrão no combobox vem o item “Selecione…”, e logo após vem “Brasil, “Argentina”, “Uruguai”, etc…
O método ‘paisController.actionCarregaUFs’ deveria ser executado cada vez que eu mudasse o item do combo, só que acontece o seguinte: ao carregar a página, vem listados os países no combo e por default vem o item ‘Selecione…’. Se eu clicar no combo e mudar para ‘Brasil’, o método não executa, porém se eu voltar para o item 'Selecione…” o método é executado. Ele deveria ser executado quando eu mudei para ‘Brasil’! O método só executa quando eu volto para ‘Selecione…’, mudando para qualquer outro item do combo o método não executa!
O que tem de errado? O que eu devo fazer? Por favor, ficarei muito grato se alguém puder me ajudar.

23 Respostas

S

não ta faltando o evento ai não!?

<p:ajax event=“change” listener""/>

testa ai creio que seja isso!

abraço

jonas.cant

Não… o event=“change” é por padrão caso ele for omitido.

DaniloAndrade

esta errado, o padrão é null

veja a pagina 19 do primefaces user guide

jonas.cant

Ok, desculpe a informação errada. Colocando o ‘event=“change”’ ou não colocando, dá na mesma (no meu caso). Encontrei aqui no fórum uma pessoa que estava com a mesma situação que a minha, mas pra ele o problema foi resolvido colocando o o escopo do bean como @ViewScoped. O meu bean já está com @ViewScoped e mesmo assim não funciona. O evento só é acionado quando é selecionado o item ‘Selecione…’.
Preciso muito resolver esse problema. :cry:

DaniloAndrade

tenta coloca o itemLabel e itemValue e faz um teste

jonas.cant

Mas o que eu colocaria no “itemLabel” e 'itemValue" já que estou usando uma lista de SelecItem? O SelecItem já tem “dentro” dele o “itemLabel” e “itemValue”.
P.S.: tentei colocar o “itemLabel” e “itemValue” com vazio e não funcionou.

DaniloAndrade

não esta aparecendo nada no seu log?

jonas.cant

Acredito que não tenha nada a ver com o meu problema, mas quando eu reinicio o server, dá a seguinte exceção:

java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: control.PaisController

Caused by: java.io.NotSerializableException: control.PaisControlle

Quando estou testando o combobox, mudando de itens, não dá mensagem nenhuma no console do servidor.

jhoamaral

seus managedBeans implementam Serializable?

jonas.cant

Não. Basta eu colocar “implements Serializable” ou preciso criar algum método?

jhoamaral

Só colocar implements Serializable e declarar um atributo

private static final long serialVersionUID
juno.rr

Amigo, não é o teu <f:selectItems> que está errado? Pra mim que faltaram atributos.
Eu usaria assim:

&lt;f:selectItems value="#{paisController.paises}" var="pais" itemLabel="#{pais.nome}" itemValue="#{pais}"/&gt;

Mas como nunca usei com o objeto SelectItem, posso ta falando besteira.
Abraço.

jonas.cant

O SelectItem já possui o itemLabel e itemValue.
Repare o código que estou usando:

public List<SelectItem> getListarPaisesCombo() {
		List<SelectItem> listaCombo = new ArrayList<SelectItem>();
		List<Pais> lista = new PaisDaoImp().list();
		
		PaisDao pd = new PaisDaoImp();
				
		for (int i = 1; i <= lista.size(); i++) {
			SelectItem item = new SelectItem();			
			item.setLabel(lista.get(i - 1).getNome());						
                        item.setValue(lista.get(i - 1));
			listaCombo.add(item);
		}
				
		return listaCombo;
	}
jhoamaral

Você esta setando o objeto Pais direto no sectItem, mas não especificou nenhum Converter. Acredito que tenha que criar um Converter para suas classes.
Não está aparecendo nenhum erro no console?

jonas.cant

Não utilizo Converter. O código abaixo supostamente substituiria o conversor, pois estou passando um SelectItem:

public List<SelectItem> getListarPaisesCombo() {
		List<SelectItem> listaCombo = new ArrayList<SelectItem>();
		List<Pais> lista = new PaisDaoImp().list();
		
		PaisDao pd = new PaisDaoImp();
				
		for (int i = 1; i <= lista.size(); i++) {
			SelectItem item = new SelectItem();			
			item.setLabel(lista.get(i - 1).getNome());						
                        item.setValue(lista.get(i - 1));
			listaCombo.add(item);
		}
				
		return listaCombo;
	}

E não aparece nenhuma mensagem de erro. O SelectOneMenu espera um objeto do tipo Pais, e é isso que os itens estão devolvendo.

jonas.cant

Alguém com mais alguma sugestão? Estou a ponto de largar de mão e partir pra outra linguagem… :frowning:

jhoamaral

Desconheço o fato de não precisar de Converter quando se utiliza uma lista de SelectItem, tem certeza disso?

Qual o servidor de aplicação que vc está utilizando? Pode ser um problema da configuração do log no servidor não está sendo exibida mensagem de erro.

jhoamaral

Retorna um List de Pais e usa essa abordagem

<p:selectOneMenu value="#{autoCompleteBean.selectedPlayer1}" converter="player">  
      <f:selectItem itemLabel="Select One" itemValue="" />  
      <f:selectItems value="#{autoCompleteBean.players}" var="player" itemLabel="#{player.name}" itemValue="#{player}"/>  
</p:selectOneMenu>

Você evita um for dentro do código pra popular os SelectItems.

juno.rr

Meu, olha só, tentei simular o problema aqui e o que descobri é que não funciona se vc setar o objeto Pais no controlador, vc precisa setar uma String e através dela encontrar o Pais correspondente.
Provavelmente é o que o outro colega falou, ta faltando um converter.

Segue o código q usei pra fazer funcionar:

&lt;?xml version='1.0' encoding='UTF-8' ?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"&gt;

  &lt;h:body&gt;
    &lt;h:head&gt;
      &lt;style type="text/css"&gt;
        #select {
          position: relative;
          top: 8px;
        }
        #paisOutput {
          border: 1px solid black;
          width: 200px;
        }
      &lt;/style&gt;
    &lt;/h:head&gt;
    &lt;h:form prependId="false" id="form1"&gt;

      &lt;p:panel header="Selecione um país"&gt;
        &lt;p:outputLabel id="label" for="select" value="País:"/&gt;
        &lt;p:selectOneMenu value="#{paisController.selected}" id="select"&gt;
          &lt;f:selectItem itemLabel="Selecione..." itemValue="#{null}"/&gt;
          &lt;f:selectItems value="#{paisController.paises}" var="pais"
                         itemLabel="#{pais.name} - #{pais.acronym}"
                         itemValue="#{pais.acronym}"/&gt;
          &lt;p:ajax event="change" update="paisOutput"/&gt;
        &lt;/p:selectOneMenu&gt;
        
        <br/><br/>
        
        &lt;h:outputText id="paisOutput" value="#{paisController.pais}"/&gt;
      &lt;/p:panel&gt;
    
    &lt;/h:form&gt;
  &lt;/h:body&gt;
&lt;/html&gt;
package com.jpower.pstat;

import java.util.LinkedList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ViewScoped
@ManagedBean
public class PaisController {

  private List&lt;Pais&gt; paises;
  private String selected;
  private Pais pais;
  
  public PaisController() {
    paises = new LinkedList&lt;&gt;();
    selected = "null";
    pais = null;
    paises.add(new Pais("Brasil", "BR"));
    paises.add(new Pais("Uruguay", "UY"));
    paises.add(new Pais("Ucrania", "UA"));
  }

  public List&lt;Pais&gt; getPaises() {
    return paises;
  }

  public void setPaises(List&lt;Pais&gt; paises) {
    this.paises = paises;
  }

  public String getSelected() {
    return selected;
  }

  public void setSelected(String selected) {
    System.out.println("* setSelected: "+ selected);
    for(Pais p : paises) {
      if(p.getAcronym().equals(selected)) {
        pais = p;
        break;
      }
    }
    System.out.println("* pais: "+ pais);
  }

  public Pais getPais() {
    return pais;
  }
}
package com.jpower.pstat;

public class Pais {
  
  private String name;
  private String acronym;
  
  public Pais() {
    name = null;
    acronym = null;
  }
  
  public Pais(String name, String acronym) {
    this.name = name;
    this.acronym = acronym;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAcronym() {
    return acronym;
  }

  public void setAcronym(String acronym) {
    this.acronym = acronym;
  }

  @Override
  public String toString() {
    return "Pais{" + "name=" + name + ", acronym=" + acronym + '}';
  }
}
jonas.cant

Aí pessoal, o fato de não chamar o evento quando seleciono algum país foi resolvido colocando a propriedade immediate=“true” no SelectOneMenu.
Porém ainda não terminei com meu problema… O SelectOneMenu está assim:

<p:selectOneMenu id="pais" value="#{paisController.pais}" immediate="true" >
	<f:selectItem itemLabel="Selecione..." />
	<f:selectItems value="#{paisController.listaPaisesCombo}" />
	<p:ajax event="change" listener="#{paisController.actionCarregaUFs}" />
</p:selectOneMenu>

O problema agora é que ao selecionar algum país, não está sendo setado para o objeto ‘pais’ do bean. O objeto fica nulo. Enfim, minha próxima tentativa é implementar o Converter como alguns colegas já me sugeriram. Assim que eu tiver um tempinho eu vou tentar implementar e se der certo ou não eu voltarei aqui no tópico. Obrigado a todos desde já.

jonas.cant

Pessoal, consegui resolver o problema. Até que enfim!!!
O que eu fiz:

  • Implementei um converter para a classe Pais. Resultado: não funcionou!
  • Pesquisei em sites não brasileiros sobre o problema que eu enfrentava, descobri um fórum onde foi postado que na classe da entidade (no meu caso a classe Pais) eu deveria sobrescrever os métodos ‘equals’ e ‘hashCode’. Resultado: agora está funcionando e o ajax está invocando o método a cada troca de país do combobox.

Se alguém que entende do negócio souber me dar uma explicação do porquê ter funcionado, eu fico grato. Muito obrigado a todos que tentaram me ajudar, certamente foi útil e me fez correr atrás de outras soluções.

P.S.: continuo usando o converter, mas acredito que todo problema seria resolvido apenas sobrescrevendo os dois métodos que eu citei.

jhoamaral

jonas.cant:
Pessoal, consegui resolver o problema. Até que enfim!!!
O que eu fiz:

  • Implementei um converter para a classe Pais. Resultado: não funcionou!
  • Pesquisei em sites não brasileiros sobre o problema que eu enfrentava, descobri um fórum onde foi postado que na classe da entidade (no meu caso a classe Pais) eu deveria sobrescrever os métodos ‘equals’ e ‘hashCode’. Resultado: agora está funcionando e o ajax está invocando o método a cada troca de país do combobox.

Se alguém que entende do negócio souber me dar uma explicação do porquê ter funcionado, eu fico grato. Muito obrigado a todos que tentaram me ajudar, certamente foi útil e me fez correr atrás de outras soluções.

P.S.: continuo usando o converter, mas acredito que todo problema seria resolvido apenas sobrescrevendo os dois métodos que eu citei.

Para o converter funcionar voce precisa do equals e hashCode implementados pois o JSF vai comparar o objeto selecionado com os objetos que estão na lista do OneMenu para saber qual é o correto.
Tudo que vai pra pagina é convertido em String e de alguma forma tem que ser convertido de volta em Objeto para o bean.

jonas.cant

Então o problema era a falta do converter e a implementação do método equals e hashCode. Fica aí a solução pra quando outro inexperiente igual a mim tiver este problema. :slight_smile:
Muito obrigado pela resposta.

Criado 5 de março de 2013
Ultima resposta 6 de mar. de 2013
Respostas 23
Participantes 5