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