Search code examples
jsptomcatintellij-ideaservletsejb

@EJB in Servlet returns NullPointerException (Intellij, Tomcat)


I am working on Java Web Application with JSP, Servlet, EJB, JDBC, Tomcat, and PostgreSQL, by using Intellij.

I am trying to inject my CustomerDAO.java into SignUp.java (Servlet), but it always returns NullPointerException, which is shown below. I hope someone can tell me what I have did wrong. Thank you in advance!

Message:

Cannot invoke "dao.CustomerDAO.createCustomer(model.Customer)" because "this.customerDAO" is null

Exception:

java.lang.NullPointerException: Cannot invoke "dao.CustomerDAO.createCustomer(model.Customer)" because "this.customerDAO" is null
    controller.SignUp.doPost(SignUp.java:24)
    jakarta.servlet.http.HttpServlet.service(HttpServlet.java:563)
    jakarta.servlet.http.HttpServlet.service(HttpServlet.java:631)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

Below are my files to work around.

JpaEntityManagerFactory.java

package util;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class JpaEntityManagerFactory {

    private static final String PERSISTENCE_UNIT_NAME = "postgres";
    private static EntityManagerFactory emFactory;

    public static EntityManager getEntityManager() {
        if (emFactory == null || !emFactory.isOpen()) {
            emFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        }
        return emFactory.createEntityManager();
    }

    public static void closeEntityManagerFactory() {
        if (emFactory != null && emFactory.isOpen()) {
            emFactory.close();
        }
    }

}

AbstractFacade.java

package dao;

import jakarta.persistence.EntityManager;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import util.JpaEntityManagerFactory;

import java.util.List;

public abstract class AbstractFacade<T> {

    private EntityManager em = JpaEntityManagerFactory.getEntityManager();
    private Class<T> entityClass;

    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    public void create(T entity) {
        em.getTransaction().begin();
        em.persist(entity);
        em.getTransaction().commit();
    }

CustomerDAO.java

@Stateless
public class CustomerDAO extends AbstractFacade<Customer> implements CustomerDAOI {

    public CustomerDAO() {
        super(Customer.class);
    }

    public boolean createCustomer(Customer customer){
        try{
            this.create(customer);
            return true;
        }
        catch (Exception e){
            return false;
        }
    }

SignUp.java

package controller;

import jakarta.ejb.EJB;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import dao.CustomerDAO;
import model.Customer;

import java.io.IOException;

@WebServlet(name = "SignUp", value = "/SignUp")
public class SignUp extends HttpServlet {

    @EJB
    private CustomerDAO customerDAO;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        Customer customer = new Customer("John");
        customerDAO.createCustomer(customer);   //returns NullPointerException

    }
}

Everything only works if I changed this

@EJB
private CustomerDAO customerDAO;

to

@EJB
private CustomerDAO customerDAO = new CustomerDAO();

but this is not I want, as I have to apply EJB in my application.

Below are steps that I have tried.

  1. Installed Jakarta EE EJB Plugin in Intellij. customerDAO in private CustomerDAO customerDAO once to be greyed out and appear Private field 'customerDAO' is never assigned, and this step recovers it.

  2. Used @ManagedBean and mappedName in SignUp.java

@WebServlet(name = "SignUp", value = "/SignUp")
@ManagedBean
public class SignUp extends HttpServlet {

    @EJB(mappedName = "CustomerDAO")
    private CustomerDAO customerDAO;

  1. Used @Local for CustomerDAOI.java.

  2. Added this into src/main/webapp/WEB-INF/web.xml

<ejb-local-ref>
        <ejb-ref-name>CustomerDAO</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <local>dao.CustomerDAO</local>
</ejb-local-ref>

Solution

  • Tomcat doesnt support EJB, it is just a web container. Use compliant Jakarta EE server like OpenLiberty