JSF com EJB 3 - ManagedBean --> Facade --> DAO - Problema na injeção de persistência

Prezados colegas, preciso de ajuda para integrar em uma aplicação web com JSF e EJB 3 os componentesseguintes:

ManagedBean --> Facade --> DAO.

Consegui injetar o DAO diretamente no ManagedBean, o problema é que quando coloquei o Facade na história não consigo fazer funcionar.

Do ManagedBean preciso chamar um método do Facade e do Facade, um método da DAO. Tentei injetar a DAO na Facade e a Facade no ManagedBean, mas o objeto injetado aparece como nulo.

Criei um DAOFactory e injetei no Facade. É possivel injetar o Facade no managedBean?

Estou começando agora a utilizar EJB com JSF e preciso de ajuda. Agradeço se puderem ajudar.

Vou postar a seguir meus componentes ManagedBean, DAOFactory, facade e DAO.

Obrigado

[b]DAOFactoryImpl[/b]

@Stateless
public class DAOFactoryImpl implements DAOFactory {
    @PersistenceContext(unitName = "Exemplo001PU")
    private EntityManager entityManager;

    @Override
    public DepartamentoDaoImpl getDepartamentoDao() {
         DepartamentoDaoImpl dao = new DepartamentoDaoImpl();
         dao.setEntityManager(entityManager);
         return dao;
    }
}


[b]DepartamentoDaoImpl [/b]

//@Stateless
public class DepartamentoDaoImpl implements DepartamentoDao {
   //@PersistenceContext(unitName = "Exemplo001PU")
    private EntityManager entityManager;
    //private EntityManager entityManager;

    public DepartamentoDaoImpl() {
    }

    @Override
    public void create(Departamento a) {
        entityManager.persist(a);
    }

    @Override
    public void edit(Departamento entity) {
        entityManager.merge(entity);
    }

    @Override
    public void remove(Departamento entity) {
        entityManager.remove(entityManager.merge(entity));
    }

    @Override
    public Departamento find(Object id) {
        return entityManager.find(Departamento.class, id);
    }

    @Override
    public List<Departamento> buscaTodos() {
        CriteriaQuery cq = entityManager.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Departamento.class));
        return entityManager.createQuery(cq).getResultList();
    }

    @Override
    public List<Departamento> buscarFaixa(int[] faixa) {
        CriteriaQuery cq = entityManager.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Departamento.class));
        Query q = entityManager.createQuery(cq);
        q.setMaxResults(faixa[1] - faixa[0]);
        q.setFirstResult(faixa[0]);
        return q.getResultList();
    }

    @Override
    public int contar() {
        CriteriaQuery cq = entityManager.getCriteriaBuilder().createQuery();
        Root<Departamento> rt = cq.from(Departamento.class);
        cq.select(entityManager.getCriteriaBuilder().count(rt));
        Query q = entityManager.createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager=entityManager;
    }
}

[b]DepartamentoFacadeImpl[/b]
@Stateless
public class DepartamentoFacadeImpl implements DepartamentoFacade {

    @EJB
    private DAOFactory daoFactory;

    private DepartamentoDao departamentoDao;

     public DepartamentoFacadeImpl() {
        departamentoDao = daoFactory.getDepartamentoDao();
    }

    @Override
    public void create(Departamento a) {
        departamentoDao.create(a);
    }
   
    @Override
    public void remove(Departamento entity) {
        departamentoDao.remove(entity);
    }

    @Override
    public Departamento find(Object id) {
        return departamentoDao.find(id);
    }

    @Override
    public List<Departamento> buscaTodos() {
        return departamentoDao.buscaTodos();
    }

    @Override
    public List<Departamento> buscarFaixa(int[] faixa) {
        return departamentoDao.buscarFaixa(faixa);
    }

    @Override
    public int contar() {
        return departamentoDao.contar();
    }

    @Override
    public void edit(Departamento entity) {
        departamentoDao.edit(entity);
    }
}


[b]DepartamentoMBean[/b]

@ManagedBean(name = "departamentoMBean")
@SessionScoped
public class DepartamentoMBean {

    private Departamento corrente;
    private DataModel itens = null;
    //@EJB
    //private dao.DepartamentoDao ejbFacade;

    @EJB
    private dao.factory.DAOFactoryImpl daoFactory;

    private DepartamentoDaoImpl ejbFacade = daoFactory.getDepartamentoDao();

    //private DepartamentoFacadeImpl ejbFacade=new DepartamentoFacadeImpl();
    private PaginationHelper pagination;
    private int indiceItemSelecionado;

    public DepartamentoMBean() {
    }

