[Resolvido] JSF, HashMap e renderização

5 respostas
D

Olá a todos,

Eu tenho um template de objetos que são renderizados, mas não é feita a avaliação das expressões que recuperam informações (fazem a ligação) do Bean. Assim um grid que está neste template não tem seus dados preenchidos.

Minha suspeita recai em cima do Map, como se a árvore de componentes do JSF não estivesse montada da primeira vez, mas da segunda sim.

no meu Bean tenho:

Map<String, ObjetoComplexo> mapa;
List<Long> lista;

e em minha página tenho:

<a4j:repeat value="#{ucMBean.lista}" var="item">
	<ui:param name="gerenciador" value="#{ucMBean.mapa[item]}" />

<a4j:repeat>

Neste último trecho, ucMBean.mapa[item] retorna uma Lista e são os dados desta lista que só são exibidos em um segundo reRender.

Alguém já passou por situação semelhante e sabe como contornar este problema?

PS: Já tentei fazer uma gambi, para fazer o reRender na mão, mas não deu certo.

Estou utilizando Richfaces 3.3.3.

5 Respostas

R

Mostre o pedaço do fonte que tem o grid completo!

Pois ja passei por isso por não ter o componente renderizado, ae tem que ver como esta seu rendered no grid!

posta ae para eu dar uma olhada.

D

O código do Grid está ao final, mas além das linhas do grid não serem renderizados, todos os componentes de entrada de dados não tem suas “ligações” feitas com os atributos do bean.

O componente de inputText aparece vazio na primeira vez, mas na segunda aparece com o valor definido no bean. Da mesma forma que o grid consegue listar os registros definidos no bean.

Em todos os momentos o breakpoint mostra que o bean já possui os dados no Mapa. É como se o JSF não entendesse como converter o value do Mapa, para o objetoComplexo que tem uma lista dentro e os elementos a serem “ligados” aos inputtext do template.

Pelo que entendi, todos os componentes que não dependem de informação do bean são renderizados. Os que representam algum atributo do bean, que para o grid é uma lista e para o inputText é uma String do objeto complexo não tem seus valores renderizados.

<!-- GRID -->
<div>
	<rich:dataTable value="#{gerenciador.lista}" var="element" rowKeyVar="indice" rows="#{meuBean.qtRegistroPagina}">

		<!-- Botão de Edição -->
		<rich:column>
			<a4j:commandLink action="#{gerenciador.editar}" reRender="cabecalho#{entidade}" oncomplete="ajaxComplete()" ajaxSingle="true">
				<f:setPropertyActionListener target="#{gerenciador.entidadeTemporaria}" value="#{element}" />
			</a4j:commandLink>
		</rich:column>

		<!-- Botão de Exclusão -->
		<rich:column>
			<a4j:commandLink action="#{gerenciador.excluir}" reRender="cabecalho#{entidade}" oncomplete="ajaxComplete()" ajaxSingle="true">
				<f:setPropertyActionListener target="#{gerenciador.entidadeTemporaria}" value="#{element}" />
			</a4j:commandLink>
		</rich:column>

		<rich:column>
			<h:outputText value="#{element.nome}" />
		</rich:column>

	</rich:dataTable>
</div>
R

Eu ja precisei fazer isso uma vez, trabalhar com mapas…, será que você não está de alguma forma passando o parâmetro de forma errada?

Veja eu fiz da forma abaixo:

