terça-feira, 9 de novembro de 2010

[Java] Criando templates com Facelets

Obs: As referências a bibliotecas de tags, xml, imports e configurações serão omitidas. O objetivo é apenas compreender a composição de um template.

Sabemos que é possível compor uma página JSP utilizando includes para melhor reaproveitar trechos de páginas que serão comuns em todo o site ou aplicação.

Com JSP é possível fazer isso pela tag <%@include%> ou ainda, utilizando-se dos recursos JSTL, por meio da construção c:import.

Interessante! Entretanto, estas abordagens podem nos trazer alguns problemas. Por exemplo, é impossível passar parâmetros, dinamicamente, da página que declara os includes para os arquivos incluídos. O recurso <jsp:param> não funcionará nem para o JSF, porque este recurso guarda conteúdo em escopo de página, o que não é suportado pelo JSF. Além disso, alguns containers poderão causar replicações inesperadas de conteúdo, executando uma instrução include mais de uma vez (ver ciclo de vida jsf). Estes problemas vão além de meros bugs da implementação de alguns containers.

O Facelets resolve estes problemas com mecanismo de template baseado em uma abordagem de passagem de parâmetros por EL e suporte completo ao modelo de componentes do JSF.

Veremos por meio de exemplos a composição de um template comum a uma aplicação hipotética, utilizando os recursos do Facelets.

Para um template, basta criar um arquivo xhtml e definir as áreas que serão substituídas quando o template for aplicado. Vamos exemplificar isto construindo um xhtml (vou chamar de meuTemplate.xhtml), informando ao template que o título, o cabeçalho e o conteúdo, serão voláteis, ou seja, irão mudar a cada página:

<head>
    <title>
        <ui:insert name=”titulo”>
          Aqui vai o titulo
        </ui:insert>
    </title>
</head>

<body>
    <ui:insert name=”cabecalho”>
      Aqui vai o cabeçalho
    </ui:insert>
    <ui:insert name=”conteudo”>
      Aqui vai o conteúdo
    </ui:insert>
</body>

Na página em que vamos usar o template, referenciamo-lo da seguinte forma:

<ui:composition template=”meuTemplate.xhtml”></ui:composition>

Redefinindo o valor das áreas voláteis da seguinte forma:

<ui:define name=”titulo”>
  Novo valor do título
</ui:insert>
<ui:define name=”cabecalho”>
  Novo valor do cabeçalho
</ui:insert>
<ui:define name=”conteudo”>
  Novo valor do conteúdo
</ui:insert>

Este é um exemplo muito simples do Facelets para a definição de templates, muita coisa mais sofisticada podemos fazer com estas tags. Saiba que existem outras e espero explorá-las aqui no blog em breve.

Referências:


Grande abraço.

domingo, 31 de outubro de 2010

[Java] Hibernate e o pool de conexões

"Em ambiente de desenvolvimento minha aplicação funciona que é uma beleza, mas quando em produção, experimento alguns problemas relacionados a utilização do banco de dados. Algumas transações não fecham corretamente, retornando-me exceções de timeout e coisas do tipo."

Se você utiliza Hibernate e já passou por algo semelhante, pode ter sido vítima do seu gerenciador de pool de conexões.

O Hibernate é, de longe, o framework MOR (Mapeamento Objeto Relacional) mais utilizado no mercado, pois implementa as especificações JPA e mais alguma coisa. Parece-me até que o JPA é feito baseado no Hibernate e não o contrário. Também pudera, seu idealizador Gavin King, é dos maiores colaboradores das JSRs que consolidam detalhes das especificações EJB 3.0, JPA e JDO. E muitos irão concordar comigo, trata-se de umas das melhores ferramentas a disposição dos javeiros de plantão, fala sério.

Ocorre é que com tantos recursos a disposição, realizar o fine tunning do Hibernate não é um trabalho tão trivial.

Dentre todas as opções configuráveis para melhoria de performance, segurança e escalonamento, tais como cache de segundo nível, configurações de mapeamentos e locks, destaco neste post o pool de conexões.

