AutoComplete com JPA - Erro de conversão

21 respostas
G

Boa Tarde Pessoal,

Estou com um problema para utilizar o AutoComplete do PrimeFaces… Estou usando Eclipse Juno, PrimeFaces 3.3 e Hibernate 4.1.7.

Estou tentando fazer um AutoComplete de uma lista de bairros.

Primeiro eu populo minha lista de bairros e depois tem o meu método complete que iria verificar a existência do bairro.

Provavelmente um dos meus métodos esta errado, teria como me dar uma ajudinha??

Valeuu

@SuppressWarnings("unchecked")
	public void preencheBairros() {
		this.bairros = new ArrayList<Bairro>();

		Session session = HibernateUtil.getSession();

		this.bairros = session.createCriteria(Bairro.class)
				.addOrder(Order.asc("nomeBairro")).list();

		session.close();
	}

	public List<String> complete(String busca) {
		List<String> retorno = new ArrayList<String>();
		for (Bairro bairro : bairros) {
			if (bairros.contains(busca)) {
				retorno.add(bairro);
			}
		}
		return retorno;
	}

O erro que aparece é esse: 

Nov 2, 2012 6:07:25 PM com.sun.faces.lifecycle.ApplyRequestValuesPhase execute
WARNING: /cadastroFuncionario.xhtml @51,63 completeMethod="#{cadastraFuncionariosBean.complete}": java.lang.NullPointerException
javax.el.ELException: /cadastroFuncionario.xhtml @51,63 completeMethod="#{cadastraFuncionariosBean.complete}": java.lang.NullPointerException
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:111)
	at org.primefaces.component.autocomplete.AutoComplete.broadcast(AutoComplete.java:340)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)

// restante do erro...

21 Respostas

G

Modifiquei meus métodos e criei um conversor. Mas agora esta dando o seguinte erro:

Nov 3, 2012 4:54:11 PM com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback visit
SEVERE: java.lang.ClassCastException: java.lang.String cannot be cast to modelo.Bairro

Meus métodos ficaram assim:

public List<Bairro> complete(String busca) throws Exception {
		this.bairros = funcionarioDao.listaTodos();
		List<Bairro> complete = new ArrayList<Bairro>();
		try {
			for (Bairro fore : this.bairros) {
				if (fore.getNomeBairro().contains(busca)) {
					complete.add(fore);
				}
			}
		} catch (Exception e) {
			FacesUtil.adiconarMensagem(FacesMessage.SEVERITY_ERROR, "Erro.",
					"Erro na listagem de bairros");
			e.printStackTrace();
		}
		return complete;
	}

Conversor

@FacesConverter(value = "bairroConverter")
public class BairroConverter implements Converter {

	@Override
	public Object getAsObject(FacesContext context, UIComponent component,
			String value) {
		FuncionarioDao funcionarioDao = new FuncionarioDao();
		Bairro bairro = null;
		try {
			bairro = funcionarioDao.buscaPorNome(value);
		} catch (Exception e) {
			FacesUtil.adiconarMensagem(FacesMessage.SEVERITY_FATAL,
					"Erro grave!!", "Erro no conversor de bairros");
			e.printStackTrace();
		}
		return bairro;
	}

	@Override
	public String getAsString(FacesContext context, UIComponent component,
			Object value) {
		Bairro bairro = new Bairro();
		bairro = (Bairro) value;
		return bairro.getNomeBairro();
	}

Não sei onde o que possa ser esse erro…

E

Poste aqui o código do xhtml com a chamada do autocomplete.

No teu complete tente colocar isso para ver se altera algo:

if (busca == null){ busca = ""; }

H

Aqui tem um exemplo de autocomplete funcionando: Aplicação Web Completa Tomcat JSF Primefaces JPA Hibernate.

G

edudebom:
Poste aqui o código do xhtml com a chamada do autocomplete.

No teu complete tente colocar isso para ver se altera algo:

if (busca == null){ busca = ""; }

Segue abaixo o xhtml:

<p:autoComplete value="#{cadastraFuncionariosBean.bairro}"
						completeMethod="#{cadastraFuncionariosBean.complete}" var="bairro"
						itemLabel="#{bairro.nomeBairro}" itemValue="bairro"
						converter="bairroConverter" />

Eu alterei tambem o meu conversor, deixei dessa forma:

Bairro bairro = new Bairro();
		try {
			bairro = (Bairro) value;
		} catch (Exception e) {
			FacesUtil.adiconarMensagem(FacesMessage.SEVERITY_FATAL, "Erro.",
					"Erro no conversor.");
			System.out.println("Erro na conversão");
			e.printStackTrace();
		}
		return bairro.getNomeBairro();
	}

O erro:

