sexta-feira, 27 de novembro de 2009

Guicifique seus Testes - Parte 6

Esta é sexta parte da tradução para português do interessante artigo Guicing Up Your Testing, June 21, 2007, por Dick Wall. Trata-se de uma leitura interessante, que junta dois tópicos que estou estudando atualmente: Teste Unitário e Google Guice, além de falar um pouco sobre Injeção de Dependências e os Padrões de Projeto Singleton e Factory.

Índice

Uma rápida reflexão sobre Design Patterns

A afirmação sobre a bala de prata se aplica, em minha opinião, tanto para o uso de bibliotecas como o Guice quanto para Design Patterns. Padrões de Projeto podem encapsular conceitos importantes, mas usá-los indiscriminadamente pode levar a problemas similares aos que tivemos ao jogar todas as responsabilidades para cima do Guice.

Lembremos que a modelagem inicial do teste estava particularmente difícil de testar justamente devido a uma aplicação pouco flexível do padrão Singleton, que era difícil de ser substituída por outra mais adequada. Uando o Guice, acabamos por aplicar o mesmo padrão Singleton, mas de forma diferente, deixando claro que a culpa não era propriamente do padrão Singleton, mas sim da forma como ele havia sido implementado.

Ainda assim, não se pode tentar pensar sempre em termos de padrões de projeto, na medida que agindo dessa forma pode-se limitar bastante as possíveis abordagens de desenvolvimento. Padrões de Projeto possuem seu valor, assim como os Anti-Patterns, e ainda mais importante, a Criatividade e o Pensamento Original e Independente.

Modelagem usando Guice e o Padrão Factory

Neste exemplo, encontrei um forte exemplar de como combinar a Injeção de Dependências oferecida pelo Guice e o Padrão de Projeto Factory. Iremos usar o Guice para criar objetos FabricaPedidos, que serão injetadas como o objeto GerenciadorTaxaJuros cofigurado nos bindings do Guice. Iremos então usar esta Fábrica para criar os objetos Pedido. Ao tirar do Guice a responsabilidade de criar os objetos da classe Pedido, ela pode voltar a ter ambos os atributos Cliente e GerenciadorTaxaJuros populados via construtor, com ambos os atributos podendo ser marcados como imutáveis.

Desta forma, corrigimos os problemas que introduzimos no código ao adaptá-lo para fazer uso da Injeção de Dependências. Vamos ao código. Na classe Pedido, reescrevemos o construtor, e retiramos a anotação @Inject (já que ela não vai mais ser diretamente gerenciada pelo Guice!).

Note que restauramos a palavra reservada final ao atributo cliente, e que o construtor recebe como argumentos tanto o GerenciadorTaxaJuros como o cliente. Como o Guice não fará mais a injeção através desta classe, criamos uma FabricaPedidos, que irá fazer este trabalho:

Não devem haver surpresas até aqui: o Guice irá injetar um GerenciadorTaxaJuros via construtor da classe FabricaPedidos. Agora, para criar um pedido, iremos chamar o método criaPedidoParaCliente, passando como parâmetro o cliente deste pedido. O método criará o Pedido, usando o GerenciadorTaxaJuros injetado pelo Guice, e o Cliente informado através da chamada da API FabricaPedidos. Vejamos o que ocorre com os testes:

Ao invés de criar um Pedido no construtor, agora criamos uma Fábrica de Pedidos. No teste, esta fábrica é usada para criar objetos Pedido, para os clientes aplicáveis. Esta implementação é muito mais limpa do que a anterior, e recuperamos a imutabilidade dos atributos da classe Pedido.

Melhorias Adicionais

Outra coisa a ser notada é que, ao invés de a busca em `GerenciadorTaxaJuros` receber como parâmetro um ID de um `Cliente`, faz mais sentido receber um objeto `Cliente`, fazendo a busca baseada neste objeto. Isto torna a API mais limpa e flexível, uma vez que permitiria que a busca possa ser parametrizada também por outros atributos da classe `Cliente`, caso conveniente. Desta forma, atualizamos a interface `GerenciadorTaxaJuros`:

E sua implementação fake:

O método `calculaTotalComTaxas` da classe `Pedido` também precisa ser refatorado para receber um objeto `Cliente` ao invés de seu ID:

A Biblioteca AssistedInject

Utilizar o padrão Factory em conjunto com Injeção de Dependências solucionou as deficiências introduzidas no final do primeiro artigo, então podemos nos perguntar se o próprio Guice não poderia oferecer alguma forma de contornar estas limitações, uma vez que elas parecem ser bem comuns.

Talvez o Guice possa, em breve. Jesse Wilson e Jerome Mourits, engenheiros da Google, criaram uma extensão do Guice chamada AssistedInject, que formaliza o uso do padrão `Factory` para ser mais facilmente utilizado com o Guice. Uma descrição do que ela faz pode ser encontrada em:

  • http://groups.google.com/group/google-guice/browse_thread/thread/9a7e2c57583d21d6
  • http://code.google.com/p/google-guice/wiki/AssistedInject

Conclusão

Vimos, portanto, que a Injeção de Dependências, por mais útil que seja, é apenas mais uma ferramenta na caixa de ferramentas. Ela pode ser utilizada com outras boas práticas e padrões de projeto quando apropriado, e quando fizer sentido. Usado corretamente, ele pode tornar mais bonitas a arquitetura e a implementação de uma aplicação.

Guicifique seus Testes - Parte 5

Esta é quinta parte da tradução para português do interessante artigo Guicing Up Your Testing, June 21, 2007, por Dick Wall. Trata-se de uma leitura interessante, que junta dois tópicos que estou estudando atualmente: Teste Unitário e Google Guice, além de falar um pouco sobre Injeção de Dependências e os Padrões de Projeto Singleton e Factory.

Índice

Não há bala de Prata

Na quarta parte desta série, precisamos refatorar a classe Pedido para que ela recebesse via construtor um objeto GerenciadorTaxaJuros. Esta medida foi necessária para que o Guice pudesse realizar a injeção de dependências via construtor. Porém, como criação de objetos Pedido agora seriam controlados pelo Guice, perdemos a liberdade de fornecer ao Pedido, via construtor, o objeto Cliente com quem ele se relaciona.

Podemos ponderar se o próprio objeto cliente poderia ter sido injetado pelo Guice, mas isso não se aplica neste caso: precisamos ter a liberdade de criar pedidos para diferentes clientes (ainda neste teste, poderíamos também incluir a checagem da taxa para um segundo cliente!), portanto a informação encapsulada pela classe Cliente está fora dos limites da classe Pedido.

