Problemas com <p:ajax [RESOLVIDO]

23 respostas
J

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

J

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

D

esta errado, o padrão é null

veja a pagina 19 do primefaces user guide

J

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:

D

tenta coloca o itemLabel e itemValue e faz um teste

J

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.

D

não esta aparecendo nada no seu log?

J

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.

J

seus managedBeans implementam Serializable?

J

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

J

Só colocar implements Serializable e declarar um atributo

private static final long serialVersionUID
J

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.

J

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

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?

J

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.

J

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

J

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.

J

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.

J

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 + '}';
  }
}
J

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á.

J

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.

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.

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.

J

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