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

Duvida Injeção do EntityManager

Estava recebendo "null" ao tentar injetar o EntityManager na classe UsuarioDAO.

Analisando o código disponibilizado, percebi que o entityManager nesta classe é chamado através do getEntityManager() do JPAUtil

Porém nas outras classe o @inject funciona..

A duvida é. a injeção não funciona por que o metodo @produces ainda não foi executado?

Tem alguma reclação com ciclo de vida do JSF?

Conseguiria otimizar isso fazendo algo no JSF para inicializar tudo o que for @produces ? No PhaseListener por exemplo ?

7 respostas

Fala aí Marco, tudo bem?

nesse trecho: "Analisando o código disponibilizado, percebi que o entityManager nesta classe é chamado através do getEntityManager() do JPAUtil"

Quando você se refere "nesta classe" está falando na classe UsuarioDao? Está dizendo ela não injeta o EntityManager e utiliza a classe JPAUtil para conseguir um EntityManager seria isso?

Manda o código para eu entender melhor sua dúvida e tentar te ajudar.

Respondendo as outras dúvidas,

A anotação @Produces indica ao CDI como produzir algum objeto, através do retorno do método anotado.

Ou seja se eu anotar um método que retorna String com @Produces em qualquer lugar que eu precisar injetar uma String o CDI vai utilizar esse método que eu anotei. (Se eu tiver mais de um método que retorna String anotado com @Produces preciso utilizar um outro recurso do CDI chamado Qualifier para distinguir quando injetar por um método ou por outro.)

Não tem relação com o ciclo de vida do JSF o CDI é inicializado como um Listener de Servlet ou seja ele é inicializado antes da Servlet do JSF.

Como respondido anteriormente não tem como optimizar isso pois não tem relação com a inicialização do JSF.

Espero ter ajudado!

Fala Fernando blz?

Realmente acho que não ficou muito claro, o trecho de código é o seguinte:



package br.com.caelum.livraria.dao;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;

import br.com.caelum.livraria.modelo.Usuario;

public class UsuarioDao {

    public boolean existe(Usuario usuario) {

        EntityManager em = new JPAUtil().getEntityManager();
        TypedQuery<Usuario> query = em.createQuery(
                  " select u from Usuario u "
                + " where u.email = :pEmail and u.senha = :pSenha", Usuario.class);

        query.setParameter("pEmail", usuario.getEmail());
        query.setParameter("pSenha", usuario.getSenha());
        try {
            Usuario resultado =  query.getSingleResult();
        } catch (NoResultException ex) {
            return false;
        }

        em.close();

        return true;
    }

}

Estava tentando injetar o entity, neste caso ao invés de "new JPAUtil().getEntityManager()" declaro o atributo com a annotation @inject então faria "em = this.entity"

assim:


package br.com.caelum.livraria.dao;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;

import br.com.caelum.livraria.modelo.Usuario;

public class UsuarioDao {
    @inject
    EntityManager entity;

    public boolean existe(Usuario usuario) {

        EntityManager em = this.entity;
        TypedQuery<Usuario> query = em.createQuery(
                  " select u from Usuario u "
                + " where u.email = :pEmail and u.senha = :pSenha", Usuario.class);

        query.setParameter("pEmail", usuario.getEmail());
        query.setParameter("pSenha", usuario.getSenha());
        try {
            Usuario resultado =  query.getSingleResult();
        } catch (NoResultException ex) {
            return false;
        }

        em.close();

        return true;
    }

}

Neste caso ele não injeta e fica null

Agradeço desde já pela ajuda Fernando.

Entendi, em mando o código do seu Bean onde você está usando a classe UsuarioDao.

package br.com.caelum.livraria.bean;

import java.io.Serializable;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import br.com.caelum.livraria.dao.UsuarioDao;
import br.com.caelum.livraria.modelo.Usuario;

@Named
@ViewScoped
public class LoginBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private Usuario usuario = new Usuario();

    public Usuario getUsuario() {
        return usuario;
    }

    public String efetuaLogin() {
        System.out.println("fazendo login do usuario "
                + this.usuario.getEmail());

        FacesContext context = FacesContext.getCurrentInstance();
        boolean existe = new UsuarioDao().existe(this.usuario);
        if (existe) {
            context.getExternalContext().getSessionMap()
                    .put("usuarioLogado", this.usuario);
            return "livro?faces-redirect=true";
        }

        context.getExternalContext().getFlash().setKeepMessages(true);
        context.addMessage(null, new FacesMessage("Usuário não encontrado"));

        return "login?faces-redirect=true";
    }

    public String deslogar() {
        FacesContext context = FacesContext.getCurrentInstance();
        context.getExternalContext().getSessionMap().remove("usuarioLogado");
        return "login?faces-redirect=true";
    }
}
solução!

Boa Marco,

Perceba que nessa linha:

 boolean existe = new UsuarioDao().existe(this.usuario);

Você está instanciando UsuarioDao então o CDI nem sabe da existência desse objeto e por conta disso não injeta nenhuma dependência(no seu caso o EntityManager).

Ao invés de você instanciar vamos pedir para o CDI cuidar desse objeto pra nós.

A linha que mencionei acima por essa:

 boolean existe = usuarioDao.existe(this.usuario);

E declare um atributo UsuarioDao e vamos anotar ele com @Inject

@Named
@ViewScoped
public class LoginBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private Usuario usuario = new Usuario();

   @Inject
   private UsuarioDao usuarioDao;

   // Restante da sua classe ...

Dessa forma como é o CDI que irá instanciar seu objeto, ele cuida das dependências também.

Espero ter ajudado!

Fernando,

Então para injetar uma dependência a classe precisa estar no "contexto" do CDI ?

Quando eu injeto dentro de um Bean as injeções funcionam por que no caso o bean esta sendo gerenciado pelo CDI ?

Ou seja, a injeções devem sempre começar a partir de uma classe gerenciada pelo CDI, é isso?

Nesse caso sim.

Mas o mais importante é que você não pode efetuar nenhum new em classes que você quer injetar.

Do contrário as dependências dessas classes que você instanciou manualmente não serão resolvidas e você vai tomar NullPointerException.