Usar um método setter é a forma mais prática de contornar o problema, mas venhamos e convenhamos, ela é sub-ótima. Talvez o maior problema esteja na perda de mutabilidade: um objeto pedido existente pode ter seu cliente alterado, o que não soa particularmente seguro. Olhando por este prisma, não é desejável permitirmos que o cliente mude após ele ser atribuído ao pedido.

Poderíamos incluir código condicional dentro do setter, por exemplo lançando uma exceção em caso de tentativa de alteração, mas vamos encarar: isto começa a cheirar novamente a bacalhau.

Outro risco de permitir a mutabilidade é que alguém pode agora criar um pedido e esquecer de informar o cliente. O código (deliberadamente) não está mais protegido desta circunstância, podendo falhar com uma exceção do tipo NullPointerException ao se tentar calcular o total do pedido sem ter especificado o cliente deste pedido.

Ao me deparar com o problema da mutabilidade, isso me bloqueou por algum tempo. Certamente isso degradou aquilo que era um exemplo simples e claro em algo não tão limpo. À medida que refletia sobre isso, porém, percebi que este problema tinha valor em si!

Ele trouxe à tona um ponto importante: apesar de que a injeção de dependências seja uma ferramenta fantástica para melhorar o estilo e a modelagem de código, ela não é uma bala de prata. Da mesma forma como muitas outras ferramentas que o precederam, o Guice é surpreendentemente útil e hábil, mas não é a resposta para todos os problemas (nem mesmo para a maioria dos problemas).

Eu realmente gosto de bibliotecas que não tentam ser a solução definitiva, ao invés disso elas fazem algo específico, se propondo a fazer este algo realmente bem feito. Neste ponto, o Guice é muito bem sucedido: é a solução perfeita para Injeção de Dependências em Java: é leve, simples e rápido.

Por outro lado, mesmo um exemplo de teste bem simples evidencia algumas de suas limitações. Tão logo perdemos o controle da criação do Pedido, ao delegar este controle para o Guice, perdemos também o controle sobre a imutabilidade do atributo Cliente da classe Pedido.

Deve estar evidente que delegar ao Guice a criação direta de objetos Pedido foi uma decisão incorreta de modelagem. O problema de setar o cliente para um pedido merece uma boa solução, porém esta solução virá de um ângulo diferente daquele que nos é oferecido pela injeção de dependências. Ao invés disso, podemos mesclar esta abordagem com um outro Padrão de Projeto: Fábrica (Factory Design Pattern).

Guicifique seus Testes - Parte 4

Este artigo é quarta parte da tradução para português do interessante artigo Guicing Up Your Testing, June 21, 2007, por Dick Wall. Trata-se de uma leitura interessante, que junta dois tópicos que estou estudando atualmente: Teste Unitário e Google Guice, além de falar um pouco sobre Injeção de Dependências e os Padrões de Projeto Singleton e Factory.

Índice

Colocando o Guice em Ação

A última coisa que ainda falta fazer é fazer o setup do Guice na aplicação que ele irá rodar. Todas as peças estão no lugar agora, mas o Guice ainda não está sendo invocado em lugar algum.

Aqui está uma grande regra trazida por Zorzella e Sasha, da Google, e que é boa para se ter sempre em mente: Guice is the new "new" - em outras palavras, Guice é o nova forma de se usar o operador "new".

Numa aplicação Guice, não veremos mais tantas chamadas de construtores (new()). Ao criar um objeto usando new, não tem como envolver o Guice no processo de resolver as dependências para este objeto. Para fazer proveito do poder de autowiring, é necessário usar o Guice para criar os objetos. Vamos dar uma olhada no setup da classe de testes:

Note que pedimos ao Guice para nos retornar um gerenciadorTaxas baseado apenas na interface TaxRateManager?. Nosso código de testes, portanto, não possui mais nenhuma dependência direta a uma implementação concreta, as dependências são todas encapsuladas nas regras de binding dentro da classe ModuloTestarTaxaJuros?.

Mas espera lá, na classe ModuloTestarTaxaJuros? não definimos nenhum binding para a classe Pedido, então como é que o Guice sabe o que fazer na chamada abaixo?

O Guice possui uma regra especial para difinição de classes concretas. Como Pedido é uma classe (e não uma interface), o Guice consegue adivinhar que precisamos que ele crie um objeto desta classe para nós. Porém ele vai além, ele injeta no objeto as dependências explicitadas em seu construtor marcado com a anotação @Inject.

Agora podemos enfim chegar ao teste propriamente dito, que sofre uma ligeira alteração. Lembre que tiramos do construtor da classe Pedido o parâmetro Cliente e o colocamos em um setter. Portanto, precisamos agora fornecero cliente através deste método e não mais através do construtor:

Resultados

Depois de todo este trabalho, analisemos os resultados. Executando o teste original, simulando 5 segundos de latência para cada operação realizada no banco de dados, o JUnit mostra a seguinte saída:

Ao usar o Guice para injetar a implementação fake baseada em um HashMap?, obtemos um resultado bem mais razoável:

É uma melhoria de duas ordens de grandeza! Tudo bem, este é um exemplo inventado, mas a experiência real me diz que ele não é tão desconectado da realidade. eliminar dependências com operações de I/O, bancos de dados, serviços remotos, e assim por diante, causa uma melhoria dramática na velocidade dos testes unitários.

Isto significa que é possível rodar mais testes em menos tempo, e que estamos testando uma coisa de cada vez, sem se distrair com coisas que não têm relação direta e relevante com o teste propriamente dito (ao testar a lógica de cálculo de taxas, não há razão nenhuma de precisarmos obter informações necessariamente de um banco de dados). Ao invés disso, podemos simplesmente simular o comportamento destes componentes de baixo nível.

Guicifique seus Testes - Parte 3

Este artigo é terceira parte da tradução para português do interessante artigo Guicing Up Your Testing, June 21, 2007, por Dick Wall. Trata-se de uma leitura interessante, que junta dois tópicos que estou estudando atualmente: Teste Unitário e Google Guice, além de falar um pouco sobre Injeção de Dependências e os Padrões de Projeto Singleton e Factory.

Índice

Introdução ao Guice

