Projetos de estudo para JSF2, Spring e Hibernate

Quem está iniciando a desenvolver aplicações Web em Java, após estudar vários frameworks de forma isolada, acaba tendo algum tipo de dificuldade para integrar 2-4 frameworks a fim de ter uma arquitetura inicial de desenvolvimento.

Existem várias discussões sobre qual modelo seguir, JavaEE (CDI, EJB etc) com um servidor de aplicação robusto ou Spring com o bom e velho Tomcat. Decidir qual o melhor modelo envolve inúmeras variáveis que dependem do projeto e da equipe.

Deixando um pouco de lado essa discussão, eu pretendo enumerar alguns projetos que nós da TriadWorks utilizamos em nossos cursos e treinamentos. Os projetos são construídos durante os cursos de JSF (1.2 e 2.0), Spring e Hibernate pelos próprios alunos seguindo o método de ensino bottom-up.

Todos os projetos estão disponibilizados no GitHub a fim de facilitar o estudo, visualização do código e a atualização periódica. Segue abaixo os projetos:

  1. jsf-issuetracker – Projeto de uma aplicação de Issue Tracker com JSF 2.x, Spring 3.x e Hibernate 3.6.x (JPA2).
  2. jpa-issuetracker – Projeto de uma aplicação de Issue Tracker modelada com Hibernate 3.6.x (JPA2) e Spring 3.x.
  3. jsf-loja – Projeto de uma aplicação de Loja Virtual com JSF 1.2, Spring 3.x e Hibernate 3.5.x, além do uso de teste de unidade e integração.

Com a facilidade de compartilhar e colaborar código provinda do GitHub o projeto original jsf-issuetracker possui algumas versões (forks) bem interessantes feitas pelo Rafael Pestano, criador do Conventions Framework. O Rafael migrou o projeto original para tecnologias como CDI, EJB 3.1, CODI, Primefaces-Extensions e o próprio Conventions.

  1. jsf-issuetracker-cdi (OpenWebBeans) – idêntico ao projeto original, porém utilizando CDI com OpenWebBeans.
  2. jsf-issuetracker-cdi (Weld) – idêntico ao anterior, porém utilizando CDI com Weld.
  3. jsf-issuetracker-cdi-conventions (OpenWebBeans) – versão utilizando CDI com OpenWebBeans e Conventions Framework.
  4. jsf-issuetracker-cdi-conventions (Weld) – versão utilizando CDI com Weld e Conventions Framework.
  5. jsf-issuetracker-cdi-jboss (Weld) – versão utilizando CDI com Weld, EJB 3.1 e Conventions Framework na qual roda num JBoss AS 7. Esta versão possui uma aplicação demo hospedada no OpenShift.

São 6 (seis) versões do mesmo projeto com tecnologias diferentes que rodam em Tomcat e JBoss AS 7, ou seja, não há desculpas para não estudar e avaliar qual delas se encaixa melhor no seu projeto ou equipe.

O repositório de cada projeto possui um README que ajudará a configurar e fazer o deploy da aplicação. Se o README não estiver claro o suficiente ou mesmo incorreto, por favor, deixe-me saber que tentarei melhora-lo com a sua ajuda.

Caso tenha interesse ou alguma dúvida nos cursos e treinamentos da TriadWorks, por favor, deixe-nos saber.

10 razões para migrar sua aplicação para JSF2

Hoje foi publicado no blog da Caelum um post sobre as 10 razões para migrar sua aplicação para JSF2, e eu tive o prazer e a honra de colaborar com o post a convite de um grande amigo, o Raphael Lacerda.

O post enumera 10 razões que vão desde aspectos técnicos até comerciais, entre eles podemos citar  alguns como melhoria de performance, melhorias na especificação e fim do suporte à versão antiga da especificação e componentes.

Vale a pena conferir.

Problema do rendered dinâmico com JSF

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? :-)