【发布时间】:2019-02-27 20:31:04
【问题描述】:
在 JSF 应用程序(基于 Payara 5.183)中,我使用如下模式在某些操作后重定向用户:
@Named
@ViewScoped
public class ModelViewBean implements Serializable {
private Model _model;
...
public String delete() {
System.out.println(">> Deleting model with ID: " + _model.getId());
_appDaoBean.daoDelete(_model);
return "/main.xhtml?faces-redirect=true";
}
...
}
问题:如果有两个或多个页面使用不同的 _model 对象打开 - 操作 delete() 会导致第一次执行后其他页面上的 _model.getId() 出现 NPE。
同时像下面这样的方法工作正常:
@Named
@ViewScoped
public class ModelViewBean implements Serializable {
private Model _model;
...
public void delete() {
System.out.println(">> Deleting model with ID: " + _model.getId());
_appDaoBean.daoDelete(_model);
FacesContext.getCurrentInstance().getExternalContext().redirect("/main.xhtml");
}
...
}
我已经记录了30sec video with the issue
也是样例项目is published on the GitHub
NPE 的原因是什么,在这种情况下,在某些操作后使用导航最合适的方式是什么?
谢谢!
附注What is the difference between redirect and navigation/forward and when to use what? 之类的主题我已经阅读过,但到目前为止还没有找到我的问题的答案。
更新 1:
main.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form id="f1">
<h2>Main Page</h2>
<p:link outcome="/model.xhtml" value="Model1">
<f:param name="id" value="1"/>
</p:link>
<br/>
<p:link outcome="/model.xhtml" value="Model2">
<f:param name="id" value="2"/>
</p:link>
</h:form>
</h:body>
</html>
model.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{modelViewBean.id}" />
<f:viewAction action="#{modelViewBean.initModel}" />
</f:metadata>
<h:body>
<h:form id="f1">
<p:outputLabel value="Model ID: #{modelViewBean.model}" />
<br/>
<p:commandButton value="Delete" action="#{modelViewBean.delete()}" process="@this" update="@form" />
</h:form>
</h:body>
</f:view>
</html>
ModelViewBean.java
....
import javax.faces.view.ViewScoped;
....
@Named
@ViewScoped
public class ModelViewBean implements Serializable {
private static final long serialVersionUID = 6400111954793903238L;
private String _id;
private String _model;
private Date _beanCreateTime;
@PostConstruct
private void init() {
System.out.println(">> @PostConstruct -> init()");
_beanCreateTime = new Date();
}
public String initModel() {
System.out.println(">> ViewAction -> initModel()");
if (_id == null || _id.trim().isEmpty()) {
return "/main.xhtml?faces-redirect=true";
}
_model = UUID.randomUUID().toString();
return null;
}
public String delete() {
System.out.println(">> Deleting model with ID: " + _model.toUpperCase());
return "/main.xhtml?faces-redirect=true";
}
public String getId() {
return _id;
}
public void setId(String id) {
this._id = id;
}
public String getModel() {
return _model;
}
public Date getBeanCreateTime() {
return _beanCreateTime;
}
}
NPE:
java.lang.NullPointerException
at local.jsfsample.ModelViewBean.delete(ModelViewBean.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
....
重现问题的步骤:
- 打开 main.xhtml
- 同时打开两个选项卡(Model1 和 Model2)中的两个链接
- 使用 Model1 在第一个选项卡中按“删除”按钮 - 一切正常
- 在 Model2 的第二个选项卡中按“删除”按钮 - NPE 为
_model等于null(我还注意到@PostConstruct也被触发)
更新 2:
已更新主题以反映问题的更根本原因。感谢 cmets 中指向类似帖子的链接。
【问题讨论】:
-
JSF 2.4 不作为正式版本存在。将所有 Java EE 代码移至 Eclipse 是一种奇怪的(Oracle 要求的)副作用。示例代码(minimal reproducible example 风格,应内联发布。请使用 NPE 发布堆栈跟踪,并明确提及 NPE 发生在哪一行...
-
而且,您是否确实暗示当 bean 处于不同范围时不会发生 NPE?
-
@BalusC 谢谢你的提问!根据使用场景 - 我不能使用任何其他范围,因为我需要同时打开两个具有不同模型(实体)的相似页面。因此,尝试解决使用
@ViewScopedbean - 并没有真正帮助(即使它可以正常工作)。 -
@Kukeltje 感谢您抽出宝贵时间查看我的帖子!我已经发布了包含问题根本原因的确切代码。 GitHub 上的链接提供了完整的示例项目代码。 Stack-trace 很简单,没什么特别的。此外,通过查看我附加的短视频,问题本身变得非常自我解释。再次感谢您的宝贵时间!附言该问题也可以在带有 JSF 2.3.2 的 Glassfish 5 上重现。
-
尝试与其他范围。它在那里也失败了,你的标题不正确,人们可能会开始解决错误的方向。请再次发布minimal reproducible example inline
标签: jsf redirect nullpointerexception