Entenda o atributo immediate no JSF

Neste artigo vou tentar explicar para que serve o atributo immediate do JSF e exemplos de situações onde você iria gostar de usá-lo, estou considerando que você seja um iniciante em JSF, mas que ao menos saiba a estrutura de um projeto WEB.

Bem vamos lá…

Segue a explicação do atributo immediate segundo o JEE Tutorial:

UIInput components and command components (those that implement ActionSource, such as buttons and hyperlinks) can set the immediate attribute to true to force events, validations, and conversions to be processed during the apply request values phase of the life cycle.

O parágrafo diz que os componentes de entrada  e componentes de comandos (botões e hiperlinks), podem setar o atributo immediate para true, para fazer com que os eventos, validações e conversões sejam processadas durante a fase de aplicar valores de requisição(Apply Request Values)

Concluímos que não pulamos a validação, se você pensar no immediate como “uma forma de pular a validação”, vai ficar complicado usar o JSF.

Olhe o diagrama do ciclo de vida do JSF:

Não vou me estender quanto ao Ciclo de Vida, mas darei uma breve explicação sobre como interpretar o diagrama acima.

Os quadrados em verde são as fases, os quadrados em azul são os eventos que ocorrem em cada fase, muita gente confunde, e acha que os quadrados em azul também são  fases, se  temos 6 quadrados verdes, então o JSF tem 6 fases.

Por exemplo, um método actionListener de um botão será executado em Process Events da fase  Invoke Application, antes de Render Response.

Se este mesmo botão estiver com o Immediate setado para true, o actionListener será executado em Process Events de Apply Request Values.

Obs.:  Response Complete significa que a aplicação deve ser redirecionada para qualquer coisa que não seja um componente JSF,  um uso comum desta declaração, é quando você deseja que um actionListener devolva um um arquivo para download. Da uma ligada no post do cara chamado Urubatan no link abaixo.

http://www.guj.com.br/posts/list/54239.java

Acho que já esclarecemos um pouco as coisas, certo? Então vamos a um exemplo prático:

Para garantir que estaremos falando a mesma língua, baixe o projeto básico de exemplo, você deve importá-lo para o Eclipse JEE, talvez você tenha que corrigir as bibliotecas do seu classplath.

Se você  executou o projeto, deve ter visto JOptionPane, exibindo o que você inseriu no campo, e também em que fase do ciclo de vida aquele evento foi executado,  caso você não insira nada no campo de entrada, é impresso “campo obrigatório”, e o actionListener não é executado.

Deixe aberto em sua IDE as classes Pessoa, ManagedBeanPessoa e o arquivo jsp pessoaView.jsp

Abaixo temos alguns casos de usos

Caso 1

Eu quero que o metodo imprimeNome seja executado mesmo que eu não digite nada no campo.

Simples! Altere o botão imprimeNome, adicione o immediate=”true” ao botão.

<h:commandButton id="commandoButtonImprimeNome" immediate="true" value="Imprime Nome" actionListener="#{managedBeanPessoa.addImprimeNome}" />

Executou perfeitamente, mas note que a fase mudou, agora exibiu APPLY_REQUEST_VALUES, e o nome da pessoa esta nulo.

O nome da pessoa esta nulo, pois o modelo não foi atualizado (olhe o diagrama do ciclo de vida.). Depois que o actionListener foi executado, o ciclo seguiu para RENDER_RESPONSE e nunca chegou em UPDATE_MODEL_VALUES.

Caso 2

Eu quero que o método imprimeNome seja executado, mesmo que eu não digite nada no campo, mas caso eu tenha digitado alguma coisa, eu quero obter esses valores.

Moleza!, pois o modelo não é atualizado, então precisamos obter o valor através de um binding, altere o arquivo br.com.moacirrf.controlador.ManagedBeanPessoa.

Adicione este atributo

private HtmlInputText inputTextNome = new HtmlInputText();

importe do pacote javax.faces.component.html.HtmlInputText, e crie o método set e get para este atributo.

Altere do actionListener desta forma

public void addImprimeNome(ActionEvent event){
JOptionPane.showMessageDialog(null,"Fase JSF: "+event.getPhaseId()+ "\n Nome da pessoa: " +inputTextNome.getSubmittedValue());

}

Por ultimo, altere o arquivo pessoaView.jsp

