@EJB inside utility class 为空
@EJB inside utility class is null
我的应用程序中有一个表单,我正在尝试验证用户名 and/or 电子邮件是否已在数据库中。
这是服务 class:
@Stateless
public class CustomerFacade extends AbstractFacade<Customer> {
@PersistenceContext(unitName = "OnlineStorePU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public CustomerFacade() {
super(Customer.class);
}
}
这是实体 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
}
这是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
注入仅适用于容器管理的工件。 IE。 classes 的实例由容器本身创建,因此不是您通过 new
运算符创建的。
例如一个 servlet:
@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {
@EJB
private YourService yourService;
}
容器本身 new YourServlet()
。容器负责执行依赖注入。容器负责调用 init()
。容器负责调用适当的 doXxx()
方法。等等,这是一个容器管理的神器。
但是,您试图将其注入某些实用程序 class:
public class ErrorUtils {
@EJB
private CustomerFacade customerFacade;
}
这看起来不像是容器管理的工件。鉴于 class 上完全没有任何与容器管理相关的注释,例如 @Stateless
、@ApplicationScoped
、@WebServlet
等,您很可能只是手动创建了一个你自己的实例如下:
ErrorUtils errorUtils = new ErrorUtils();
然后你期望 @EJB
神奇地被注入。
错了。
您使用 new
关键字手动创建了 ErrorUtils
class 的实例。您正在手动管理它。所以您基本上还需要手动获取并设置该 EJB。通常,您为此使用 JNDI,另请参阅 。
errorUtils.customerFacade = (CustomerFacade) new InitialContext().lookup("java:/.../CustomerFacade");
但是,更好的方法是将 class 变成容器管理的工件。例如。一个 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。您基本上是将整个数据库 table 完全复制到 Java 的内存中,然后手动探索每条记录是否符合给定条件。
这显然效率低下。您应该以这样的方式与数据库进行交互,即return完全您需要的信息,仅此而已。您可以为此使用 WHERE
子句。看来您的 IDE 足够聪明,可以为您自动生成这样一个命名查询:Customer.findByName
。好好利用吧。
private boolean isUserNameInDBOK(String uName) {
return customerFacade.findByName(name) != null;
}
这样数据库将 return 1 或 0 条记录匹配给定条件。您只需要检查它是否 return 记录了。然而更有效的是添加一个命名查询,它执行 COUNT(*)
returning long
或 boolean
而不是整个 Customer
。即使那样,整个 ErrorUtils
class 在这个结构中也是多余的。直接调用服务方法即可。
我的应用程序中有一个表单,我正在尝试验证用户名 and/or 电子邮件是否已在数据库中。
这是服务 class:
@Stateless
public class CustomerFacade extends AbstractFacade<Customer> {
@PersistenceContext(unitName = "OnlineStorePU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public CustomerFacade() {
super(Customer.class);
}
}
这是实体 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
}
这是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
注入仅适用于容器管理的工件。 IE。 classes 的实例由容器本身创建,因此不是您通过 new
运算符创建的。
例如一个 servlet:
@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {
@EJB
private YourService yourService;
}
容器本身 new YourServlet()
。容器负责执行依赖注入。容器负责调用 init()
。容器负责调用适当的 doXxx()
方法。等等,这是一个容器管理的神器。
但是,您试图将其注入某些实用程序 class:
public class ErrorUtils {
@EJB
private CustomerFacade customerFacade;
}
这看起来不像是容器管理的工件。鉴于 class 上完全没有任何与容器管理相关的注释,例如 @Stateless
、@ApplicationScoped
、@WebServlet
等,您很可能只是手动创建了一个你自己的实例如下:
ErrorUtils errorUtils = new ErrorUtils();
然后你期望 @EJB
神奇地被注入。
错了。
您使用 new
关键字手动创建了 ErrorUtils
class 的实例。您正在手动管理它。所以您基本上还需要手动获取并设置该 EJB。通常,您为此使用 JNDI,另请参阅
errorUtils.customerFacade = (CustomerFacade) new InitialContext().lookup("java:/.../CustomerFacade");
但是,更好的方法是将 class 变成容器管理的工件。例如。一个 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。您基本上是将整个数据库 table 完全复制到 Java 的内存中,然后手动探索每条记录是否符合给定条件。
这显然效率低下。您应该以这样的方式与数据库进行交互,即return完全您需要的信息,仅此而已。您可以为此使用 WHERE
子句。看来您的 IDE 足够聪明,可以为您自动生成这样一个命名查询:Customer.findByName
。好好利用吧。
private boolean isUserNameInDBOK(String uName) {
return customerFacade.findByName(name) != null;
}
这样数据库将 return 1 或 0 条记录匹配给定条件。您只需要检查它是否 return 记录了。然而更有效的是添加一个命名查询,它执行 COUNT(*)
returning long
或 boolean
而不是整个 Customer
。即使那样,整个 ErrorUtils
class 在这个结构中也是多余的。直接调用服务方法即可。