    public DepartamentoDaoImpl getEjbFacade() {
        return ejbFacade;
    }
 
    public Departamento getSelecionado() {
        if (corrente == null) {
            corrente = new Departamento();
            indiceItemSelecionado = -1;
        }
        return corrente;
    }

    // deixar
    public String salvar() {
        try {
            ejbFacade.create(corrente);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("departamentoCriado"));
            corrente = new Departamento();
            indiceItemSelecionado = -1;
            return "Criar";
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("erroPersistenciaOcorrido"));
            return null;
        }
    }

    public String atualizar() {
        try {
            ejbFacade.edit(corrente);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("departamentoAtualizado"));
            return "Ver";
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("erroPersistenciaOcorrido"));
            return null;
        }
    }

    public PaginationHelper getPaginacao() {
        if (pagination == null) {
            pagination = new PaginationHelper(10) {

                @Override
                public int getContarItens() {
                    return ejbFacade.contar();
                }

                @Override
                public DataModel criarPageDataModel() {
                    int vetor[] = new int[]{getPrimeiroItemPagina(), getPrimeiroItemPagina() + getTamanhoPagina()};
                    List lista = ejbFacade.buscarFaixa(vetor);
                    ListDataModel lstDataModel = new ListDataModel(lista);
                    return lstDataModel;
                }
            };
        }
        return pagination;
    }

    public DataModel getItens() {
        if (itens == null) {
            itens = getPaginacao().criarPageDataModel();
        }
        return itens;
    }

    public String proximo() {
        getPaginacao().proximaPagina();
        itens = null;
        return "Listar";
    }

    public String anterior() {
        getPaginacao().paginaAnterior();
        itens = null;
        return "Listar";
    }

    public String ver() {
        corrente = (Departamento) getItens().getRowData();
        indiceItemSelecionado = pagination.getPrimeiroItemPagina() + getItens().getRowIndex();
        return "Ver";
    }

    public String editar() {
        corrente = (Departamento) getItens().getRowData();
        indiceItemSelecionado = pagination.getPrimeiroItemPagina() + getItens().getRowIndex();
        return "Editar";
    }

    public String remover() {
        corrente = (Departamento) getItens().getRowData();
        indiceItemSelecionado = pagination.getPrimeiroItemPagina() + getItens().getRowIndex();
        acaoExcluir();
        itens = null;
        return "Listar";
    }

    public String criar() {
        corrente = new Departamento();
        indiceItemSelecionado = -1;
        return "Criar";
    }

    public String listar() {
        itens = null;
        return "Listar";
    }

    public String excluirVer() {
        acaoExcluir();
        itens = null;
        return "Listar";

    }

    private void acaoExcluir() {
        try {
            ejbFacade.remove(corrente);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("departamentoDeletedado"));
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("erroPersistenciaOcorrido"));
        }
    }

    public List getItensDisponiveis() {
        return ejbFacade.buscaTodos();
    }
}

Bem, encontrei uma solução, mas não foi das melhores…

Por favor, ajudem a encontrar uma solução menos custosa.

Fiz um lookup no managedBean para acessar o FACADE. No Facade eu injetei o DAO e funcionou.

Não entendi, porém, porque tive que fazer um lookup no ManagedBean.

Porque injetando o FACADE no ManagedBean não funcionou?

Eis o lookup no managedBean.

public DepartamentoFacade getEjbFacade() {
try {
InitialContext ic = new InitialContext();
DepartamentoFacade ejbFacade = (DepartamentoFacade) ic.lookup(“facade.DepartamentoFacade”);
return ejbFacade;
} catch (NamingException ex) {
return null;
}
}

Alguém pode me dizer se há uma solução melhor?

O que eu queria era injetar uma DAOFactory na Facade e a Facade no ManagedBean, porém, a DAAOFactory não funcionou, pois o EntityManager dava null.

Enquanto isso vou me virando com essa solução…

Obrigado.

Kra, veja bem…

A injeção de dependências (esses atributos marcados com @PersistenceContext, @EJB, etc…) só funcionam se o objeto em q vc está utilizando a injeção atender a duas condições:

[list]1 - O objeto precisa ser candidado a Injeção. Nem todos os objetos no seu sistema são candidatos a injeção, geralmente os candidatos são EJBs, ManagedBeans do JSF, Servlets, ServletFilters e ServletListeners. Objetos comuns como o seu DepartamentoDaoImpl ñ são candidatos a injeção (a menos q se use CDI, nesse caso todo quase objeto é candidato à injeção);[/list]
[list]2 - O objeto precisa ser instanciado pelo container (servidor). A injeção de dependências ñ é um recurso natural da JVM por isso objetos criados com o operados new ñ tem esse “privilégio”.[/list]

