实用程序类中的@EJB为null

时间:2015-10-20 03:50:32

标签: servlets nullpointerexception ejb

我的应用程序中有一个表单,我正在尝试验证用户名和/或电子邮件是否已存在于数据库中。

这是服务类:

@Stateless
public class CustomerFacade extends AbstractFacade<Customer> {

  @PersistenceContext(unitName = "OnlineStorePU")
  private EntityManager em;

  @Override
  protected EntityManager getEntityManager() {
    return em;
  }

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

}

这是实体类:

@Entity
@Table(name = "customer")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Customer.findAll", query = "SELECT c FROM Customer c"),
    @NamedQuery(name = "Customer.findById", query = "SELECT c FROM Customer c WHERE c.id = :id"),
    @NamedQuery(name = "Customer.findByName", query = "SELECT c FROM Customer c WHERE c.name = :name"),
    @NamedQuery(name = "Customer.findByMobile", query = "SELECT c FROM Customer c WHERE c.mobile = :mobile"),
    @NamedQuery(name = "Customer.findByEmail", query = "SELECT c FROM Customer c WHERE c.email = :email"),
    @NamedQuery(name = "Customer.findByAddress", query = "SELECT c FROM Customer c WHERE c.address = :address"),
    @NamedQuery(name = "Customer.findByFax", query = "SELECT c FROM Customer c WHERE c.fax = :fax"),
    @NamedQuery(name = "Customer.findByTelephone", query = "SELECT c FROM Customer c WHERE c.telephone = :telephone"),
    @NamedQuery(name = "Customer.findByUsername", query = "SELECT c FROM Customer c WHERE c.username = :username")})
public class Customer implements Serializable {

//ALL GETTERS AND SETTERS + CONSTRUCTOR

}

这是检查表格的类:

public class ErrorUtils {

  @EJB
  private CustomerFacade customerFacade;

  //**the arg String uName is the username input from the form**
  private boolean isUserNameInDBOK(String uName) {
    boolean OKBD = true;
    //            Checking UserName is not in the DB
    for (Customer customer : customerFacade.findAll()) {
        if (customer.getUsername().equals(uName)) {
            OKBD = false;
            break;
        }
    }
    return OKBD;
  }
}

我得到的错误是customerFacadenull

Warning:   StandardWrapperValve[ControllerServlet]: Servlet.service()     
for servlet ControllerServlet threw exception java.lang.NullPointerException

这是如何引起的?如何解决?

1 个答案:

答案 0 :(得分:1)

@EJB注入仅适用于容器管理工件。即由容器本身创建的类的实例,因此不是由new运算符创建的。

E.g。一个servlet:

@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {

    @EJB
    private YourService yourService;

}

容器单独执行new YourServlet()。容器负责执行依赖注入。容器负责调用init()。容器负责调用适当的doXxx()方法。等等。它是一个容器管理的工件。

但是,您尝试将其注入某个实用程序类:

public class ErrorUtils {

    @EJB
    private CustomerFacade customerFacade;

}

这看起来不像容器管理的工件。鉴于类中完全没有任何与容器管理相关的注释,例如@Stateless@ApplicationScoped@WebServlet等,您很可能只是自己手动创建它的实例如下所示:

ErrorUtils errorUtils = new ErrorUtils();

然后你期望@EJB神奇地注入。

错误。

您使用ErrorUtils关键字手动创建了new类的实例。你是手动管理它。所以你基本上还需要手动抓取并设置那个EJB。通常,您使用JNDI,另请参阅Inject EJB bean from JSF managed bean programmatically

errorUtils.customerFacade = (CustomerFacade) new InitialContext().lookup("java:/.../CustomerFacade");

但是,更好的是将该类转换为容器管理工件。例如。 CDI托管bean:

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class ErrorUtils {

然后将其注入您的servlet而不是手动制作它:

@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {

    @Inject
    private ErrorUtils errorUtils;

}

它会照顾@EJB之类的所有依赖关系。

对具体问题

无关,下面没有意义:

private boolean isUserNameInDBOK(String uName) {
    boolean OKBD = true;
    //            Checking UserName is not in the DB
    for (Customer customer : customerFacade.findAll()) {
        if (customer.getUsername().equals(uName)) {
            OKBD = false;
            break;
        }
    }
    return OKBD;
}

你基本上是在破坏关系数据库系统的目的,低估了结构化查询语言SQL的能力。您基本上将整个数据库表完全复制到Java的内存中,然后在符合给定条件的情况下手动浏览每个记录。

这显然效率低下。您应该以这样的方式与数据库交互,使其返回完全您需要的信息,仅此而已。您可以使用WHERE条款。您的IDE似乎足够聪明,可以为您自动生成这样的命名查询:Customer.findByName。利用它。

private boolean isUserNameInDBOK(String uName) {
    return customerFacade.findByName(name) != null;
}

这样DB将返回与给定条件匹配的1或0条记录。您只需检查它是否返回了记录。更高效的是添加一个命名查询,该查询会COUNT(*)返回longboolean而不是整个Customer。即使这样,整个ErrorUtils类在这个结构中也是多余的。只需直接调用服务方法。