java.lang.ClassCastException: java.lang.String cannot be cast to modelo.Bairro
	at converter.BairroConverter.getAsString(BairroConverter.java:38)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeSuggestionsAsList(AutoCompleteRenderer.java:434)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeSuggestions(AutoCompleteRenderer.java:366)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeResults(AutoCompleteRenderer.java:116)
Erro na conversão
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeEnd(AutoCompleteRenderer.java:98)

Só isso serve?

vou testar isso que voce me falou…

E

Mude para

itemValue="#{bairro}"
G

[quote=edudebom]Mude para

itemValue="#{bairro}"

Era isso mesmo! Agora parou de dar o erro… nem acredito que era só isso… Pura falta de atenção minha.
O problema agora é que ele esta adicionando Null na tabela de bairro. Queria que ele já vinculasse o id do bairro existente… Já não era para fazer isso edudebom??

Valeu pela ajuda!

E

Teu converter está fazendo uma busca por nome. Faça ele buscar pela chave primária.

G

Hebert estou seguindo exemplo que voce citou mais estou me deparando com um erro na seguinte parte do conversor:

@Override
	public Object getAsObject(FacesContext context, UIComponent component,
			String value) {
		FuncionarioDao funcionarioDao = new FuncionarioDao();
		int bairroID;
		try {
			bairroID = Integer.parseInt(value);
		} catch (NumberFormatException exception) {
			throw new ConverterException(new FacesMessage(
					FacesMessage.SEVERITY_ERROR, "Erro grave",
					"Erro no conversor"));

O erro:

java.lang.NumberFormatException: For input string: "Botafogo"
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at converter.BairroConverter.getAsObject(BairroConverter.java:24)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.getConvertedValue(AutoCompleteRenderer.java:533)
	at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1030)
	at javax.faces.component.UIInput.validate(UIInput.java:960)
	at javax.faces.component.UIInput.executeValidate(UIInput.java:1233)
	at javax.faces.component.UIInput.processValidators(UIInput.java:698)
	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
	at org.primefaces.component.fieldset.Fieldset.processValidators(Fieldset.java:197)
	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
	at org.primefaces.component.panel.Panel.processValidators(Panel.java:293)
	at javax.faces.component.UIForm.processValidators(UIForm.java:253)
	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
	at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1172)
	at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

Sabe me dizer oque fiz de errado?

E

Uso assim:

Conversor

public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { try { return jpa.findCidade(Integer.valueOf(arg2).longValue()); } catch (NumberFormatException e) { return new Cidade(); } }

Busca

public Cidade findCidade(Long id) { EntityManager em = getEntityManager(); try { return em.find(Cidade.class, id); } finally { em.close(); }
}

M

edudebom:
Uso assim:

Conversor

public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { try { return jpa.findCidade(Integer.valueOf(arg2).longValue()); } catch (NumberFormatException e) { return new Cidade(); } }

Busca

public Cidade findCidade(Long id) { EntityManager em = getEntityManager(); try { return em.find(Cidade.class, id); } finally { em.close(); }
}


edudebom,

nesse caso só dá pra fazer com JPA?
Não sei utilizar, estou tentando fazer em Hibernate mas não estou conseguindo tambem… Tem um exemplo que possa me passar?

E

Não precisa ser JPA. Você deve ter um BairroDao certo ? Faça uma pesquisa pelo id.

M

edudebom,

fiz um método que pesquise pelo id, o autocomplete até busca os bairros, mas na hora que adiciona acontece a mesma coisa que aconteceu com o GustavoSS ele adiciona o bairro como null ao invés de pegar o id do bairro existente.

Conversor:

@Override
	public Object getAsObject(FacesContext context, UIComponent component,
			String value) {
		BairroDao bairroDao = new BairroDao();
		Bairro bairro = new Bairro();
		try {
			return bairroDao.buscaPorID(Integer.valueOf(value));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return (new Bairro());
	}

Método:

public Bairro buscaPorID(Integer id) {
		Bairro bairro = new Bairro();
		session = HibernateUtil.getSession();
		try {
			bairro = (Bairro) session.createCriteria(Bairro.class)
					.add(Restrictions.idEq(id)).uniqueResult();
		} catch (Exception e) {
			e.printStackTrace();
		}
		session.close();
		return bairro;
	}
}

Muda alguma coisa na hora de adicionar?

E

Veja no seu código fonte gerado do xhtml se os values do select estão chegando preenchidos.

M

Seria isso?

<ul class="ui-autocomplete-items ui-autocomplete-list ui-widget-content ui-widget ui-corner-all ui-helper-reset">
<li class="ui-autocomplete-item ui-autocomplete-list-item ui-corner-all" data-item-value="Bonsucesso" data-item-label="Bonsucesso">
<span class="ui-autocomplete-query">Bo</span>nsucesso</li>
<li class="ui-autocomplete-item ui-autocomplete-list-item ui-corner-all ui-state-highlight" data-item-value="Botafogo" data-item-label="Botafogo"><span class="ui-autocomplete-query">Bo</span>tafogo</li></ul>