Neste contexto é onde o Guice se encaixa perfeitamente. Ele nos dá o poder de definir uma configuração que mapeia as implementações de objetos a uma forma simples de localizá-los e obtê-los. Quando se pede um objeto para o Guice, ele não só irá procurar por aquele que foi solicitado, mas também irá percorrer o objeto procurando pelas suas dependências, e injetando os tipos corretos de dependência para o contexto aplicável. Ou seja, ele fará todo o trabalho de auto-conectar as dependências entre os objetos, eliminando a necessidade de injetá-las manualmente usando passagem de parâmetros pela aplicação.

Vejamos como é fácil começar a usar o Guice: baixe a versão mais atual desta biblioteca em http://code.google.com/p/google-guice, descompacte o arquivo, procure pelo arquivo guice-VERSION.jar, e adicione-o ao classpath de seu projeto. Feito isso, o Guice está pronto para usar. Ele nada mais é do que um conjunto de anotações para classes e uma simples API para configurar os módulos que irão conectar os objetos da maneira adequada. NA verdade ele é um pouco mais que isso, mas neste momento focarei apenas nas funcionalidades principais.

Voltando ao Exemplo

Vejamos o que o Guice pode fazer por nós. Primeiro, vamos deixar para o Guice a responsabilidade de preparar a classe Pedido toda vez que precisarmos utilizá-la. Sendo mais específico, queremos que o Guice forneça o GerenciadorTaxasJuros adequado para o contexto que a classe Pedido está sendo usada, seja em testes ou em produção:

As mudanças neste ponto incluem:

  • importar a anotação Inject; e
  • adicionar a anotação @Inject antes do construtor da classe Pedido.

Pode-se notar também que fizemos algumas regressões na modelagem, pois já não mais passamos um objeto Cliente através do Construtor - ao invés disso, agora ele deve ser injetado via um método setter. Desta forma, também é necessário retirar do atributo cliente o modificador final, pois para poder usar o setter, o atributo precisa ser mutável. Demos alguns passos para trás, mas voltaremos a falar sobre isso no final deste artigo.

Por agora, a anotação @Inject é a coisa mais importante a se notar. Ela indica para o Guice que ele é responsável pela construção de objetos dessa classe. Por mais que também seja possível criar objetos utilizando a classe da forma tradicional, iremos a partir de agora usar o Guice para fazer isso por nós, pois ele:

  1. Verifica que há uma anotação @Inject no nível do construtor.
  2. Verifica a assinatura dos tipos de parâmetros do construtor.
  3. Para cada um dos parâmetros, ele tenta encontrar um objeto adequado e injetar no objeto, durante a sua criação.
  4. Não há passo 4 (bom, na verdade há: se por algum motivo o Guice tiver problemas em resolver as dependências concretas que deve passar para algum parãmetro do construtor, ele automaticamente lança um erro que nos ajudará a rastrear e corrigir o problema).

Tudo isso parece mágica, mas não é. Para o Guice funcionar, informaremos a ele tudo o que ele precisa saber sobre como criar os objetos que irá injetar em cada parâmetro do construtor. Vamos juntar as peças.

Configuração dos Bindings (conexões entre objetos)

Primeramente, explique para o Guice o que você pretende fazer quando ele for solicitado para injetar um GerenciadorTaxasJuros em outro objeto (lembre que GerenciadorTaxasJuros é uma interface, então é necessário criar alguma de suas implementações concretas para que possa ser utilizado).

Para ensinar o Guice, criamos um módulo de configuração, com um binding dentro dele:

Pronto! Isto cria uma subclasse de Module explicando ao Guice que, quando você precisar de um GerenciadorTaxasJuros, o que você realmente quer, para propósitos de teste, é um objeto de GerenciadorTaxasJurosFake. Em produção, você pode ter um outro módulo que instrui o Guice a usar a implementação GerenciadorTaxasJurosBd.

É aqui que o "pulo do gato" de auto-conexão entre os objetos (auto-wiring) ocorre. Logicamente, em um sistema real, provavelmente haverão muito mais definições de binding, onde tudo o que é necessário é simplesmente adicionar mais chamadas binder.bind. Muitos erros encontrados em grandes sistemas que usam o Guice podem ocorrer devido à ausência de bindings, mas estes tipos de erro são reportados de uma maneira que se torna óbvio percebr quando algo está faltando.

Tem mais uma coisa: mencionamos antes que usar um único objeto GerenciadorTaxasJuros em toda a JVM seria uma boa idéia, porém fazer isso na forma de singleton estáticos é algo muito limitador (o alto acoplamento dificulta, entre outras coisas, escrevermos bons testes). Guice vem nos salvar deste embróglio provendo um "escopo" Singleton para podemos implementar os bindings. Uma forma de se fazer isso, é adicionar na configuração uma chamada ao método in(Scopes), onde Scopes é uma classe da API do Guice:

A outra forma, ainda mais prática, é utilizar a anotação @Singleton diretamente na definição da classe GerenciadorTaxasJurosFake.

Ambos possuem vantagens e desvantagens, porém é muito mais uma questão de preferência qual delas se deve escolher. Prefiro usar a anotação, pois ela expressa diretamente na classe GerenciadorTaxasJurosFake a intenção semântica de que um único objeto dela será criado para atender a todos as dependências a esta classe dentro da JVM.

Guicifique seus Testes - Parte 2

Este artigo é a segunda parte da tradução para português do interessante artigo Guicing Up Your Testing, June 21, 2007, por Dick Wall. Trata-se de uma leitura interessante, que junta dois tópicos que estou estudando atualmente: Teste Unitário e Google Guice, além de falar um pouco sobre Injeção de Dependências e os Padrões de Projeto Singleton e Factory.

Índice

Introdução à Injeção de Dependências

A solução mais simples é eliminar a dependência com o singleton. Para testar a classe Pedido, não há necessidade de realizar uma chamada real a um banco de dados, mesmo que o banco de dados seja rápido o suficiente. O que precisamos na classe GerenciadorTaxasJurosBD são dois métodos: atribuiTaxaParaCliente e verificaTaxaParaCliente. Este último usa o ID do cliente e retorna um double. Esta funcionalidade pode ser fornecida facilmente por um HashMap ao invés de ter que consultar o banco de dados, sendo a implementação com HashMap? mais rápida e leve.

A técnica de criar uma implementação de uma classe como esta, que imita o comportamento desejado para a implementação real, é conhecida como Fake Objects. É diferente da técnica Mock Objects, que veremos adiante (a técnica Mock Objects tem mais a ver com prover ao objeto um roteiro de passos que se espera que ele execute, e verificar se o roteiro foi realmente obedecido).

