为什么注入Session bean会出现空指针异常?
Why the injection of Session beans gives null pointer exception?
我有一个非常简单的 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 "";
}
}
}
它只是验证数据库中的用户名和密码以及returns 公司对象
第二个页面delivery.xhtml绑定了view bean。在这个 bean 中,我注入了登录 bean,但每次我使用 Company 对象时它 returns null。但是,当我转到 login.xhtml 时,我发现公司对象不为空。
下面是交付bean。
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 "";
}
}
这里是 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>
我正在 Glassfish 4.1 上部署应用程序
@Inject
private LoginBean loginBean;
注入的工作方式是首先在 loginBean
字段中创建一个代理对象。 CDI 不会立即创建或查找 LoginBean
实例。相反,它会一直等到您在 loginBean
字段中调用代理上的方法。 CDI 将此称为上下文引用 - 您将获得的实例取决于您请求它的上下文。
但是你没有调用方法:
loginBean.company.toString()
您直接访问 company
字段 - CDI 无法拦截它。所以你从代理那里得到了一个无用的空值。
解决方案是不直接访问托管 bean 的字段。而是将 company
设为私有并创建一个 getter:
public class LoginBean implements Serializable {
private Company company;
public Company getCompany() {
return company;
}
并在 DeliveryBean
中调用此 getter。
我有一个非常简单的 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 "";
}
}
}
它只是验证数据库中的用户名和密码以及returns 公司对象
第二个页面delivery.xhtml绑定了view bean。在这个 bean 中,我注入了登录 bean,但每次我使用 Company 对象时它 returns null。但是,当我转到 login.xhtml 时,我发现公司对象不为空。 下面是交付bean。
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 "";
}
}
这里是 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>
我正在 Glassfish 4.1 上部署应用程序
@Inject
private LoginBean loginBean;
注入的工作方式是首先在 loginBean
字段中创建一个代理对象。 CDI 不会立即创建或查找 LoginBean
实例。相反,它会一直等到您在 loginBean
字段中调用代理上的方法。 CDI 将此称为上下文引用 - 您将获得的实例取决于您请求它的上下文。
但是你没有调用方法:
loginBean.company.toString()
您直接访问 company
字段 - CDI 无法拦截它。所以你从代理那里得到了一个无用的空值。
解决方案是不直接访问托管 bean 的字段。而是将 company
设为私有并创建一个 getter:
public class LoginBean implements Serializable {
private Company company;
public Company getCompany() {
return company;
}
并在 DeliveryBean
中调用此 getter。