ou isso?

<span id="form:bairroComplete" class="ui-autocomplete">
<input id="form:bairroComplete_input" name="form:bairroComplete_input" type="text" class="ui-autocomplete-input ui-inputfield ui-widget ui-state-default ui-corner-all" autocomplete="off" value="" role="textbox" aria-disabled="false" aria-readonly="false" aria-multiline="false">
<input id="form:bairroComplete_hinput" name="form:bairroComplete_hinput" type="hidden" autocomplete="off" value="Bonsucesso"></span>
E

Rode em modo debug e veja se no teu getAsObject está chegando o value e retornando o bairro corretamente.

M

edudebom,

o value esta chegando com a seguinte informação: “Botafogo”

pelo que vi ele não entra no método buscaPorID.
e da o seguinte erro:

java.lang.NumberFormatException: For input string: "Botafogo"
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.valueOf(Unknown Source)
	at converter.BairroConverter.getAsObject(BairroConverter.java:25)

Converter:

public Object getAsObject(FacesContext context, UIComponent component,
			String value) {
		BairroDao bairroDao = new BairroDao();
		Bairro bairro = new Bairro();
		try {
			return bairroDao.buscaPorID(Integer.valueOf(value));
		} catch (Exception e) {
			e.printStackTrace();
			return (new Bairro());
		}
	}

Metodo

public Bairro buscaPorID(Integer id) {
		Bairro bairro = new Bairro();
		session = HibernateUtil.getSession();
		try {
			bairro = (Bairro) session.get(Bairro.class, id);
		} catch (Exception e) {
			e.printStackTrace();
		}
		session.close();
		return bairro;
	}
T

Tive um problema parecido ao tentar usar o autoComplete e acabei desistindo dele. Usei o selectOneMenu e acabei tendo praticamente o mesmo resultado.

O autocomplete até encontrava tudo, eu selecionava e no momento de busca-lo no banco ele passava uma variável nula para o meu ManagedBean e não conseguia localizá-lo no banco.

M

Mas ai eu não vou esbarrar no mesmo problema que é o conversor? Por que o selectOneMenu necessita de um conversor também né?

E

Tente

itemValue="#{bairro.suachaveprimaria}"

Se não funcionar cole aqui seu Bairro.java

M

Apos alterar o que voce me pediu ocorreu um erro na conversão:

java.lang.ClassCastException: java.lang.Integer cannot be cast to modelo.Bairro
	at converter.BairroConverter.getAsString(BairroConverter.java:40)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeSuggestionsAsList(AutoCompleteRenderer.java:434)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeSuggestions(AutoCompleteRenderer.java:366)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeResults(AutoCompleteRenderer.java:116)
	at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeEnd(AutoCompleteRenderer.java:98)Erro na conversão

Com ficou:

itemValue="#{bairro.idBairro}"

Onde deu o erro:
O value chegou com o valor : 15

public String getAsString(FacesContext context, UIComponent component,
			Object value) {
		if (value == null) {
			return "";
		}
		Bairro bairro = new Bairro();
		try {
			bairro = (Bairro) value; //Erro ocorreu aqui.
		} catch (Exception e) {
			FacesUtil.adiconarMensagem(FacesMessage.SEVERITY_FATAL, "Erro.",
					"Erro no conversor.");
			System.out.println("Erro na conversão");
			e.printStackTrace();
		}
		return bairro.getNomeBairro();

Classe Bairro:

package modelo;

//imports

@Entity
@Table
public class Bairro implements Serializable {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "IDBairro")
	private Integer idBairro;
	@Column(name = "Bairro", length = 40)
	private String nomeBairro;
	@OneToMany(mappedBy = "bairro", cascade = CascadeType.ALL)
	private Set<Endereco> enderecos = new HashSet<Endereco>();

	public Bairro(Integer idBairro, String nomeBairro, Set<Endereco> enderecos) {
		super();
		this.idBairro = idBairro;
		this.nomeBairro = nomeBairro;
		this.enderecos = enderecos;
	}

	public Bairro() {
		super();
	}

   //Set e Get

	@Override
	public String toString() {
		return "Bairro [idBairro=" + idBairro + ", nomeBairro=" + nomeBairro
				+ ", enderecos=" + enderecos + "]";
	}

}
M

Já não sei mais o que fazer, se tento buscar pelo id da erro de conversão, se tento buscar pelo nome também da erro de conversão! :cry:

Criado 2 de novembro de 2012
Ultima resposta 11 de nov. de 2012
Respostas 21
Participantes 5