<h:inputText id="pessoaNome"  binding="#{managedBeanPessoa.inputTextNome}" required="true" value="#{managedBeanPessoa.pessoa.nome}" requiredMessage="Campo Obrigatorio!">

</h:inputText>

Reinicie o servidor, e o valor que você digitou será exibido.

Caso 3

Eu quero que o método imprimeNome seja executado, mesmo que eu não digite nada no campo, mas caso eu tenha digitado alguma coisa, eu quero obter esses valores  e eu quero que o campo nome seja validado.

Barbada!,  adicione o immediate=”true” no campo nome.

<h:inputText  id="pessoaNome" immediate="true" binding="#{managedBeanPessoa.inputTextNome}" required="true" value="#{managedBeanPessoa.pessoa.nome}" requiredMessage="Campo Obrigatorio!">

</h:inputText>

Altere o ManagedBeanPessoaNome

public void addImprimeNome(ActionEvent event){
JOptionPane.showMessageDialog(null,"Fase JSF: "+event.getPhaseId()+ "\n Nome da pessoa: " +inputTextNome.getValue());
inputTextNome.setValue(null);

}

Teste e veja só que beleza.

Note a linha inputTextNome.setValue(null) experimente comentá-la, se você ficou com duvidas sobre qual a diferença entre getValue() e getSubmitedValue() leia este artigo do criador do PrimeFaces http://cagataycivici.wordpress.com/2005/12/28/jsf_component_s_value_local/

Concluímos aqui este artigo, se você testou todos os exemplos, aprendeu a usar o Immediate, isso evitará muitas gambiarras nos seu futuros projetos com JSF, de quebra você aprendeu um pouco sobre o ciclo de vida deste  framework, que não é tão dificil de entender como dizem por aí.

Espero que este artigo tenha sido útil.

Qualquer xingamento sugestão pode deixar um comentário.

Abrass

No votes yet.
Please wait...

