Porque @EJB está nullo ?

Estou fazendo uma requisição para “/contador/{id}” pelo PostMan e quando o código chega em notificaoDAO.contador(id), recebo a mensagem de erro dizendo que notificacaoDAO é null.

PS: Estou usando Wildfly 11 com Eclipse Oxygen

Ele etá iniciando o JDNI, mas não consigo injetar, ele não inicializa o DAO.

10:31:23,633 INFO [org.jboss.as.ejb3.deployment] (MSC service thread
1-5) WFLYEJB0473: JNDI bindings for session bean named
’NotificacaoDAOEJB’ in deployment unit 'deployment “SouVizinho.war”'
are as follows:

java:global/SouVizinho/NotificacaoDAOEJB!br.com.br.ejb.NotificacaoDAOEJB
java:app/SouVizinho/NotificacaoDAOEJB!br.com.br.ejb.NotificacaoDAOEJB
java:module/NotificacaoDAOEJB!br.com.br.ejb.NotificacaoDAOEJB
java:global/SouVizinho/NotificacaoDAOEJB
java:app/SouVizinho/NotificacaoDAOEJB java:module/NotificacaoDAOEJB

10:31:23,634 INFO [org.jboss.as.ejb3.deployment] (MSC service thread
1-5) WFLYEJB0473: JNDI bindings for session bean named
’NotificacaoControladorEJB’ in deployment unit ‘deployment
"SouVizinho.war"’ are as follows:

java:global/SouVizinho/NotificacaoControladorEJB!br.com.souvizinho.controlador.NotificacaoControladorEJB
java:app/SouVizinho/NotificacaoControladorEJB!br.com.souvizinho.controlador.NotificacaoControladorEJB
java:module/NotificacaoControladorEJB!br.com.souvizinho.controlador.NotificacaoControladorEJB
java:global/SouVizinho/NotificacaoControladorEJB
java:app/SouVizinho/NotificacaoControladorEJB
java:module/NotificacaoControladorEJB

Controller

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.enterprise.context.RequestScoped;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("ejb/notificacao")
@Stateless
@LocalBean
public class NotificacaoControladorEJB {

	
	SmartJava smartjava = new SmartJava();
	@EJB
	NotificacaoDAOEJB notificacaoDAO;

	
	@GET
	@Produces("application/json; charset=UTF-8")
	@Path("/contador/{id}")
	public Notificacao contadorGet(@PathParam("id") int id) {
		long quantidade;
		try {
			quantidade = notificacaoDAO.contador(id);
			
			return new Notificacao(quantidade);
		} catch(Exception e) {
			quantidade = 0;
			System.err.println(smartjava.getFullStackTrace(e));
			
			return new Notificacao(quantidade);
		}
	}

DAO

import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;


@Stateless
@LocalBean
public class NotificacaoDAOEJB {

	//private EntityManagerFactory entityManagerFactory;
    @PersistenceContext
	private EntityManager entityManager;
	
	SmartJava sj = new SmartJava();
	

	
	public Notificacao Salvar(Notificacao notificacao) {
		
		try {
			this.entityManager.getTransaction().begin();
			this.entityManager.persist(notificacao);
			this.entityManager.getTransaction().commit();
		} catch (Exception e) {
			System.out.println(sj.getFullStackTrace(e));
			
		} finally {
			//this.entityManager.close();
		}
		
		return notificacao;
	}
	
	public void Alterar(Notificacao notificacao){
		 
		this.entityManager.getTransaction().begin();
		this.entityManager.merge(notificacao);
		this.entityManager.getTransaction().commit();
		//this.entityManager.close();
		
	}
	
	@SuppressWarnings("unchecked")
	public List<Notificacao> Listar(){
		return this.entityManager.createQuery("SELECT a FROM Notificacao a ORDER BY a.dtcad").getResultList();
	}
	
	public Notificacao GetNotificacao(int nrseq) {
		return this.entityManager.find(Notificacao.class, nrseq);
	}
	@SuppressWarnings("unchecked")
	public long contador(int nrsequsuario) {
		try {
			return (long) this.entityManager.createQuery("SELECT COUNT(a) FROM Notificacao a "
					+ "WHERE a.visualizado = false AND a.useralvo.nrseq = :usuario ORDER BY a.dtcad")
					.setParameter("usuario", nrsequsuario).getSingleResult();
		} catch(Exception e) {
			System.err.println(sj.getFullStackTrace(e));
			return 0;
		}
	} 
	
}

Tenta clicar com o botão direito do mouse no seu projeto, clica em properties >> project facets e clica na aba run times, e clica em cima do seu servidor de aplicação que sera exibido, acredito que seja algo relacionado ao ambiente pois quando anotamos uma classe com @Stateless ela acaba sendo gerenciada pelo EJB.

Alguma configuração a fazer ?

Precisei colocar o Lookup do JDNI, então adaptei o código deste tutorial para funcionar:

https://blogs.sap.com/2014/11/26/jax-rs-the-missing-link-between-ui5-and-hcp-java-apps-adding-ejb/

E depois usei este para corrigir a transação:

@Resource
private SessionContext sessionContext;

void execute(){

UserTransaction userTxn = sessionContext.getUserTransaction();

try{

 userTxn.begin();
 /**
  *  do-something
  */
 userTxn.commit();

  } catch(Throwable e){
   userTxn.rollback(); //-- Include this in try-catch 
  }
}

Legal, parabens por encontrar a solução, só uma coisa que reparei para transações use o @Transactional, assim você não precisa ficar abrindo e fechando as transações e deixa o ejb cuidar disso.

No caso, isso seria no lugar do utx.begin, e utx.commit, correto ?

exemplo com um dao Generico:
import java.sql.SQLException;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
*

  • @author rcorreia
    */
    @Stateless
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW )
    public class GenericoDao {

    @PersistenceContext(unitName = “”)
    private EntityManager em;

    public void salvar(T t) throws SQLException {
    getEm().persist(t);
    }

    public void atualizar(T t) throws SQLException {
    T oi = getEm().merge(t);
    }

    public List lista(String select) throws SQLException {
    Query query = getEm().createNamedQuery(select);
    return query.getResultList();
    }

    public List lista(String select, List parametros) throws SQLException {
    Query query = getEm().createNamedQuery(select);
    for (int i = 0; i < parametros.size(); i++) {
    query.setParameter(i + 1, parametros.get(i));
    }
    return query.getResultList();
    }

    public T buscar(String select, Object parametro) throws SQLException {
    Query query = getEm().createNamedQuery(select);
    query.setParameter(1, parametro);
    return (T) query.getSingleResult();
    }

    public T buscar(String select) throws SQLException {
    Query query = getEm().createNamedQuery(select);
    return (T) query.getSingleResult();
    }

    public T getPrimeiroResultado(String select) throws SQLException {
    Query query = getEm().createNamedQuery(select).setMaxResults(1);
    return (T) query.getSingleResult();
    }

    @SuppressWarnings(“unchecked”)
    public List findByNamedQuery(String namedQueryName) {
    List results = null;
    results = this.em.createNamedQuery(namedQueryName).getResultList();
    return results;
    }

    public EntityManager getEm() {
    return em;
    }
    }

Valeu, desconhecia esse método! Vou usar isto para novos métodos, preguiça de reescrever agora os que já estão prontos kkk

kkkkkkk, entendo, boa diversão.