Voltando ao assunto, o que importa aqui é que para testar a classe Pedido e o seu cálculo para taxar uma determinada venda, não importa quem faz o trabalho de verificar qual o valor da taxa aplicável ao Cliente. Assumindo que o único trabalho de um GerenciadorTaxasJuros seja armazenar e recuperar a taxa usando o ID do cliente, podemos trabalhar com a seguinte implementação:



Há algumas coisas para observar aqui. Primeiro, esta implementação é bem simples. Mais importante, ela armazena tudo em memória, nunca chegando nem perto de um banco de dados, então ela tende a ser realmente eficaz para se utilizar em um teste unitário. Todos os dados necessários podem ser configurados no próprio teste, sem necessidade de armazenar nada no banco de dados.

A segunda coisa é que agora a classe agora implementa a interface GerenciadorTaxasJuros. Para a injeção de dependências funcionar, é necessário criar uma interface que a classe Pedido possa usar, ao invés de expor dentro dela uma implementação específica. A interface deve se parecer com o código abaixo:


Agora, na classe Pedido, podemos substituir todas as referências à classe GerenciadorTaxasJurosBD pela interface GerenciadorTaxasJuros. Isto nos traz toda sorte de benefícios além da testabilidade, que irei cobrir em futuros artigos?.

Em poucas palavras, tudo o que fizemos até aqui foi para eliminar uma dependência que o código tinha com uma implementação. Pedido agora não está mais amarrado a uma classe que o obriga a acessar o banco de dados. Ele agora se comunica através de uma interface, não importando para ele qual a implementação real que vai utilizar, desde que a implementação cumpra o contrato que é estabelecido pela interface.

É claro, agora é necessário, alguma forma, prover para o pedido uma implementação de GerenciadorTaxasJuros. Em produção, iremos fornecer para o pedido a implementação GerenciadorTaxasJurosBD, mas em ambiente de teste, podemos oferecer GerenciadorTaxasJurosFake, que é mais eficaz nexte contexto.

A forma mais fácil de fazer isso (sem ainda utilizar uma framework como o Guice), é simplesmente injetar a implementação desejada da interface GerenciadorTaxasJuros através do construtor da classe Pedido:


A partir de agora, todas as vezes que um pedido for criado

  • em ambiente de produção, podemos injetar um objeto GerenciadorTaxasJurosBD
  • em ambiente de testes, podemos injetar um objeto GerenciadorTaxasJurosFake, que é mais eficaz.

Se você conseguiu entender o conceito acima, você agora compreende tudo o que precisa saber sobre Injeção de Dependências. É apenas uma maneira especial de dizer para o pedido "Eu vou dizer onde você vai buscar os dados quando eu te configurar". Se isso é tudo o que tenho que falar sobre injeção de dependências, então onde é que entra o Guice?

Pense no seguinte: se você tiver que usar o construtor em toda parte em sua aplicação, o que isto acarretará ao seu código? Por um lado, você agora terá bastante trabalho adicional, tendo que passar pra lá e pra cá os objetos que deseja injetar através da aplicação. Toda vez que precisar de um Pedido, onde quer que seja na aplicação, terá de injetar manualmente uma implementação da interface GerenciadorTaxasJuros.

Posso até conseguir alguma forma mais prática de fazer isso, mas provavelmente ela provocará o mesmo tipo de inflexibilidade / acoplamento que existia quando usávamos meramente um Singleton. Logo logo o código inteiro vai estar infestado de parâmetros sendo passados via construtores ou algum outro bacalhau que vai deixar o código cada vez mais sujo.

Além disso, apesar de que um Singleton que tantas pessoas usam em aplicações Java seja um estorvo, o fato de se reutilizar um único objeto GerenciadorTaxasJuros ao invés de ter que criar um novo cada vez que precisar passá-lo ao construtor da classe Pedido, este conceito ainda é bom e desejado.

Sem falar nos problemas relacionados a Thread Safety? ou gargalos de desempenho, instanciar mais de um objeto GerenciadorTaxasJuros - um para cada Pedido - em uma única JVM seria um desperdício de memória, uma vez que todos eles realizam exatamente o mesmo trabalho (e nem mencionamos o quão caro é construir novas conexões no caso da implementação que acessa o banco de dados).

Portanto, enquanto a Injeção de Dependências resolveu o problema de alto Acomplamento, ela introduziu muito mais problemas, e não é nada prática em aplicações de grande porte. É por este motivo que outros Padrões de Projeto?, como Fábricas? e Dicionários?, entre outros, se tornaram tão populares. Eles fornecem uma forma mais organizada de localizar utilizar objetos através da aplicação.

O problema com os dicionários e fábricas é que eles são pesados e normalmente são difíceis de configurar. Eles desempenham um importante papel em grandes sistemas coporativos, mas podem ser inviáveis de se utilizar em pequenos projetos. A maioria utiliza busca de objetos por nome através de Strings, o que carrega seus próprios riscos - Strings incorretas não podem ser capturadas pelo compilador e só vão manifestar problemas em tempo de execução.

O que precisamos, portanto, é de alguma forma de "conectar" (wiring) todas essas dependências entre objetos, e esta conexão deve ser feita em tempo de execução, para evitar alto acoplamento no código. Devemos ser capazes de configurar em algum lugar qual implementação precisamos utilizar em cada circunstância, e deixar que alguma biblioteca faça o trabalho de conectar tudo, seja para testes ou para produção.

Guicifique seus Testes - Parte 1

Este artigo é primeira parte da tradução para português do interessante artigo Guicing Up Your Testing, June 21, 2007, por Dick Wall. Trata-se de uma leitura interessante, que junta dois tópicos que estou estudando atualmente: Teste Unitário e Google Guice, além de falar um pouco sobre Injeção de Dependências e os Padrões de Projeto Singleton e Factory.

Índice

Introdução

O Guice é um container leve para injeção de dependências escrito por Bob Lee e Kevin Bourrillion, da Google. Este artigo examina o caso de uso mais simples e óbvio do Guice, para simular (mock) ou imitar (fake) objetos em testes unitários.

Se você já é familiar com a idéia de Objetos Mock e Objetos Fake, este artigo pode parecer tedioso (exceto a parte do Guice, espero). Porém, se você ainda não utiliou estas técnicas, este artigo vai além de cobrir a sua utilização: vai demonstrar também como estas técnicas andam de mãos dadas com a injeção de dependências.