14 thoughts on “Entenda o atributo immediate no JSF

  1. Teria como o metodo imprimeNome seja executado mesmo que eu não digite nada no campo, sem usar o atributo immediate=”true”?

    Deus te abençoe

    No votes yet.
    Please wait...
    • Sim.
      Mas você terá que usar alguma biblioteca de componentes Ajax, como Richfaces.

      Ou
      Definir de forma dinamica se o campo deve ser required.

      Imagina um cenario onde eu tenhos dois botões e um deles eu preciso validar o campo, mas quando o outro for precionado eu não quero que a validação seja executada, os dois botões estão com immediate=’false’.

      Você pode usar parâmetros para fazer com que o required da tag seja trocado de forma dinâmica.

      Veja :

      <h:form id="form">
         					<h:panelGrid columns="2">
         			 			<h:inputText id="pessoaNome" required="#{param['form:commandoButtonImprimeNome2'] != null }"  value="#{managedBeanPessoa.pessoa.nome}" requiredMessage="Campo Obrigatorio!">
         			 			</h:inputText>
         			 			<h:message for="pessoaNome" />
         			 		</h:panelGrid>
         			 		
      				<h:commandButton id="commandoButtonImprimeNome"  value="Imprime Nome  ignora validação" actionListener="#{managedBeanPessoa.addImprimeNome}" />   			
      				<h:commandButton id="commandoButtonImprimeNome2"  value="Imprime Nome" actionListener="#{managedBeanPessoa.addImprimeNome}" />   			
      			
      			
      				</h:form>
         	
      

      Tente entender o que acontece nesta linha
      required=”#{param[‘form:commandoButtonImprimeNome2’] != null }”

      Note a necessidade de adicionar um ID para o form

      Abrass
      E Obrigado pelo comentário

      No votes yet.
      Please wait...
  2. Moacir,

    Excelente post, ta adicionado em favoritos…

    Obrigado

    No votes yet.
    Please wait...
  3. Moacir,

    ótimo post, parabéns.
    Já tinha conhecimento sobre o atributo immediate e de sua utilização, só que ainda não tenho conhecimento 100% do ciclo de vida do JSF. Com o post consegui adquirir mais conhecimento sobre o ciclo de vida.

    Abraços.

    No votes yet.
    Please wait...
  4. Primeiro gostaria de dar os parabéns pelo post, excelente, muito bom, referência mesmo.

    Mas tenho uma dúvida, qual cenário devemos colocar immediate somente nos inputs?
    Li esse artigo aqui também e ele explica dos 3 cenários possíveis, só que não conseguir entender esse de immediate somente nos inputs:

    http://www.slideshare.net/rponte/boas-prticas-com-javaserver-faces-jsf-presentation

    No votes yet.
    Please wait...
    • Ola.
      Obrigado pelo comentário, que bom que foi útil.

      Bem vamos a tua resposta:

      Os campos de input também geram eventos,da mesma forma que os commands, então é possivel ter algo assim:

      
      <h:inputText id="pessoaNome"  immediate="true"  required="true" value="#{managedBeanPessoa.pessoa.nome}" binding="#{managedBeanPessoa.bindNome}" 
         	valueChangeListener="#{managedBeanPessoa.addBuscarIdadePessoa}" onblur="submit()" requiredMessage="Campo Obrigatorio!">
      </h:inputText>
      
      <h:inputText id="pessoaIdade" binding="#{managedBeanPessoa.bindIdade}" immediate="false" required="true"  value="#{managedBeanPessoa.pessoa.idade}" requiredMessage="Campo Obrigatorio!">
      </h:inputText>   			 			</h:inputText>
      
      

      No managedBean o listener, poderia ficar assim:

      
      public void addBuscarIdadePessoa(ValueChangeEvent event){
      		Map<String,Integer> idades = new HashMap<String, Integer>();
      		idades.put("moacir", 25);
      		idades.put("tatiane", 20);
      		idades.put("maria", 19);
      		idades.put("juju", 30);
      		if(idades.containsKey(this.bindNome.getValue())){
      			this.bindIdade.setSubmittedValue(""+idades.get(this.bindNome.getValue()));
      		}else{
      			this.bindIdade.setSubmittedValue("");
      		}
      		
      	}
      

      Raramente precisei utilizar isto no JSF, mas a opção de utilizar esta aí, você deve testar todas as combinações possíveis e ver a que for mais útil.

      Tente montar este cenário, na aplicação de exemplo contida no artigo, e veja como o JSF se comporta.

      Se não ficou claro, pode postar a dúvida.
      Abraço

      No votes yet.
      Please wait...
  5. Pingback: Ken

  6. Pingback: nfl jerseys wholesale

  7. Olá! Muito bom sua postagem, e um belo blog! Adorei!
    Bom, o exemplo é feito com actionListener, gostaria de saber se consigo fazer um retorno do bean, para meu formulário. Como é o caso do action. No caso estou tentando retornar o “form” mas ele não o atualiza. Pode me ajudar?

    No votes yet.
    Please wait...
    • Então, consegui resolver o “problema”, eu apenas coloquei o parâmetro resetValues=”true” dentro do meu commandbutton do primeface. Só não consegui entender uma coisa. Neste mesmo commandbutton, eu tenho o parâmetro update=”@form” onde ele informa o componente do meu formulário que eu quero que seja atualizado. O resetValue, ele se ativo, reajusta os valores que eu desejo, do meu componente de entrada.
      A minha dúvida é: Se eu estou reajustando, o formulário não deveria era ser limpo, já que eu já o atualizei?

      No votes yet.
      Please wait...
  8. Gostaria de saber porque meu comentário foi apagado.Cometi algum erro?

    No votes yet.
    Please wait...
    • Me desculpe Palloma,
      Não havia recebido nenhum dos comentários, por problemas de corrupção no mysql, agora mudei para um cloud linux onde eu consegui recuperar os cometários novos.

      No votes yet.
      Please wait...
  9. moacir! tenho um problema com immediate quando uso ajax , mesmo inserindo texto no inputtext q ta required=true ele envia null para o bean, ja viu isso?
    escopo do bean eh @view

    No votes yet.
    Please wait...
  10. Boa noite, tenho uma duvida tenho um form, que tem um p:dataTable e p:contextMenu e também alguns p:inputText, esse p:inputText sao preenchidos, e tem um botão que adiciona essas informação na tabela, ate ai 100%, o problema que alguns desse p:inputText são obrigatorio, e quando uso o contextMenu para alterar ele, não consigo pois ele aue validar antes de preenche o objeto.
    tem alguma coisa que possa fazer ?

    No votes yet.
    Please wait...

Leave a Reply

Your email address will not be published. Required fields are marked *