Facelets: desligue o cache de páginas em desenvolvimento
Entenda como o Facelets processa suas páginas XHTML e como isso pode impactar na sua produtividade
Quando desenvolvemos para Web é muito comum tirarmos proveito do hot deploy da IDE ao criar ou editar páginas JSP. Ao editar uma página JSP não precisamos reiniciar o servidor, pois nossa modificação é enxergada pela aplicação logo após salvarmos o arquivo. Agora, basta dar um refresh no navegador para ver a alteração!
O que a IDE faz é deployar o JSP modificado no servidor, em seguida o servidor se encarrega de verificar se houve mudanças no arquivo para então recompilá-lo. Isso acontece de forma transparente para o desenvolvedor. No fim, nossa rotina é algo como:
- altera JSP;
- salva alteração na IDE e;
- tecla F5 no browser.
Esse mesmo processo acontece quando trabalhamos com JSF 2 e sua engine de páginas, o Facelets. O desenvolvedor altera o XHTML, salva a modificação e atualiza a página no navegador.
Embora a IDE atualize o servidor com a nova modificação da página o JSF ignora essa modificação por um intervalo curto de tempo. Isso faz com que a mudança possa não ser vista de imediato pelo desenvolvedor. No fim das contas, talvez ele precise teclar 2 ou 3 vezes o F5 para ver a alteração no browser!
Mas por que o JSF ignoraria minha modificação?
Como o Facelets processa uma página
Para entendermos esse delay na atualização das páginas, precisamos primeiramente entender como o Facelets processa uma página...
Quando uma requisição Web chega na aplicação, o JSF precisa processar a página e seus componentes. É aí que o Facelets entra em ação: ele carrega o XHTML do disco, faz o parsing e validação das tags do arquivo, compila cada tag para uma estrutura em memória e, por fim, faz o cache dessa estrutura para que nas próximas requisições à mesma página ele não tenha que fazer tudo novamente.
Isto traz um ganho considerável de performance, pois como tudo está cacheado em memória as requisições seguintes ficam muito mais rápidas. Se o Facelets tem o cache da página ele não tocará no disco.
Mas há um porém...
Esse cache, por padrão, é mantido em memória por 2 segundos, o que significa que o Facelets usará o cache em vez da página do disco somente durante esse intervalo. Após esse período o cache é invalidado e tudo recomeça.
Ah! É importante entender que esse processamento e cache não tem nada a ver com a famosa árvore de componentes do JSF.
A idéia é até interessante para o ambiente de produção, onde não editamos as páginas e precisamos o máximo de desempenho, mas não para o ambiente de desenvolvimento, onde 2 segundos parece uma eternidade para um desenvolvedor numa máquina razoável. É quase uma questão de ALT+TAB...
Desligue o cache em desenvolvimento
Apesar da boa intenção do JSF, esse cache compromete a produtividade do desenvolvedor durante o desenvolvimento. Para falar a verdade, chega a ser irritante ter que esperar 2 segundos para só então dar aquele F5 no browser.
Mas podemos melhorar o tempo de resposta ao editar uma página...
Basta desligarmos o cache de páginas. Pra isso, dentro do web.xml
, configure o parâmetro de contexto javax.faces.FACELETS_REFRESH_PERIOD
com o intervalo de tempo em segundos, como a seguir:
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>0</param-value> <!-- cache desligado -->
</context-param>
Utilizamos o valor 0 (zero) acima para desligar o cache por completo. Dessa forma, assim que salvarmos a página na IDE a modificação será enxergada imediatamente no navegador após um F5.
Caso o valor seja maior que 0 (zero), o cache será invalidado após este intervalo. O que, sinceramente, não faz o menor sentido durante o desenvolvimento. Nem mesmo o valor padrão de 2 segundos eu recomendaria.
Habilite o cache em produção
Em produção precisamos do comportamento oposto. O cache deve ser ligado por um tempo indeterminado. Logo, em produção o valor ideal é -1, na qual significa que o cache nunca será invalidado.
Dessa forma, antes de fazer o deploy da aplicação no servidor de produção, não esqueça de habilitar o cache indefinidamente:
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>-1</param-value> <!-- habilita o cache indefinidamente -->
</context-param>
Por não fazer sentido ter um valor diferente de -1 em produção, a especificação do JSF 2.3 adotou ele como padrão. Mas não desanime, a partir da versão 2.2.11 do JSF já temos o mesmo comportamento!
Com esta melhoria na especificação, temos outra alternativa para habilitar o cache indefinidamente...
Podemos usar o conceito de Project Stage do JSF 2 para determinar em qual ambiente a aplicação se encontra. Como o intuito é ligar o cache de páginas em produção, basta definirmos o parâmetro de contexto javax.faces.PROJECT_STAGE
como "Production" no arquivo web.xml
:
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
Caso você não defina o ambiente, o JSF usará "Production" por padrão.
Tire o melhor da ferramenta
Quanto menos tempo o desenvolvedor fica ocioso esperando a ferramenta trabalhar melhor para ele. Não podemos nos dar o luxo de ficar esperando uma página ser atualizada pela IDE ou mesmo reiniciar o servidor a cada alteração de arquivo.
Saber configurar e tunar as ferramentas que você trabalha no dia a dia é importante e com certeza impacta no desenvolvimento.
O cache de páginas do Facelets traz tanto melhorias para o ambiente de desenvolvimento quanto de produção. Some ele ao hot deploy no Eclipse para obter um ganho significativo de produtividade e economize até 5h por semana.
Para ficar por dentro de outras dicas e boas práticas para desenvolvimento Web, conheça nossos cursos de Java para Web e JSF 2 com Spring.
E você, já havia percebido esse delay na atualização de suas páginas? Conhecia esta configuração do JSF 2?
Desenvolvedor e instrutor na TriadWorks