O Caso de Teste

Para ilustrar o uso do Guice, é necessário configurar um exemplo de teste unitário. Vou me basear em algo relativamente simples:

O sistema possui uma classe Pedido, que usa um Gerenciador de Taxas de Juros para verificar qual a taxa que incide sobre uma venda para um determinado Cliente. O pedido acrescenta o valor da taxa ao valor total dos Itens do pedido. A taxa varia de acordo com o status do cliente, então o gerenciador procura a taxa de um determinado cliente usando o seu ID. Vamos supor que o Banco de Dados onde essas taxas ficam armazenadas está sobrecarregado com muitos registros, e que leva 5 segundos para executar qualquer tipo de consulta ou atualização.

Seu objeto de testes se parecerá com isto:

Vamos dar uma olhada nesta implementação. Para o construtor, observe que:

O construtor está obtendo um objeto GerenciadorTaxasJurosBD usando o padrão Singleton, uma forma bastante comum em muitos softwares atuais. Este padrão assegura que, em toda a máquina virtual, haverá apenas um objeto deste tipo, e ele deve ser obtido através de uma chamada estática da classe GerenciadorTaxasJurosBD .

Eu pessoalmente acho que o padrão Singleton, pelo menos na forma como a maioria das pessoas o implementam (chamada estática que retorna um atributo privado interno a uma classe) é um dos mais nocivos padrões GoF (veja [http:://a.b.c livro da Gang of Four]), entre outros numerosos padrões de autoridades mundo afora. O perigo está no fato de que é muito fácil de entender, muito sedutor, mas resulta em conseqüências indesejáveis em muitos e diversos aspectos.

Neste caso em particular, a implementação de GerenciadorTaxasJurosBD na forma de um Singleton implica que, todas as vezes que você criar um Pedido, você está amarrado a uma implementação específica, a que se comunica com o Banco de Dados. Este é o problema com o Singleton: ele torna muito fácil recuperar o gerenciador de taxas que precisamos consumir, mas o preço que pagamos é que ficamos presos a uma implementação específica, com pouca flexibilidade para alterar a implementação.

Por exemplo, quando você quiser testar esta simples classe de Pedido, o teste terá que usar a implementação GerenciadorTaxasJurosBD. Isto implica em fazer um busca no banco de dados, e com a performance que supomos inicialmente, isto vai nos tomar 5 segundos a cada operação. Desta forma, no método calculaTotalComTaxa(), a chamada

demora 5 segundos para retornar. Se considerarmos que na preparação da classe de testes inserimos 2 usuários de teste:

Ao configurar dois clientes fictícios (imitando o comportamento de clientes reais) e colocá-los no Banco de Dados com duas taxas distintas, a implementação Singleton nos obriga a fazer duas operações no banco de dados, perdendo outros preciosos 10 segundos, a cada teste! Ao rodar os testes, no melhor caso (rodando apenas as 3 operações descritas acima), o teste vai demorar 15 segundos para rodas. Imagine uma centena de testes como este, cada um demorando 15 segundos cada. Você vai ter que esperar um bocado...

O singleton portanto detona o desempenho de realizar testes. Você pode melhorar a situação procurando bancos de dados mais eficientes para usar, mas ainda assim sua implementação estará acoplada e limitada a uma implementação dependente de acesso a banco de dados, o que costuma ser ineficiente.

sexta-feira, 20 de novembro de 2009

Eclipse Chromium Javascript Remote Debugger

Fábio Miranda, em 17 Out 2009
Quem desenvolve aplicações Web, em algum momento com certeza já precisou escrever código Javascript, seja para dar mais interatividade a uma tela, para inspecionar elementos DOM da página, ou para fazer chamadas assíncronas com o servidor. E provavelmente já se deparou com situações onde era necessário debugar o código para investigar erros. Antigamente, eu utilizava uma forma bastante primitiva (e ineficiente) de depurar código javascript, uma versão tosca dos clássicos "printf" e "system.out": usava o Window.alert() para inspecionar o valor das variáveis. Esta abordagem é muito ruim: intrusiva (tem que alterar o código), ineficiente (é necessário que colocar vários alerts para acompanhar a evolução do valor da variável / objeto investigado), e nem sempre revela com clareza em que ponto do código pode estar localizado um bug. Felizmente, descobri ferramentas para isso.
  • No Internet Explorer, há o Microsoft Script Debugger (não é instalado por padrão, deve ser baixado no MSDN).
    • Na prática é uma versão tosca, porém mais elaborada, do Window.alert. É pouco amigável e possui poucos recursos (pelo menos era no tempo que experimentei).
  • No Firefox, há o Firebug, e a brincadeira começa a ficar interessante.
  • No Chrome, há o Javascript Console, meu favorito.
Com o Firebug e o Chrome, é realmente muito fácil e natural debugar código Javascript. Para ficar ainda melhor, existem plugins que integram esses debuggers com o Eclipse: Fireclipse e Chrome Eclipse Debugger. Irei mostrar a seguir como configurar o Chromium Debugger.

Chromium Javascript Remote Debugger

O primeiro passo é baixar o plugin do Eclipse:
  1. Help > Software Updates > Add Site...
  2. Em Location, copie e cole a URL: http://chromedevtools.googlecode.com/svn/update/dev
  3. Baixe o plugin e reinicie o Eclipse.

Passo-a-Passo

Usar o debugger consiste de três passos:
  1. Criar uma External Tool Configuration para o Eclipse iniciar o Chrome em modo de Debug
  2. Criar uma Debug Configuration que se conecta a este navegador.
  3. Criar breakpoints no Projeto criado automaticamente pela Debug COnfiguration.

Iniciar Chrome em modo de Debug

  1. Run > External Tools > External Tools Configurations
  2. Indicar a localização do chrome.exe
  3. Informar como Argumento a porta onde o navegador dever iniciar.
    • --remote-shell-port=9222
    • É necessário informar a porta, pois o debugger do eclipse se conectará ao Chrome por esta porta!

Criar Debug Configuration

Agora começa de fato o uso do plugin do Chromium.
  1. Vá no menu Run > Debug Configurations
  2. Clique em Chromium Javascript e crie uma nova configuração
  3. Coloque um nome de sua preferência:
    1. O primeiro nome se refere ao nome da Debug Configuration que será disponibilizado no botão "Debug As..."
    2. O segundo nome (Remote Scripts Project Name) é o nome do projeto que será criado no eclipse, onde poderemos selecionar os locais onde colocaremos os breakpoints
  4. Informe a portaatravés da qual o Debugger irá se conectar ao navegador do Chrome. (A mesma informada na External Tool Configuration acima)
  5. Caso deseje ver um log da comunicação entre o Eclipse e o Chrome em um Console do Eclipse, deixe marcada a opçãoShow debbuger network communication console)

Iniciar o Chrome, o Debugger, Setar breakpoints e Começar a Depurar!

Execute o Chrome e o Debugger a partir dos respectivos ícones (figura abaixo). Após rodar o Debugger, o plugin cria um projeto, que é listado no Project Explorer. Toda vez que uma página é acessada no Chrome, os fontes onde estão localizados código Javascript são listados nesse projeto, como na figura abaixo. Ao selecionar um desses fontes, podemos setar breakpoints (basta clicar duas vezes ao lado esquerdo da linha que se quer debugar). Todos as views do debugger (variables, expressions, breakpoints e threads) estarão disponíveis. Pronto! Debugar no Eclipse nunca foi tão fácil e produtivo. É lógico que vc pode usar o próprio Chrome para debug, mas na minha opinião:
  1. é mais fácil visualizar os valores das variáveis no Eclipse
  2. é possível caminhar pelo stack de execução de uma thread
  3. configurar expressões.
  4. usar o eclipse diminui a necessidade de ficar alternando entre várias janelas, tornando o trabalho menos cansativo.
  5. torna mais precisa a contagem de tempo do Mylyn, pois fica menos fora da IDE (diminui a imprecisão devido a paradas de contagem de tempo por o Eclipse estar ocioso).

Tutorial JPA com Hibernate e SchemaExport (Parte 1)

Fábio Miranda em 18 Out 2008

A JPA (Java Persistence Architecture) é uma poderosa API que o desenvolvedor Java deve dominar. Ela permite que se faça o mapeamento entre um Modelo Orientado a Objetos (OO) e tabelas do Modelo Entidade-Relacionamentos (MER) de um Banco de Dados - em outras palavras, Mapeamento Objeto-Relacional.

Há 3 modos de trabalho: OO >>> MER ou Top Down É sobre esta abordagem que falaremos neste artigo.

OO <<< MER ou Bottom Up Normalmente usado quando se lida com sistemas legados (portanto as tabelas já existem, e há pouca flexibilidade para mudanças nessas tabelas - o modelo OO deve se acomodar ao MER para possibilitar o mapeamento). Pode ser usada também quando se possui uma boa ferramenta de modelagem relacional, e é desejável ter um controle fino da DDL gerada.

OO <<--->> MER ou Meet in the Middle Mesclagem das abordagens anteriores (modela OO, modela ER, realiza mapeamentos (via annotations ou XML), e por fim testa cada entidade para verificar se a persistencia ocorreu conforme desejado).

A abordagem OO >>> MER de longe é a mais interessante das três, permitindo, inclusive, que as tabelas do banco de dados sejam criadas automaticamente, tornando o trabalho muitíssimo produtivo.

Vamos ao que interessa. As ferramentas usadas neste tutorial:

1) Setup