Esse seu problema pode ser resolve com muito menos código. Faça o seu DepartamentoDAOImpl um EJB e injete ele no ManagedBean com a anotação @EJB e pronto. Assim vc dispênça a necessidade de uma fábrica e ainda tira proveito da injeção de dependências no seu DAO. Vc pode, ainda, dispensar o DAO e injetar o EntityManager nos EJBs q possuem a lógica dos casos de uso e p/ evitar q a lógica de acesso aos dados se misture com a lógica do sistema vc pode usar @NamedQueries. O EntityManager é um DAO genérico, ñ há necessidade de vc escrever algo q o framework já te dá pronto. Assim o seu código vai ficar mais simples e mais fácil de manter, se perder flexibilidade, e com CDI vc pode expandir ainda mais essa flexibilidade.

PS.: por favor quanto vc for postar código use tags [code] p/ facilitar a visualização.

Rafael, primeiramente, obrigado pela resposta, foi muito útil, entretanto, surgiram novas dúvidas.

Eu havia feito como você disse, criei o DepartamentoDAOImpl como um EJB e injetei no ManagedBean e funcionou direitinho.

A questão é que tem alguns desenvolvedores que não dispensam um componente FACADE entre o DAO e o ManagedBean.

Quando e porque esse FACADE é necessário, já que ele me parece, na maioria dos exemplos que vi, apenas uma ponte entre esses componentes?

Outra coisa, eu tornei o DAO um EJB e injetei no FACADE. Tornei o FACADE um EJB e tentei injetar no ManagedBean e não funcionou, pois o objeto injetado aparecia como null. Ai eu fiz um lookup no ManagedBean para utilizar o FACADE. Dessa forma funcionou direitinho. Minha dúvida é, porque eu não consegui injetar o FACADE no EJB com a anotação @EJB? Porque eu tive que fazer o lookup?

Se eu fizer como você disse, deixar o DepartamentoDAOImpl como um EJB e injetar no ManagedBean, isso é uma boa prática?

Agradeço pela atenção.

Desculpe por ter postado código de maneira indevida. Na próxima vez utilizarei a tag [code].

Obrigado.

O padrão Service Facade é remanescente do velho J2EE. Originalmente o padrão foi concebido p/ o desenvolvimento aplicações com cliente remoto, como uma aplicação com cliente Swing e EJBs implementando a lógica. Ele é importante nesses casos pq cada chamada de um cliente remoto à um EJB envolve:

[list]serialização dos parâmetros;[/list]
[list]envio pela rede;[/list]
[list]deserialização dos parâmetros no servidor;[/list]
[list]processamento da lógica;[/list]
[list]serialização do retorno;[/list]
[list] transferência do retorno pela rede;[/list]
[list]deserialização do retorno[/list]

Como vc pode notar isso td incorre em um custo alto p/ a performance dessas chamadas, sendo assim, ñ é conveniente o uso de EJBs q possuam uma interface de granularidade fina (com muitos métodos onde cada método faz apenas uma pequena e bem específica taréfa). Os Service Facades oferecem uma interface de granularidade grossa (poucos métodos q fazem muita coisa) pq assim vc reduz o número de chamadas remotas e melhora a performance da aplicação. Por ser esse um modelo muito simples de se seguir, os Service Faces se popularizaram com um padrão p/ todo tipo de aplicação JEE. Isso causa algumas sérias inconveniências pois Service Facades ñ são mais q “bibliotecas de funções” e incentivam a programação estruturada. APIs de granularidade grossa são mais simples de se usar mas são mais difíceis de customizar e reaproveitar. Com a chegada do JEE5, mas principalmente do JEE6 com CDI, muitas ferramentas ajudam vc a evitar esse tipo de padrão quando ele ñ é necessário. Particularmente, quando estou usando JEE6 com CDI em projetos puramente WEB eu prefiro usar meus EJBs (Controllers) como ManagedBeans ao invés de usar dois objetos p/ essa taréfa, lembre-se q o padrão MVC descreve uma arquitetura em 3 camadas e ñ em 4 como é muito comum em aplicativos JEE5 (ou 5 se vc usar DAOs). De fato, os até mesmo os populares DAOs são hoje um pouco redundantes posto q o EntityManager do JPA oferece tds as funcionalidades de um DAOs genérico já pronto p/ vc, escrever DAOs é como reinventar a roda. É claro q p/ q isso funcione na prática vc precisa lançar mão das @NamedQueries através das quais vc pode separar a lógica de acesso ao banco do resto da lógica da aplicação.