Sabemos que há muito, os bancos de dados relacionais utilizam-se de tal recurso para acelerar o atendimento a requisições de conexões em ambientes de concorrência. Trata-se de iniciar o serviço com algumas conexões já criadas, e em ir atendendo as requisições com estas conexões, variando entre limites mínimos e máximos em relação a quantidade de conexões criadas. A este conjunto de conexões automaticamente criadas pelo serviço de banco de dados, chamamos pool de conexões.

O Hibernate também trabalha assim. Em linhas gerais, ao ser inicializado, ele pega um número de conexões com o banco de dados e utiliza estas conexões para atender as requisições de suas sessões. O problema é que o gerenciador de pool de conexões do Hibernate não é otimizado o suficiente para uso em produção, apresentando uma série de problemas como referências a conexões encerradas e performance. Isto é dito na própria documentação do Hibernate, que pode ser verificado na página 8 da referência da versão 3.5.6 final, a que utilizei para estudar a questão.

Se você não implementar um dos gerenciadores de pool de conexão de terceiros, suportados pelo Hibernate, nas saídas de console ao iniciar sua aplicação, desde que seu mecanismo de logger esteja configurado para os warnings do Hibernate, poderá ver alguma recomendação sobre o tema, além de experimentar alguns problemas como o relatado na abertura deste post.

Para solucionar a questão, basta implementar um gerenciador de pool de conexão de terceiros suportado pelo Hibernate. O mais utilizado é o c3p0 e para configurá-lo basta incluir o seu .jar no classpath da aplicação e configurar seus parâmetros no seu arquivo de configuração do hibernate. Para quem utiliza o hibernate.cfg.xml, basta incluir neste arquivo as seguintes linhas:

<property name="hibernate.c3p0.min_size">3</property>
<property name="hibernate.c3p0.max_size">10</property> 
<property name="hibernate.c3p0.timeout">90</property>  
<property name="hibernate.c3p0.idle_test_period">120</property> 

 No trecho acima, configuramos, respectivamente, o número mínimo de conexões no pool, o número máximo de conexões no pool, o tempo, em segundos, em que cada conexão irá expirar se não houver atividade e de quanto em quanto tempo, em segundos, a vida das conexões no pool deverá ser testada.

Em versões mais recentes do Hibernate, também pode ser necessário informar quem fará a gerência do pool de conexões com a seguinte linha no mesmo arquivo hibernate.cfg.xml, complementando as configurações já comentadas:

<property name="hibernate.connection.provider_class"> org.hibernate.connection.c3p0ConnectionProvider 
</property>

Existem outros parâmetros configuráveis do c3p0.

Para decidir que parâmetros configurar e com que valores, é necessário um estudo dos requisitos não funcionais da aplicação e a realização de testes em busca da melhor configuração para o cenário pretendido.

Veja um exemplo com base nas configurações anteriormente citadas (hibernate.c3p0.max_size = 10): Para descobrir o número máximo de transações para o seu cenário, basta que você conheça o tempo de sua transação mais demorada. Imaginemos que a transação mais demorada para o seu caso seja de 2 segundos. Significa dizer que se você tiver 10 acessos concorrentes, o 11o. visitante a requisitar uma conexão, na pior das hipóteses, teria que esperar 2 segundos. Em outras palavras seria possível, no pior cenário, atender 5 requisições transações simultâneas por segundo, 300 por minuto e 18000 por hora . Portanto, cuidado com os números que vai escolher!

ATENÇÃO: Não se esqueça de compatibilizar os números de conexões no pool do c3p0 com os números de conexões no pool do banco de dados que você utiliza. Não adianta muito configurar o c3p0 para o máximo de 30 conexões no pool se o seu banco está configurado para um máximo de 5 conexões no pool.

Existem também outros gerenciadores de pool para o Hibernate como o proxool e o dbcp pool da Apache.

Espero que este post possa servir de ajuda assim como estas informações também me foram úteis um dia.

Para referência:

http://docs.jboss.org/hibernate/core/3.5/reference/pt-BR/pdf/hibernate_reference.pdf

http://blog.caelum.com.br/2010/04/14/as-dependencias-do-hibernate-3-5/

http://blog.caelum.com.br/2008/09/02/vazamento-de-memoria-e-de-conexoes/

Comente, critique e participe. De antemão já te agradeço.