Realize os passos 1 a 3 deste outro post.

2) Configuração JPA no Eclipse

Crie uma pasta lib no seu projeto. Nela, iremos colocar as bibliotecas necessárias para usar o hibernate, para em seguida configurarmos o Build Path (para "importar" as bibliotecas para uso no Eclipse).

Tais bibliotecas podem ser localizadas nos respectivos diretórios descompactados da distribuição Hibernate (exceto as bibliotecas commons, cujas versões mais atualizadas podem ser obtidas no site Apache Commons).

Não podemos esquecer do driver do banco de dados, ou seja copiar C:\JavaDB\lib\derbyclient.jar para Locadora\lib, pois ele será necessário na configuração do Build Path.

Sua pasta lib agora deve parecer como a imagem abaixo:

Para configurar o Build Path, clique com o botão direito no nome do projeto e abra a janela de Propriedades

Escolha a opção para adicionar Jars do projeto

Então selecione todos os jars presentes na pasta lib

O projeto com as bibliotecas importadas deve parecer assim:

3) Persistence.xml

O próximo passo será criar o descritor META-INF/Persistence.xml. Mais abaixo segue o código deste descritor, pronto para copiar.

Neste descritor, devem estar presentes todas as informações relevantes para o Hibernate, por exemplo os parâmetros de acesso ao banco de dados. Estes podem ser fornecidos na forma de parâmetros de conexão JDBC (URL, nome do driver, etc...) ou simplesmente por meio do endereço JNDI de um datasource configurado em um Application Server.

Notar a string de conexão com o BD: jdbc:derby://localhost:1527/locadora;create=true.

- jdbc:derby://localhost:1527 informa onde localizar o Derby - locadora é o nome do banco de dados que será criado - create=true é o parâmetro que informa ao derby que, caso o banco não exista, é pra criá-lo.

Além disso, esse descritor permite que habilitemos funcionalidades interessantes, por exemplo SHOW_SQL, que escreve no console todas as queries que o Hibernate executa, e o Schema Export, que falaremos logo adiante.

4) EntityManagerFactory

Neste passo, criaremos uma classe de teste com um método main, apenas para iniciar a Unidade de Persistência que acabamos de configurar no persistence.xml. Note que está destacado em vermelho o nome da unidade de persistência que iremos utilizar (o mesmo nome que também está destadado em vermelho no descritor acima).

Perceba que podemos ter várias unidades de persistência declaradas no persistence.xml, e que elas podem ser consumidas pela aplicação criando a respectiva Fábrica de EntityManagers, conforme o código acima.

Antes de executar o teste, lembre que o banco de dados deve estar rodando. Caso não esteja, execute StartNetworkDerby. Só em seguida execute a classe de teste, clicando com o botão direito no corpo do método main e execute conforme a figura abaixo.

A execução deste teste deve demorar de 5 a 15s, e ao terminar exibe a mensagem "Schema Export Complete"

Como estamos usando o Derby como banco de dados, note que um novo diretório - locadora - é criado. Neste diretório o Derby armazenará todos os arquivos que dizem respeito a esse schema. Para vizualizá-lo, basta clicar no ícone do projeto e pressionar F5.

5) Modelo OO e Mapeamentos OR

Nesta parte 1 da série, mostraremos apenas uma classe simples, e o respectivo mapeamento com as anotações @Entity, @Id, @GeneratedValue e @Transient. No próximo artigo da série, iremos tratar as demais anotações da JPA. Segue abaixo seu código.

