Servlets @实用程序类中的EJB为空

Servlets @实用程序类中的EJB为空,servlets,nullpointerexception,ejb,Servlets,Nullpointerexception,Ejb,我在我的应用程序中有一个表单,我正在尝试验证用户名和/或电子邮件是否不在数据库中 这是服务级别: @Stateless public class CustomerFacade extends AbstractFacade<Customer> { @PersistenceContext(unitName = "OnlineStorePU") private EntityManager em; @Override protected EntityManager get

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

这是服务级别:

@Stateless
public class CustomerFacade extends AbstractFacade<Customer> {

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

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

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

}
这是检查表单的类:

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;
  }
}
我得到的错误是
customerFacade
null

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

这是如何造成的,我如何解决它?

通过
@EJB
注入只在容器管理的工件中工作。即,类的实例由容器本身创建,因此不是由您通过
new
操作符创建的

例如,servlet:

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

    @EJB
    private YourService yourService;

}
容器本身不会创建新的YourServlet()。容器负责执行依赖项注入。容器负责调用
init()
。容器负责调用适当的
doXxx()
方法。等等,它是一个容器管理的工件

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

@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;

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

ErrorUtils errorUtils = new ErrorUtils();
然后你期望
@EJB
神奇地被注入

您使用
new
关键字手动创建了
ErrorUtils
类的实例。您正在手动管理它。因此,您基本上还需要手动获取并设置EJB。通常,您使用JNDI来实现这一点,请参见

但是,更好的方法是将该类转换为容器管理的工件。例如,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条与给定条件匹配的记录。您只需检查它是否返回了记录。但更有效的方法是添加一个命名查询,该查询执行
计数(*)
返回
布尔值
,而不是整个
客户
。即使如此,整个
ErrorUtils
类在这个构造中也是非常多余的。直接调用服务方法。

这并不是对您的问题的真正回答,但您的算法效率很低。直接查询用户名和id不是比遍历所有可能用户的整个列表更好吗?这是100%正确的@PaulProgrammer,但我的问题比效率更重要的是,在我能够处理大(O)之后,让它工作起来。)但我也注意到,我不能为findAll()调用任何@namedquerys exept,太棒了,你说得对。我做了更改,它成功了。关于customerFacade.findByUserName(name),Netbeans IDE不允许我调用finsAll()调用的任何其他@namedquery。请帮忙,不客气。至于新问题,只需按右上角的[Ask question]按钮。链接到新问题
private boolean isUserNameInDBOK(String uName) {
    return customerFacade.findByName(name) != null;
}