Quanto ao problema no seu Facade. Caso ainda esteja interessado em resolve-lo, poste o código p/ q eu possa dar uma olhada.

Rafael, obrigado novamente.

Entendi! Entretanto, tenho mais algumas dúvidas.

Se o EntityManager é um DAO genérico, então não preciso necessariamente de criar componentes DAO.
Sendo assim, a classe que contém métodos como os apresentados a seguir podem ser o meu FACADE (abstrato). Como posso classificar essas classes?

public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }

    public List<T> buscaTodos() {
        CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        return getEntityManager().createQuery(cq).getResultList();
    }

    public List<T> buscarFaixa(int[] faixa) {
        CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        Query q = getEntityManager().createQuery(cq);
        q.setMaxResults(faixa[1] - faixa[0]);
        q.setFirstResult(faixa[0]);
        return q.getResultList();
    }

Mais uma dúvida, os ManagedBeans são CONTROLLERS, as classes com os métodos apresentados acima são representadas como MODEL, certo?

O os componentes como os Converters do JSF são representados na CONTROLLER do MVC?

Muito obrigado pelas respostas.

EJBs são controllers e os models são as suas entidades do JPA. Componentes como Converters ou Validadors do JSF são possuem nenhum papel específico no padrão MVN, embora a taréfa de um Converter é tipicamente realizada por um controller e do Validador por models. Os JEE6 introduzio o framework BeansValidador q permite q as taréfas de validação de dados fiquem realmente nas classes de model (entidades do JPA) e eventualmente nas classes controller (algums casos de uso possuem regras de validação específicas como o campo de confirmação de senha em um cadastro de usuário, a confirmação ñ faz parte do modelo).

Quando uso CDI, minhas views do JSF acessam dirétamente actions em um EJB (no CDI um objeto pode ser, ao mesmo tempo, ManagedBean e EJB) q por sua vez executam a lógica nas entidades JPA. Particularmente a estrutura a seguir me parece um pouco redundante:

// ManagedBean (o código omite getters e setters)
@ManagedBean
public class PersonBean {
  @EJB PersonFacade personFacade;

  private Person person;

  public String save() {
    personFacade.save(person);
    return "/person/list";
  }
}

// ServiceFacade
@Stateless
public class PersonFacade {
  @EJB PersonDAO personDAO;

  public void save(Person person) {
    personDAO.save(person);
  }
}

// DAO
@Stateless
public class PersonDAO {
  @PersistenceContext EntityManager em;

  public void save(Person person) {
    em.persist(person);
  }
}

Vc tem 3 métodos em 3 classes diferêntes q dizem exatamente a mesma coisa, algumas pessoas podem chamar isso de abstração mas, pra mim, isso é redundância. Bastaria isso:

// (o código omite getters e setters)
@Stateful
@Named
public class PersonCRUD {
  @Inject EntityManager em;

  private Person person;

  public String save() {
    em.persist(person);
    return "/person/list";
  }
}

Desse modo vc escreve menos, entrega resultados mais rápido (garanto q vc vai ganhar pontos com o seu chefe/cliente), tem um código mais simples (+ simples = - bugs & melhor mantenibilidade) e vai ter mais tempo p/ coisas realmente divertidas como namorar ou escutar Iron Maiden :)!

Rafael, muito obrigado.

Você esclareceu todas as minhas dúvidas.

Valeu mesmo.

[]s

Caro Rafael, boa noite.

Estou tentando tornar meu managed bean um EJB. Para isso injetei o EntityManager no managed bean. As opções para consulta e listagem funcionaram, entretanto, nas demais operações como em.persist(corrente) ou em.merge(corrente) retorna uma exceção do tipo TransactionRequiredException.

Você pode dar uma olhada no código. Não consegui achar o erro. Postei o código abaixo.

Obrigado.

package mBean;

import bean.Departamento;
import util.JsfUtil;
import util.PaginationHelper;
import java.util.List;
import java.util.ResourceBundle;
import javax.ejb.Stateless;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

@Stateless
@Named
@ManagedBean(name = "departamentoMBean")
@SessionScoped
public class DepartamentoMBean {
    @PersistenceContext(unitName = "Exemplo001PU")
    @Inject
    EntityManager em;
    private Departamento corrente;
    private DataModel itens = null;
    private DataModel itensSelecionados = null;
    private PaginationHelper pagination;
    private int indiceItemSelecionado;

    public DepartamentoMBean() {
    }

    public EntityManager getEntityManager() {
        return em;
    }
 
    public Departamento getSelecionado() {
        if (corrente == null) {
            corrente = new Departamento();
            indiceItemSelecionado = -1;
        }
        return corrente;
    }