@Override
	public List<Cliente> listarClientes() {
		Cliente c = new Cliente();
		c.setNome("Chocholina");
		c.setTelefone("33228899");
		
		Cliente c1 = new Cliente();
		c1.setNome("CoisoDoido");
		c1.setTelefone("899900");
		List<Cliente> listaClientes = new ArrayList<Cliente>();
		listaClientes.add(c);
		listaClientes.add(c1);
		
		return  listaClientes;
		//Query queryClientes = entityManager.createQuery("select c from Cliente c");
		//return queryClientes.getResultList();
	}
	@Override
	public Map<String,Cliente> listarClientesDoDia() {
		
		Cliente c = new Cliente();
		c.setNome("João Maurício");
		c.setTelefone("33228899");
		
		Cliente c1 = new Cliente();
		c1.setNome("Mário Roberto");
		c1.setTelefone("899900");
		
		Map<String, Cliente> map = new HashMap<String, Cliente>();
		map.put(c.getTelefone(), c);
		map.put(c1.getTelefone(), c1);
		
		return map;
	}

	
	
	@Override
	public String retornaChave() {
		return "899900";
	}
	@Override
	public int retornaIndice() {
		
		return 0;
	}



<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:s="http://jboss.com/products/seam/taglib"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:a4j="http://richfaces.org/a4j"
    template="/layout/template.xhtml">

    <ui:param name="showGlobalMessages" value="false"/>
    <ui:define name="body">
    <f:view>
    	<h:form>
    	<!-- 
	        Clientes Kim
	        <h:dataTable value="#{clientesHandler.listarClientesDoDia()}" var="varClientes" border="1">
	        <h:column>
	        	<f:facet name="header">
	        		Clientes
	        	</f:facet>
	        	<h:outputText value="#{varClientes.value.nome}" />
	        </h:column>
	        	
	        </h:dataTable>
	      -->  
	     	<!-- retorna uma chave para buscar no mapa-->
	      <ui:param name='chave' value="#{clientesHandler.retornaChave()}" /> 
	      <ui:param name='indice' value="#{clientesHandler.retornaIndice()}" /> 
	     
	      <br />
			viche <br />
	      &lt;!-- Retornando o objeto de um mapa dinamicamente --&gt;
	      &lt;h:outputText value="#{clientesHandler.listarClientesDoDia()[chave].nome}" /&gt;<br />
	      &lt;h:outputText value="#{clientesHandler.listarClientes()[indice].nome}" /&gt;<br />
&lt;!--	  		&lt;a4j:commandButton value="mostrarClientes" action="#{clienteMB.mostrarClientes}"&gt;&lt;/a4j:commandButton&gt;--&gt;
	        &lt;h:messages styleClass="message"/&gt;
        &lt;/h:form&gt;
     &lt;/f:view&gt;  
    &lt;/ui:define&gt;
&lt;/ui:composition&gt;

Pelo menos aqui funcionou normal.

D

Ribclauport, fico muito agradecido pelos esclarecimentos e exemplos que me ajudaram bastante.

Consegui resolver, mas o que entendi era que eu estava errando nos tipos das Listas e Mapas.

Eu tinha uma lista de Long e um Mapa de String. Quando unifiquei tudo para Long, passou a funcionar tudo ok.

Outra coisa que fiz foi mudar de:

&lt;ui:param name="gerenciador" value="#{ucMBean.mapa[item]}" /&gt;

para:

&lt;ui:param name="gerenciador" value="#{ucMBean.mapa[item.id]}" /&gt;

Já que item era o ObjetoComposto e item.id é um Long, como (agora) é a chave do Mapa (não mais String).

PS.: Uma coisa que me chamou atenção nos exemplos que você passou foi a chamada ao método listarClientesDoDia(). Quando fiz isso, o parser reclamou da presença dos parênteses. É isso mesmo, com parêntese e tudo? Estou usando Richfaces 3.3.3 + JSF 1.2. Não sei se isso é possível no JSF 2.

&lt;h:outputText value="#{clientesHandler.listarClientesDoDia()[chave].nome}" /&gt;<br />

Muito obrigado Ribclauport.

R

Bem observado, isso é possível por que estou usando Jboss Seam, reza a lenda que jsf 2.0 foi influenciado pelo mesmo nesta abordagem.

Criado 13 de dezembro de 2012
Ultima resposta 14 de dez. de 2012
Respostas 5
Participantes 2