Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Dúvida sobre @Inject no EntityManager

Referente a aula 2. Depois que deixamos de instanciar o JPAUtil na classe DAO e passando pra uma variável EntityManager, conforme segue:

EntityManager em = new JPAUtil().getEntityManager();

passamos a injetar o EntityManager na classe DAO:

@Inject private EntityManager em;

além disso, dentro da classe JPAUtil passamos a anotação @Produces no getEntityManager conforme abaixo:

@Produces @RequestScoped public EntityManager getEntityManager() { return emf.createEntityManager(); }

Minha dúvida é o seguinte:

O JPAUtil era antigamente instanciado dentro do DAO, agora não é mais. Quando o DAO injeta o EntityManager, como que o CDI sabe que o EntityManager a ser injetado é o da classe JPAUtil? Nao consigo enxergar mais essa relação. Nao sei se ficou confuso meu questionamento.

2 respostas
solução!

Fala ai Leandro, tudo bem ?

Todo momento que cria um DAO ele percebe que precisa passar um valor para o EntityManager, o CDI olha a anotação e procura no seu projeto por alguém que tenha a anotação para produzir um EntityManager, dado que encontrou, ele retorna a instância.

Olá Leandro.

Veja no seu código, o seguinte:

@Inject
private EntityManager manager;

Para te ajudar pense no seguinte. O retorno do atributo declarado, por exemplo nesse caso, o EntityManager.

Quando declaro o EntityManager com @Inject eu estou pedindo pro CDI alguma instancia do EntityManager, algo que retorne um EntityManager.

Sendo assim, pense junto comigo e vamos analisar em qual local do código é possível retornar um Objeto qualquer.

Primeiro seria em um construtor de uma classe por exemplo na classe Pessoa, o construtor retorna uma instância:

public class Pessoa{
        // Isso retorna uma instancia
        public Pessoa(){
        }
}

E também com a anotação @Produces, por exemplo no EntityManager que retorna a instancia no método getManager.

public class JPAUtil{
    //O retorno é EntityManager, ele retorna uma 
    //instância de Entity Manager
    @Produces
    public EntityManager getManager(){
        return manager;
    }
}

Aí surge a pergunta, mas como o CDI sabe que o método getManager retorna o EntityManager que eu pedi em qualquer tela com o @Inject, se na classe do EntityManager deve existir algum construtor para retornar o próprio EntityManager?

A resposta é simples, existem algumas anotações que você pode definir de qual lugar que pode ser considerado uma instancia, por exemplo a anotação @Any, que quando eu informo em cima da classe, o CDI desconsidera que a classe retorne uma instancia a partir do construtor.

Faremos um teste, e você pode repetir aí no seu código.

Vamos supor que você tenha no seu sistema alguma janela (Por exemplo Vendas) que precise de uma configuração para decidir se você deve imprimir ou não uma página.

Assim você primeiramente criaria uma classe Configuração que gravaria essas configurações no Banco de Dados.

private class Configuracao{

    private boolean imprimePagina;

    public Configuracao(){
    }

    public void setImprimePagina(boolean imprimePagina){
        this.imprimePagina = imprimePagina;
    }

}

Na janela de Vendas ficaria assim:

private class Vendas{

    @Inject
    private Configuracao configuracao;

}

Dessa forma o CDI ira retornar uma instancia de construtor criando um "new Configuracao()".

Agora vamos pensar que tu queira que a configuracao venha de um banco de dados. Assim na classe Configuracao você adiciona o @Any e em outra classe por exemplo ConfiguracaoRepository você cria um método com @Produces que retorna a instancia de Configuracao vinda de um banco de dados. Como segue.

@Any
private class Configuracao{
    //restante do código
}

ConfiguracaoRepository com @Produces

private class ConfiguracaoRepository{

    //Dessa forma o CDI retorna essa instância ao invés da instancia do construtor padrão. 
    @Produces
    public Configuracao getConfiguracaoDoBanco(){
        return new ConfiguracaoDAO().getConfiguracao();
    }
}

Espero que tenha ajudado.