Execute novamente a classe Teste. Iremos verificar o que aconceceu com o banco usando através do plugin DTP do Eclipse (leia este post).

Ao mostrar o persistence.xml, lembra que falamos do Schema Export? Ele pode ser configurado via parâmetro do persistence.xml.

Na inicialização do Hibernate (criação da EntityManagerFactory de uma unidade de persistência), o Schema Export pode criar automaticamente as tabelas do banco de dados, a partir de todas as classes anotadas com @Entity, e seus respectivos mapeamentos objeto-relacionais expressos por meio de anotações Java.

Como resultado, foi criada a tabela PERSON, com os campos ID (chave primária ou Primary Key ou PK) e Name, do tipo varchar. Os campos estáticos e transientes de nossa classe não foram mapeados para colunas do banco de dados.

Note o poder que isto representa: trabalhamos o tempo todo com Java, e de quebra ganhamos o banco de dados prontinho para uso!

Neste artigo, tivemos todo o cuidado de fazer um tutorial hands-on, que qualquer javeiro consiga executar. Nos próximos artigos desta série, iremos nos preocupar apenas com os conceitos Objeto-Relacionais de JPA, mostrando como as classes, hierarquias de classes e relacionamentos são mapeados para tabelas e colunas do banco de dados. E melhor: tudo de forma automática, com o Schema Export que acabamos de mostrar.

Anotations serve para que?

Fábio Miranda em 22 Set 2008

http://tech.groups.yahoo.com/group/riojug/message/21020

O melhor exemplo que me vem à cabeça é JPA.

Antes:

Depois:

Multiplique isso num sistema com 50 entidades...

Ou seja: Do modo tradicional, para cada entidade do sistema, é necessário manter um arquivo em XML que faz o mapeamento objeto-relacional.

Com annotations, você lida apenas com a classe Java, e "Anota" aquilo que vc teria de fazer via XML.

Vantagens de Annotations: - Menos artefatos para dar manutenção. - Mais fácil de refatorar. - Programação "por Convenção" - p. ex., todos os atributos da sua classe são "convencionalmente" entendidos como colunas do mapeamento, exceto quando forem estáticos ou transientes. (no xml, todo atributo teria de ser mapeado para uma coluna).

Desvantagens: é intrusiva, ou seja, o código fica "recheado" de "configurações" que não necessariamente têm a ver com o domínio do problema - ou em outras palavras, revelam detalhes de implementação.

8 Reasons Why CIOs Think Their Application Developers Are Clueless

Fábio Miranda em 12 Set 2008

Postado recentemente no RioJUG, uma leitura interessante: 8 Reasons Why CIOs Think Their Application Developers Are Clueless.

GWT Getting Started Tutorial

Fábio Miranda em 10 Set 2008

Neste Link pode ser acessada a tradução do Getting Started da documentação do Google Web Toolkit. Boa diversão!

Tutorial JavaDB, Eclipse e DTP

Fábio Miranda em 06 Abr 2008

A partir do Java 6, a Sun passou a distribuir o Apache Derby junto com o Java, sob a alcunha de JavaDB. Trata-se de uma alternativa interessante para uso em ambientes de desenvolvimento e teste. Além disso, ele possui um excelente plugin que permite sua integração com o Eclipse.

Além de mostrar como usar o Derby aliado ao Eclipse, este artigo serve como introdução para uma série de artigos sobre JPA que pretendo postar nas próximas semanas.

1) Configuração do JavaDB

O Java6 instala o JavaDB no diretório c:\Program Files\Sun\JavaDB. Recomendo copiar o diretório JavaDB direto para a raiz (c:\JavaDB). É necessário setar a variável DERBY_HOME=c:\JavaDB no classpath do sistema operacional.

2) Instalação dos plugins do Derby no Eclipse

Após baixar os plugins Derby Core e Derby UI em http://db.apache.org/derby/derby_downloads.html, descompactá-los e copiar os conteúdos das pastas "plugin" para a pasta "eclipse/plugin".

Os plugins do Derby são baixados nos links indicados acima - atenção, pois estão meio "escondidos" no meio da documentação.

3) Usando o Derby Integrado ao Eclipse

3.1) Iniciar o Eclipse e Criar projeto "Locadora"

3.2) Clicar com o botão direito no nome do projeto. Se o plugin do Derby foi corretamente instalado, aparecerá a opção "Apache Derby | Add Apache Derby Nature".

Ao habilitar esta opção, as bibliotecas do Derby são importadas para o Build Path do projeto, e novas opções são habilitadas para que possamos usar este plugin:

3.3) Execute o comando sysinfo (último item listado pelo plugin) para verificar se a instalação do Derby está OK (passos 1.1 e 1.2).

3.4) Execute os comandos Start Network Server e Stop Network Server toda vez que precisar iniciar / parar o servidor derby.

3.5) Use o IJ para realizar comandos SQL direto no Console do Eclipse:

4) A Perspectiva Database Development (Eclipse Data Tools Platform)

Mesmo sendo uma mão na roda ter o IJ integrado no Eclipse, a DTP se mostra uma alternativa mais interessante para realização de consultas.

4.1) Window | Open Perspective | Other | Database Development

4.2) Criar Novo Perfil de Conexão

4.3) Escolher Generic JDBC Connection - Derby Embedded não servirá para o nosso caso!

4.4) Nomear o perfil

4.5) Como esta é a primeira vez que configuramos o DTP, a lista drop-down de drivers encontra-se vazia. É necessário configurar novo driver (também pode ser feito em Window | Preferences | Connectivity | Driver Definitions).

4.6) Localizar o driver apropriado (no nosso caso, Derby 10.2) e adicionar nova definição.

4.7) Selecionar Derby Client Driver

4.8) Informar a localização do derbyclient.jar (c:\JavaDB\lib).

4.9) Alterar as propriedades de conexão. Muita atenção para o parâmetro User ID, setá-lo para APP. Leia este artigo no OnJava para entender o porquê.

4.10) Selecione o driver que acabamos de configurar.

4.11) Teste a conexão.

4.12) Conectar-se.

4.13) Expandir LOCADORA | Schemas | APP | Tables | Person | Columns, para visualizar a tabela que criamos anteriormente.

4.14) Vá em File | New | SQL File, e crie um arquivo query.sql na raiz do projeto.

