实用程序类中的@EJB为空 [英] @EJB inside utility class is null
问题描述
这是服务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);
}
}
这是实体类: / p>
@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 =:phone),
@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;
// ** arg String uName是从表单**
private boolean isUserNameInDBOK(String uName){
boolean OKBD = true;
//检查UserName不在($客户:customerFacade.findAll())的DB
{
if(customer.getUsername()。equals(uName)){
OKBD = false;
break;
}
}
return OKBD;
}
}
我得到的错误是 customerFacade
是 null
:
警告:StandardWrapperValve [ControllerServlet]:Servlet.service()
为Servlet ControllerServlet抛出异常java.lang.NullPointerException
这是怎么引起的,我该如何解决?
通过 @EJB
仅在容器管理的工件中工作。即通过新
运算符由容器本身创建的类,而不是由您创建的类的实例。
例如。一个servlet:
@WebServlet(/ your-servlet)
public class YourServlet扩展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
class使用
新的
关键字。您正在手动管理它。所以你基本上也需要手动抓取和设置EJB。通常,您使用JNDI,另见从JSF管理的入口EJB bean bean以编程方式。
errorUtils.customerFacade =(CustomerFacade)new InitialContext()。 ../CustomerFacade);
但是,更好的是将该类转换为容器管理工件。例如。一个CDI管理的bean:
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class ErrorUtils {
然后注入它在你的servlet而不是手动制作它:
@WebServlet(/ your-servlet)
public class YourServlet扩展了HttpServlet {
@Inject
private ErrorUtils errorUtils;
}
它会保留所有依赖项,如code> @EJB 也正确注入。
无关<对于具体的问题,下面没有意义:
private boolean isUserNameInDBOK(String uName){
boolean OKBD = true;
//检查UserName不在($客户:customerFacade.findAll())的DB
{
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)!=空值;
}
这样DB将返回与给定条件匹配的1或0条记录。你只需要检查它是否返回记录。更有效的是添加一个命名查询,它执行 COUNT(*)
返回一个 long
或者可能 boolean
而不是整个客户
。即使这样,整个 ErrorUtils
类在这个构造中是相当多余的。直接调用服务方式。
I have a form in my application for which I'm trying to validate that the userName and/or email is not already on the DB.
This is service 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);
}
}
This is the entity 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
}
This is the class checking the form:
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;
}
}
The error I'm getting is that the customerFacade
is null
:
Warning: StandardWrapperValve[ControllerServlet]: Servlet.service()
for servlet ControllerServlet threw exception java.lang.NullPointerException
How is this caused and how can I solve it?
Injection via @EJB
works only in container managed artifacts. I.e. instances of classes which are created by the container itself and thus not by you via the new
operator.
E.g. a servlet:
@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {
@EJB
private YourService yourService;
}
The container does new YourServlet()
all by itself. The container takes care of performing dependency injection. The container takes care of calling init()
. The container takes care of calling appropriate doXxx()
method. Etc. It's a container managed artifact.
However, you attempted to inject it in some utility class:
public class ErrorUtils {
@EJB
private CustomerFacade customerFacade;
}
This does not look like a container managed artifact. Given the complete absence of any container management related annotations on the class such as @Stateless
, @ApplicationScoped
, @WebServlet
, etc, it's very much likely that you was just manually creating an instance of it yourself like below:
ErrorUtils errorUtils = new ErrorUtils();
And then you expected that @EJB
magically gets injected.
Wrong.
You manually created an instance of ErrorUtils
class using new
keyword. You're manually managing it. So you basically also need to manually grab and set that EJB. Usually, you use JNDI for that, see also Inject EJB bean from JSF managed bean programmatically.
errorUtils.customerFacade = (CustomerFacade) new InitialContext().lookup("java:/.../CustomerFacade");
But, much better is to just turn that class into an container managed artifact. E.g. a CDI managed bean:
import javax.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class ErrorUtils {
And then inject it in your servlet instead of manually crafting it:
@WebServlet("/your-servlet")
public class YourServlet extends HttpServlet {
@Inject
private ErrorUtils errorUtils;
}
It will take care that all of its dependencies like @EJB
are also properly injected.
Unrelated to the concrete problem, the below doesn't make sense:
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;
}
You're basically defeating the purpose of a relational database system and underestimating the powers of the structured query language SQL. You're basically copying the entire database table fully into Java's memory and then manually exploring every single record if it matches a given condition.
This is plain inefficient. You should be interacting with the database in such way that it returns exactly the information you need and nothing more. You can use among others the WHERE
clause for this. It appears that your IDE was smart enough to autogenerate such a named query for you: Customer.findByName
. Make use of it.
private boolean isUserNameInDBOK(String uName) {
return customerFacade.findByName(name) != null;
}
This way the DB will return 1 or 0 records matching the given condition. You just have to check if it returned a record or not. Yet more efficient is to add a named query which does a COUNT(*)
returning a long
or perhaps boolean
instead of a whole Customer
. Even then, the whole ErrorUtils
class is pretty superfluous in this construct. Just invoke the service method directly.
这篇关于实用程序类中的@EJB为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!