JSF - h:selectOneMenu está executando método duas vezes

4 respostas
alexmoraes

Boa Tarde!

Estou com um problema em uma página JSF.
Tenho duas h:selectOneMenu que, pela seleção do usuário, os grupos devem ser atualizados.

<h:selectOneMenu binding="#{userHandler.selectedUser}">
            <a4j:support event="onchange" reRender="selGroup"/>
            <f:selectItem itemValue="-1" itemLabel="Please select"/>
            <f:selectItems value="#{userHandler.usersToComboBox}"/>
          </h:selectOneMenu>

          <h:selectOneMenu binding="#{userHandler.selectedGroup}" id="selGroup">
            <f:selectItem itemValue="-1" itemLabel="Please select"/>
            <f:selectItems value="#{userHandler.groupToComboBox}"/>
          </h:selectOneMenu>

Por conta do ciclo de vida do JSF, ele está executando os métodos usersToComboBox e groupToComboBox duas vezes. O método usersToComboBox executa uma consulta no bd trazendo os usuários. O groupToComboBox traz os grupos que aquele usuário pertence.

Como faço para que ele não execute esses método duas vezes em um único request?

Obrigado!

Alexandre

4 Respostas

J

Primeiro, entenda o ciclo do JSF para saber como, quando e pq são chamados os métodos.
E para tratar isso, tu pode armazenar os dados no momento da primeira chamada, dai quando chamar o método get pela segunda fez, tu ja tem esses dados, sem precisar descer no banco( esse é um dos maiores gargalos de aplicações que usam JSF sem se compreender o funcionamento do ciclo).

alexmoraes

Como que eu sei que ele está chamando pela segunda vez dentro do ciclo? Eu tenho essa informação em algum lugar?

alexmoraes

Bom dia!
Não sei se é a melhor solução mas, para corrigir esse problema fiz o seguinte.

<h:selectOneMenu binding="#{userHandler.selectedUser}" valueChangeListener="#{userHandler.groupChangeListener}>  
  <a4j:support event="onchange" reRender="selGroup"/>  
  <f:selectItem itemValue="-1" itemLabel="Please select"/>  
  <f:selectItems value="#{userHandler.usersToComboBox}"/>  
</h:selectOneMenu>  
  
<h:selectOneMenu binding="#{userHandler.selectedGroup}" id="selGroup">  
  <f:selectItem itemValue="-1" itemLabel="Please select"/>  
  <f:selectItems value="#{userHandler.groupToComboBox}"/>  
</h:selectOneMenu>

Adicionei o valueChangerListener no primeiro selectOneMenu. Nesse método eu limpo a lista que irá povoar o segundo selectOneMenu.
Assim quando ele for preencher o segundo, ele testa se existe conteúdo ou não. Não havendo roda a consulta.
Quando eu mudar o conteúdo do primeiro selectOneMenu ele executa a consulta novamente pois a lista será limpa.

segue o código dos métodos no bean.

private List<SelectItem> group = new ArrayList<SelectItem>();

	public void groupChangeListener(){
		group.clear();
	}
	
	public List<SelectItem> groupToComboBox(){
		if(group.isEmpty()){
				//executa consulta
		}
		return group;
	}
alexmoraes

uma outra solução, creio que mais decente.

No changelistener executar a consulta para carregar o propriedade do bean que irá preencher o segundo selectOne.
E no get da segunda selectOne somente retornar o objeto.

Acho q fica melhor q ficar zerando a lista…

Criado 27 de abril de 2011
Ultima resposta 29 de abr. de 2011
Respostas 4
Participantes 2