4.15) Selecione o banco de dados e escreva uma query. Note que este editor possui recurso de auto-completar, que pode ser útil durante a construção de queries.

4.16) Com o botão direito, selecione Execute ALL. Os resultados são exibidos logo abaixo, podendo ser visualizados de forma tabular (bem melhor que o texto plano gerado pelo IJ).

4.17) Outra funcionalidade importante que o DTP oferece é a possibilidade de exportar os dados para txt, html, xml e csv, facilitando o transporte de dados para outros programas - por exemplo para uma boa e velha planilha eletrônica, a qual a maioria dos usuários de sistemas de software gostam de ler seus relatórios...

5) Conclusões

Espero ter conseguido demonstrar com clareza o poder do Derby - um BD relativamente fácil de configurar, já que acompanha a distribuição do Java 6, não requerendo a instalação de ferramentas adicionais.

Mostrei também como usá-lo junto com o Eclipse usando seus plugins próprios; em seguida o configuramos com o DTP, possibilitando centralizar no Eclipse as atividades de administração de Banco de Dados, minimizando a necessidade de ferramentas adicionais.

Até a próxima.

Integração Spring x JPA

Por Fábio Miranda, em 19 Fev 2008

Os primeiros parágrafos contém o "resumo da ópera". Em seguida, um pouco de código exemplificando as opções de integração.

DAOs que usam JPA necessitam de EntityManagerFactories (EMFs) e/ou EntityManagers (EMs) para realizar as operações num bancos de dados.

O Spring Framework gerencia objetos, podendo resolver dependências entre eles. Caso o Spring gerencie a(s) EMFs e os DAOs, ele pode injetar os EMFs nos DAOs, de forma transparente ao código. Então, a primeira coisa a se aprender é como fazer o Spring gerenciar a(s) EMF(s).

Uma vez configurados os beans necessários no Spring, pode-se partir para o código. É possível usar JPA com Spring de forma desacoplada, através de anotações JPA (desde que configure o Spring para reconhecer tais anotações); ou de forma acoplada, usando APIs especializadas do Spring.

DUMMY STEP) Para integrar JPA com Spring, logicamente é necessário um projeto JPA (grosso modo: entidades devidamente anotadas, e um arquivo META-INF/persistence.xml). Exemplo de projeto:

  • src
    • br.com.airframes
      • Product.java
    • META-INF
      • persistence.xml

1) Configuração recomendada da EMF (LocalContainerEntityManagerFactoryBean)

Esta maneira é a mais flexível e poderosa. A linha "load-time-weaver" refere-se a questões de instrumentação de código requeridas por alguns provedores de persistência. Não será necessária quando o provedor é o Hibernate, por isso deixei comentada.

Note que está comentada a linha da propriedade dataSource. Por default, o Spring usa as configurações de acesso ao banco presentes em persistence.xml. Porém, vc pode deixar que o Spring também gerencie o seu datasource (ignorando persistence.xml), conforme item 6 deste tutorial.

2) Declarar um DAO como bean do Spring, no qual será injetada a EMF:

3) Integração de Baixo acoplamento usando anotações (Plain JPA)

3.1) Para o Spring reconhecer as anotações JPA, declarar:

ou

3.2) Codificação do Dao

Pronto! Esta é a maneira mais poderosa de integrar Spring e JPA, sem que haja qualquer dependência ao Spring explícita no código Java. A Spring Framework desempenha seu papel de forma transparente, injetando o EntityManagerFactory num mecanismo possível graças a anotações e ao PersistenceAnnotationBeanPostProcessor.

4) Outras maneiras de o Spring gerenciar o EMF.

Há duas maneiras alternativas àquelas apresentadas no passo 1 deste tutorial:

4.1) No caso da aplicação rodar em um App Server, é preferível deixar o Spring localizar o EMF na árvore JNDI:

É necessário também cuidado especial com a instrumentação de código, de modo que ela não entre em conflito com as bibliotecas do App Server. (consultar documentação do Spring).

4.2) LocalEntityManagerFactoryBean ao invés de LocalContainerEntityManagerFactoryBean

É a forma mais simples porém mais limitada de integrar JPA ao Hibernate. Ela não dá suporte, por exemplo, a transações globais. Seu uso é recomendado em aplicações simples que usam apenas JPA para acessar dados. Pode ser muito útil em aplicações standalone e ambientes de teste.

5) Integração Altamente Acoplada ao Spring

Neste caso, lida-se com JpaTemplates no lugar de EntityManagers, pois JPATemplate encapsula o EntityManager (JPATemplate gerencia internamente o EntityManager, não expondo-o ao programador).

Desta forma, como o código Java deixará de usar a API EntityManager, deve-se:

- Remover as declarações do item 3.1 deste tutorial (annotations post processors).

- Reescrever a configuração do DAO, possibilitando injeção do EMF via setter:

- Escrever método setter no DAO possibilitando o Spring injetar a dependência:

Dispostas as linhas gerais, seguem as opções para este tipo de integração:

5.1) Declarar JpaTemplate explicitamente em cada DAO da aplicação

5.2) Herdar JpaDaoSupport

JpaSupportDao já fornece o jpaTemplate, e setter para injeção do EntityManagerFactory, sem que necessidade de escrever código redundante nos DAOs

5.3) E quando precisar acessar a EntityManager API diretamente?

Escrever subclasses de JpaCallback e executá-los em JpaTemplates. Ao fornecer um JpaCallback, JpaTemplate executará o método doInJpa(EntityManager em) passando como parâmetro a sua referência interna da EntityManager.

Essa abordagem possibilita ao programador acesso indireto à EntityManager (através de um Callback). Para não inchar o sistema com estas subclasses, é possível usar herança implícita no código.

O código abaixo reescreve doSomething com Callbacks que permitem acessar o EntityManager.

6) Datasource gerenciado pelo Spring

6.1) Spring localiza datasource no JNDI

6.2) Spring lida diretamente com datasource

(Usa DBCP como Pool de Conexões - pode ser substituída por outra segundo preferência - por exemplo o C3P0).

Para configurar um datasource na JNDI, é necessário consultar a documentação do app server / container web.

Para o Tomcat: Tomcat-JNDI HowTo.

A biblioteca Simple-Jndi permite implementar uma árvore JNDI em aplicações stand-alone (pode ser útil em casos de testes).

Bibliografia http://static.springframework.org/spring/docs/2.5.x/reference/orm.html#orm-jpa http://static.springframework.org/spring/docs/2.5.x/reference/jdbc.html