Posts Tagged ‘Java’

Problema do rendered dinâmico com JSF

Wednesday, December 1st, 2010

Desde o surgimento dos conjuntos de componentes Ajax passou-se a aproveitar melhor as features do JSF e destes componentes para trazer ao usuário uma UI mais rica e na medida do possível mais leve. Graças a estes componentes ficou mais fácil desenvolver estes tipos de UI quase que transparentemente da mesma forma convencional (sem Ajax) que estávamos acostumados a escrever nossas páginas.

Entre tantos benefícios dessa abordagem apareceram alguns problemas que também não estávamos acostumados a lidar, como saber o que enviar e repintar antes de uma requisição Ajax, ou saber limpar um formulário adequadamente quando necessário ou mesmo repintar determinados componentes de exibição dinâmica.

Pegando este último problema como tema deste post, o que eu tenho notado é que ainda hoje em dia ele é um dos problemas mais comuns de acontecer e ao mesmo tempo um dos mais discutidos em fóruns e listas de discussão. Sendo, nada mais justo do que explana-lo aqui no blog e facilitar a vida de muitos, assim como a minha.

Problema

Este problema, que muitos ainda desconhecem, é comumente conhecido como “problema do rendered dinâmico” (bem, ao menos é como eu o chamo!) e só acontece quando trabalhamos com JSF e Ajax - independente do conjunto de componentes - mais especificamente após tentarmos repintar (ou rerenderizar, como você queira chamar) um componente com o atributo rendered dinâmico, como este:


    

Este componente poderia ser repintado após algum evento Ajax disparado pelo usuário na tela, como por exemplo ao selecionar o tipo de cadastro entre pessoa física ou jurídica, algo similar a isto:


    
    
    

Aparentemente não há qualquer problema com os trechos de código acima, principalmente se o componente iniciar visível para o usuário (ou seja, a EL ${myBean.pessoaFisica} do rendered estiver sendo avaliada para true).

Após mudar para o tipo pessoa jurídica é disparado um evento Ajax, o componente é repintado e desaparece da tela, como era de se esperar, claro. Contudo se você alterar a opção para o tipo pessoa física o componente não reaparecerá para o usuário. E é aí onde está o problema!

Se você for esperto, após alguns minutos analisando o problema, notará que a requisição Ajax foi disparada pelo componente tipoDePessoa (Firebug, plugin para Firefox, pode te ajudar aqui), o estado do managed bean foi alterado e o ciclo de vida do Faces foi processado sem qualquer erro.

E a partir daí, depois de refazer e analisar todos os passos básicos e sensatos, perde-se inúmeras horas tentando descobrir onde está de fato o problema neste simples cenário. A primeira vista parece ser um bug do JSF ou do conjunto de componentes, mas na verdade não é.

Solução

Sendo direto e sem rodeios: você não pode rerenderizar um componente na qual possua o atributo rendered dinâmico, ou seja, o componente não pode possuir EL para definir seu estado de visibilidade para o usuário.

Para resolver isso, repinte o componente parent do componente que possui o rendered dinâmico. Lembrando que este componente parent não pode ter o atributo rendered dinâmico, ou seja, ele sempre precisa ser renderizado.

Componentes como a4j:outputPanel ou mesmo h:panelGroup são excelentes componentes para servirem como componente parent. Sabendo disto, o código apropriado seria algo como:


    
        
    

E o componente responsável pelo evento Ajax deve repintar, no caso acima, o a4j:outputPanel (componente parent sem rendered dinâmico) e não mais o h:panelGroup.

Entendendo o problema

Para quem ainda não sabe, o atributo rendered (que por padrão é true) dos componentes é responsável por tornar o componente visível ou não para o usuário, ou seja, sempre que este atributo for true o componente poderá gerar código XHTML para ser exibido na página. Caso ele seja false, normalmente, nenhum código XHTML é gerado. Vale lembrar que mesmo o rendered sendo false o componente ainda existe na árvore de componentes no lado servidor.

Não é interessante tentar rerenderizar um componente com rendered dinâmico pois quando o atributo rendered é avaliado para false o componente (código XHTML na verdade) não aparece na árvore DOM da página. Sendo, após repintar este mesmo componente (agora com rendered avaliado para true) o código JavaScript do Richfaces responsável por atualizar o bloco de código onde se encontraria o componente na árvore DOM não consegue achar a posição exata para repintar na página (para injetar o novo código XHTML), já que o código XHTML do componente não existe mais. Então, no final, o Javascript do Richfaces acaba simplesmente não fazendo nada.

Por isso, quando você repinta um componente parent qualquer (que sempre tem o atributo rendered avaliado para true) o Richfaces consegue encontrar a posição exata deste componente na página e injetar o novo código XHTML, e como o componente com rendered dinâmico é um nó (filho) do componente parent ele também é repintado.

Concluindo

O problema é simples e a solução mais simples ainda! Nada como ler a documentação do seu conjunto de componentes favorito para entender e evitar este problema. Vale salientar que este problema ocorre com praticamente todos os conjuntos de componentes Ajax.

Acho que para um assunto simples como este eu falei mais do que devia. Espero que tenha ficado claro ou ao menos tenha dado uma luz para quem está enfrentando essa dor de cabeça. Caso queria saber mais sobre o assunto você poderá consultar a documentação do Richfaces, mais especificamente os tópicos 5.5 e 5.6.1.

Enfim, estou feliz por ter tirado mais um post antigo da minha lista de drafts! Atualmente minha rotina diária não tem me permitido investir o tempo que eu gostaria para blogar, mas cá estamos nós novamente, certo? :-)

Just Java 2009 - Eu vou.

Thursday, September 10th, 2009

O maior evento da comunidade Java brasileira, Just Java, na sua 8ª edição, irá ocorrer na próxima semana, dia 15 a 17 de Setembro, em São Paulo.

Assim como no ano passado, eu irei participar do evento. No entanto, este ano eu, juntamente com um amigo, submetemos um trabalho, que por sua vez foi aprovado. Então nós dois estaremos ministrando uma palestra nesta edição do evento.

A palestra será “Os 10 maus hábitos dos desenvolvedores JSF“, e será apresentada por mim e pelo Tarso Bessa no último dia do evento, quinta-feira, dia 17, às 13:00h.

Um resumo da palestra pode ser visto logo abaixo:

Serão apresentadas 10 discussões sobre os maus hábitos mais comuns entre os desenvolvedores JSF, hábitos encontrados não somente entre iniciantes, mas também entre alguns desenvolvedores mais experientes, e por sua vez serão apresentadas soluções para cada um deles.

O conteúdo da apresentação será bem objetiva e simples. Muitos dos maus hábitos apresentados serão reconhecidos por alguns profissionais, e provavelmente as soluções propostas por nós para cada um deles. O mais interessante mesmo são as discussões e questionamentos durante a palestra sobre cada mau hábito, discussões estas que agregam grande valor a apresentação.

Enfim, eventos como o Just Java são muito bons pela excelente grade de palestras técnicas e principalmente pelo networking que acabamos fazendo durante o evento. Tenho certeza que este evento irá superar os anteriores em vários aspectos.

Espero ver muitos amigos e profissionais que conheço apenas de listas e fóruns de discussão, e se possível trocar algumas idéias com cada um deles.

Para ver a grade do evento:
http://grade.justjava.com.br/

Para maiores informações sobre o evento:
http://www.sucesusp.org.br/eventos2009/justjava/