为什么注入Session bean会出现空指针异常?

Joh*_*van 1 jsf dependency-injection primefaces jsf-2 jakarta-ee

我有一个非常简单的 JSF 2.2 ( hibernate 4.3 ) 应用程序,它有 2 个页面。第一页是 login.xhtml,它绑定到会话 bean 下面

import javax.inject.Named;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;

import javax.faces.context.FacesContext;


@Named(value = "loginBean")
@SessionScoped
public class LoginBean implements Serializable {

    /**
     * Creates a new instance of LoginBean
     */
    Company company;
   
    private static final long serialVersionUID = 1520318172495977648L;

    public String Login() {
        CompanyHelper companyHelper = new CompanyHelper();
        company = companyHelper.Login(this.loginName, this.password);
        if (company != null) {
            return "";
        } else {
            FacesMessage msg = new FacesMessage("Failed", "Wrong Usernames or password.");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            FacesContext.getCurrentInstance().addMessage(null, msg);
            return "";
        }
    }


}
Run Code Online (Sandbox Code Playgroud)

它只是验证数据库中的用户名和密码并返回公司对象

第二页delivery.xhtml 里面绑定了view bean。在这个 bean 中,我注入了登录 bean,但每次使用 Company 对象时它都返回 null。但是,当我转到 login.xhtml 时,我发现 company 对象不为空。下面是交付豆。

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.faces.model.SelectItem;
import javax.inject.Named;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;


@Named(value = "deliveryBean")
@ViewScoped
public class DeliveryBean implements Serializable {

    /**
     * Creates a new instance of DeliveryBean
     */
    @Inject
    private LoginBean loginBean;


    @PostConstruct
    public void init() {
       
        // returns null pointer exception
        Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, loginBean.company);
       

    }

    public String SendItem() {
        // reutn null point exception 
        String personName=deliverRequest.setDeliverFrom(loginBean.company.getContactPersonName());
        return "";
    }

  

}
Run Code Online (Sandbox Code Playgroud)

这是 pom.xml

 <dependencies>
        <!-- https://mvnrepository.com/artifact/org.primefaces/primefaces -->
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>6.1</version>
        </dependency>

        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>


      

     
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.11.Final</version>
        </dependency>

 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
Run Code Online (Sandbox Code Playgroud)

我正在 Glassfish 4.1 上部署应用程序

Vse*_*nov 5

@Inject
private LoginBean loginBean;
Run Code Online (Sandbox Code Playgroud)

注入的工作方式是首先在loginBean现场创建一个代理对象。CDI 不会LoginBean立即创建或查找实例。相反,它会等到您在loginBean现场调用代理上的方法。CDI 将此称为上下文引用 - 您将获得的实例取决于您请求它的上下文。

但是你不调用一个方法:

loginBean.company.toString()
Run Code Online (Sandbox Code Playgroud)

company直接访问该字段 - CDI 无法拦截。所以你从代理得到一个无用的空值。

解决方案是不直接访问托管 bean 的字段。而是设为company私有并创建一个 getter:

public class LoginBean implements Serializable {

private Company company;

public Company getCompany() {
    return company;
}
Run Code Online (Sandbox Code Playgroud)

并在DeliveryBean.