    public String salvar() {
        try {
            em.persist(corrente);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("departamentoCriado"));
            corrente = new Departamento();
            indiceItemSelecionado = -1;
            return "Criar";
        } catch (Exception e) {
            System.out.println(e.getMessage());
            String m = e.getMessage();
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("erroPersistenciaOcorrido"));
            return null;
        }
    }

    public String atualizar() {
        try {
            em.merge(corrente);
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("departamentoAtualizado"));
            return "Ver";
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("erroPersistenciaOcorrido"));
            return null;
        }
    }

    public PaginationHelper getPaginacao() {
        if (pagination == null) {
            pagination = new PaginationHelper(10) {
                @Override
                public int getContarItens() {
                    CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
                    Root rt = cq.from(Departamento.class);
                    cq.select(em.getCriteriaBuilder().count(rt));
                    Query q = em.createQuery(cq);
                    return ((Long) q.getSingleResult()).intValue();
                }

                @Override
                public DataModel criarPageDataModel() {
                    int vetor[] = new int[]{getPrimeiroItemPagina(), getPrimeiroItemPagina() + getTamanhoPagina()};
                    CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
                    cq.select(cq.from(Departamento.class));
                    Query q = em.createQuery(cq);
                    q.setMaxResults(vetor[1] - vetor[0]);
                    q.setFirstResult(vetor[0]);
                    List lista = q.getResultList();

                    ListDataModel lstDataModel = new ListDataModel(lista);
                    return lstDataModel;
                }
            };
        }
        return pagination;
    }

    public DataModel getItens() {
        if (itens == null) {
            itens = getPaginacao().criarPageDataModel();
        }
        return itens;
    }

    public String proximo() {
        getPaginacao().proximaPagina();
        itens = null;
        return "Listar";
    }

    public String anterior() {
        getPaginacao().paginaAnterior();
        itens = null;
        return "Listar";
    }

    public String ver() {
        corrente = (Departamento) getItens().getRowData();
        indiceItemSelecionado = pagination.getPrimeiroItemPagina() + getItens().getRowIndex();
        return "Ver";
    }

    public String entrarConsulta() {
        corrente = new Departamento();
        indiceItemSelecionado = -1;
        return "Consultar";
    }

    public String consultar() {
        itensSelecionados = null;
        return "ListarSelecionados";
    }

    public DataModel getItensSelecionados() {
        if (itensSelecionados == null) {
            Query query = em.createNamedQuery("Departamento.findByParteNomDep");
            query.setParameter("nomDep", "%" + corrente.getNomDep() + "%");
            List lista = query.getResultList();
            itensSelecionados = new ListDataModel(lista);
        }
        return itensSelecionados;
    }

    public String editar() {
        corrente = (Departamento) getItens().getRowData();
        indiceItemSelecionado = pagination.getPrimeiroItemPagina() + getItens().getRowIndex();
        return "Editar";
    }

    public String remover() {
        corrente = (Departamento) getItens().getRowData();
        indiceItemSelecionado = pagination.getPrimeiroItemPagina() + getItens().getRowIndex();
        acaoExcluir();
        itens = null;
        return "Listar";
    }

    public String criar() {
        corrente = new Departamento();
        indiceItemSelecionado = -1;
        return "Criar";
    }

    public String listar() {
        itens = null;
        return "Listar";
    }

    public String excluirVer() {
        acaoExcluir();
        itens = null;
        return "Listar";

    }

    private void acaoExcluir() {
        try {
            em.remove(em.merge(corrente));
            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("departamentoDeletedado"));
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/propriedades.recursos.propriedades").getString("erroPersistenciaOcorrido"));
        }
    }

    public List getItensDisponiveis() {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Departamento.class));
        return em.createQuery(cq).getResultList();
    }
}

Retomando o tópico…

Tentei fazer algo como o q Dev.Rafael falou, mas n tá rolando…

Tô tentando chamar um método do meu Bean (EJB) direto da minha pagina JSF, mas
n tá indo (só os métodos).

[code] @Named
@Stateless
public class PessoaFacadeBean {

public PessoaFacadeBean(){
	setName("Maria 1");
}

private String name;

//Getters and Setters..

public void imprimir() {
	System.out.println("Teste");
	
}	

}[/code]

Num ManagedBean tinha o parâmetro “ActionEvent” que n é suportado pelo CDI, então, n to vendo como chamar este método.

Queria algo assim, e outra coisa, qdo anoto meu EJB com algum Scopo (Request por ex), dá pau, e diz q só aceita @Dependent.

Alguém já usou o CDI com EJB 3.1 e FSF, no Eclipse?
Dos exemplos q vi, não funcionaram.

Falew.