实用程序类中的@EJB为空 [英] @EJB inside utility class is null

查看:142
本文介绍了实用程序类中的@EJB为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的申请中有一个表单,我正在尝试验证该用户名和/或电子邮件尚未在数据库中。



这是服务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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