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