A história nos mostra que até pouco tempo atrás os
programadores eram completamente responsáveis pelo gerenciamento do ciclo de
vida de todos os objetos decorrentes da implementação. Ou seja, os programadores
escreviam o código para criar, relacionar, usar e destruir objetos
ao longo da execução da determinada solução.
Atualmente este quadro está mudado, vemos
as tecnologias chamadas de “server side” a cada dia engolindo estas
responsabilidades. Eu poderia até me arriscar a afirmar que esta
responsabilidade já foi retirada das mãos dos programadores e passada a ser
implementada pela parte “infraestrutural” da solução.
Para aqueles que ainda
não conseguiram visualizar o fato, a questão chave é entender que implementar
manualmente este gerenciamento de objetos não é uma tarefa trivial, que pode ainda
cresce em complexidade devido à natureza e à escalabilidade da solução.
A tecnologia java vem seguindo esta tendência e amadurecendo juntamente ao longo
dos anos e hoje vemos especificações dos chamados “containers“.
que têm se tornado a parte infraestrutural de sistema com o propósito de assumir
esta responsabilidade.
Resumindo: gerenciar todos os possíveis objetos em uma solução flexível, escalável e
algumas vezes distribuída é uma tarefa muito complexa, que por este mesmo motivo
foi abandonado pelos programadores e passado para componentes de softwares
externos apelidados de containers.
Injeção de Dependência – DI
Se nos aprofundarmos na questão, veremos que a evolução natural do gerenciamento
de objetos por estes controladores externos, chamados de containers, levou à criação de um padrão que revolucionou a forma de se construir programas
orientados a objetos. É aí que entra a conhecida Dependecy Injection – DI, ou injeção de dependência, antigamente chamada de Inversion of
Control – IoC (inversão de controle). A DI define um padrão de
desenvolvimento de programas
de computadores utilizado quando é necessário manter baixo o nível de acoplamento entre diferentes
módulos de um sistema. Nesta solução as dependências entre os módulos não são
definidas programaticamente, mas sim pela configuração de uma infraestrutura de
software container que é responsável por “injetar” em cada componente suas
dependências declaradas.
Conceitos Chaves da DI
Os containers, que já eram responsáveis por cuidar dos objetos, passaram a
fazê-lo com muito mais classe e flexibilidade com a adoção da DI, que foi
rapidamente popularizada. Segue abaixo um descritivo básico e prático
de conceitos de um container com injeção de dependência:
1. Construção de Objetos – os desenvolvedores deixaram de implementar a
construção dos objetos, passando a delegar configuravelmente isso dentro do
container de DI. Isto é bem simples de entender: não existe mais operador
new dentro dos programas! Isto é feito automaticamente e “debaixo dos panos”
pelos container. O programador simplesmente configura isso de alguma forma no
container.
2. Inicialização de Propriedades – os
desenvolvedores deixaram de
implementar a definição de valores padrões para as propriedades
de um objeto criado, delegando também de forma configurável nos containers.
3. Gerenciamento de Dependência – os
desenvolvedores deixaram de
implementar as dependências entre os objetos do sistema,
delegando, também de forma configurável, nos containers.
4. Ciclo de Vida – os desenvolvedores deixaram de implementar o
tamanho e a forma de visibilidade dos escopos referentes aos objetos durante a
execução, passando a configurá-los muito mais facilmente dentro do
containers.
5. Configurações declarativa – um container DI deve fornecer
uma forma de configuração declarável, ou seja: o meio de declaração de ser um
arquivo externo de fácil edição e alteração. O XML tem sido o predominante.
O que eu gostaria de pontuar é que eu, redundantemente, destaquei as palavras
“deixaram de
implementar“ com o propósito de gerar no leitor a idéia
de que, com o uso de container de DI, o código-fonte final deixa de possuir as
características acima mencionadas.
Containers Java
Atualmente existem vários containers já consagrados na tecnologia java,
alguns padrões baseados em especificações e outros proprietários. Em alguns
casos é até viável combinar alguns dentes em uma mesma solução para se chegar a um ambiente desejado. Aqui vão algumas sugestões de estudo: Spring, HiveMind e Guice. Não vou indicar
e nem comentar outros containers porque o foco de hoje é mostrar que dentro do JavaServer Faces existe
um completo container de DI. Tenho percebido, ao longo de minhas
consultorias, que poucas pessoas o conhecem e o usam de verdade.
JSF Managed Bean Facility Container – JSF
Para aqueles que nunca ouviram falar, a tecnologia JSF vem com um completo
container DI embutido, chamado de Managed Bean Facility. Com ele é
possível fazer todas as operações básicas de um container. O objetivo deste artigo é apresentar estas operações, mostrando que, na maioria das vezes, os
desenvolvedores não precisam gastar horas e horas resolvendo ou costurando
outros containers externos em aplicações web usando JavaServer Faces.
01. Construção de Objetos
Uns dos primeiros critérios importantes para um container DI é controlar o
ciclo de vida (vida e morte) dos objetos. O JSF Bean Facility oferece uma
robusta solução para isso. A implementação é feita pela configuração de
qualquer POJO
no arquivo arquivo faces-config.xml. Veja o exemplo da definição de uma
classe e sua configuração que instrui o JSF Bean Facility a gerenciar os objetos
dentro de um escopo denominado “request”:


Acabamos de configurar um objeto para ser criado e destruído a cada pedido
HTTP feito para aplicação JSF. As páginas faces podem referenciar este objeto
usando a EL – Expression Language
#{clienteBean.nome}.
02. Ciclo de Vida
Algo importante para se pontuar é que existem quatro escopos que podem ser
utilizados para delimitar o “tempo de vida” de um objeto. Segue um resumo
deles:
- application – criado e armazenado no contexto do servlet.
Todos os usuários da aplicação compartilham este objeto. Ele é destruído quando
a aplicação for desligada “undeploy”. - session – criado quando a aplicação precisar usar e é
armazenado na sessão servlet de cada usuário. Cada usuário terá seu próprio
objeto. Ele é destruído quando a sessão do usuário for destruída, não importa a
forma. - request – criado e armazenado no request servlet do pedido
HTTP. Ele é destruído ao término da resposta HTTP. - none – criado e não é armazenado em nenhum lugar. Ele é
criado e passado para o recurso que necessitar. Este objeto não é destruído
pelo JSF Bean Facility, ficando a cargo do recurso que está usando se
responsabilizar por isso.
03. Inicialização de Propriedades
JSF Bean Facility possui mecanismos bem simples para serem instruídos a
inicializar propriedades dos objetos que estão sob o seu controle. Segue o
exemplo que acrescenta a configuração das propriedades da classe
exemplo.Cliente usada no exemplo anterior:

04. Gerenciamento de Dependências
Cuidar das dependências entres os objetos é um dos requisitos fundamentais
de um container, e o JSF Bean Facility também não deixa a desejar. Os
relacionamentos entre os objetos podem ser declados
no faces-config.xml através da EL – Expression Language. A única
limitação do JSF Bean Facility que vale ser citada é que ele não faz
“dependências cíclicas”. Segue abaixo a continuação do mesmo exemplo da classe
exemplo.Cliente que agora é agregador de uma classe de chamada de
exemplo.Nota. Ou seja, um objeto de Nota será criado e injetado em
um objeto Cliente. Veja as classes completas e a configuração declarativa:


Arquivo faces-config.xml:

Eu coloquei a declaração dos objetos em sequência lógica para ficar
didaticamente mais intuitivo, mas eles podem ser declarados em qualquer ordem que
serão resolvidos de qualquer forma. Algo importante de se ressaltar é que existe
uma simples regra: o escopo do objeto agregador deve ser igual ou maior ao do objeto
dependente. Para qualquer dúvida, releia o tópico 02, que apresenta todos os
escopos existentes no container JSF.
Conclusão
JSF Bean Facility reafirma, então, a popularização do desenvolvimento baseado
em POJOs e a centralização de gerenciamento de objetos baseando em containers.
Mesmo ele não oferecendo um leque completo de recursos + serviços, como
encontrado em outros container conhecidos no mercado, o JSF Bean Facility é
suficiente eficaz para controlar objetos que serão utilizados na camada da
visão, que é o lugar do própria filosofia da especificação JSF.
Vale lembrar
que outros containers mais completos podem ser integrados com ele, criando, assim,
um ambiente único para suportar outras camadas e serviços para o aplicativo
final.
Os exemplos apresentados foram elaborados com o objetivo único de
apresentar e pontuar os determinados recursos discutidos em questão, estando
eles incompletos. Estou à disposição para qualquer eventual dúvida, ajuda ou
idéia complementar. Para todas as informações e possibilidades consulte os
livros Core
JSF ou JSF in Action.
Até a
próxima.







