Spring AsyncTask:更新 jsf 视图组件
Spring AsyncTask: update jsf view component
我有一个很长的 运行 工作必须 运行 在后台进行,完成后我想更新 jsf 视图组件。
我用 SimpleAsyncTaskExecutor
来完成这项工作。效果很好,但是在更新 ui 时我得到 NullPointerException
.
这是我的代码
SimpleAsyncTaskExecutor tasks = new SimpleAsyncTaskExecutor();
tasks.submitListenable(new Callable<String>() {
@Override
public String call() throws Exception {
//Do long time taking job in approximately 16 seconds
doTheBigJob();
//then update view component by it's id
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(myComponentId);
return "";
}
});
不是:当时间很短时(比如2秒),不会出现NullPointerException
提前致谢。
FacesContext.getCurrentInstance()
returns null
因为它试图从 thread local variable 获取上下文。但是因为执行线程不是由 JSF 初始化的(由 javax.faces.webapp.FacesServlet
完成)而是由执行程序创建的,所以线程局部变量是 null
.
我不知道为什么 NullPointerException
有时不会发生。默认情况下 SimpleAsyncTaskExecutor
每次都会创建新线程,除非您指定线程池。当我重新创建示例时,它每次都会发生。也许是,但没有正确记录...
要解决您的问题,您需要求助于轮询。例如,您可以使用支持 bean 的 属性 来指示作业已完成。
@Named("someBean")
@SessionScoped
public class SomeBean {
private volatile boolean jobDone = false;
public String execute() {
SimpleAsyncTaskExecutor tasks = new SimpleAsyncTaskExecutor();
tasks.submitListenable(new Callable<String>() {
public String call() throws Exception {
//Do long time taking job in approximately 16 seconds
doTheBigJob();
jobDone = true
return "";
}
});
return null;
}
public boolean isJobDone() {
return jobDone;
}
}
在您的页面上输入 jobDone==true
时呈现的组件。例如:
<h:outputText id="jobDoneText" rendered="#{someBean.jobDone}" value="Job finished"/>
然后使用轮询和 AJAX 更新当前页面。
在纯 JSF 中,进行轮询的唯一方法是结合使用 JavaScript 和 JSF AJAX 请求。
或者,您可以使用 Primefaces 组件 p:poll
轮询更改。
<p:poll interval="1" update="jobDoneText" />
有关 JSF 中轮询的更多信息,请参阅以下问题的答案:JSF, refresh periodically a component with ajax?
我有一个很长的 运行 工作必须 运行 在后台进行,完成后我想更新 jsf 视图组件。
我用 SimpleAsyncTaskExecutor
来完成这项工作。效果很好,但是在更新 ui 时我得到 NullPointerException
.
这是我的代码
SimpleAsyncTaskExecutor tasks = new SimpleAsyncTaskExecutor();
tasks.submitListenable(new Callable<String>() {
@Override
public String call() throws Exception {
//Do long time taking job in approximately 16 seconds
doTheBigJob();
//then update view component by it's id
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(myComponentId);
return "";
}
});
不是:当时间很短时(比如2秒),不会出现NullPointerException
提前致谢。
FacesContext.getCurrentInstance()
returns null
因为它试图从 thread local variable 获取上下文。但是因为执行线程不是由 JSF 初始化的(由 javax.faces.webapp.FacesServlet
完成)而是由执行程序创建的,所以线程局部变量是 null
.
我不知道为什么 NullPointerException
有时不会发生。默认情况下 SimpleAsyncTaskExecutor
每次都会创建新线程,除非您指定线程池。当我重新创建示例时,它每次都会发生。也许是,但没有正确记录...
要解决您的问题,您需要求助于轮询。例如,您可以使用支持 bean 的 属性 来指示作业已完成。
@Named("someBean")
@SessionScoped
public class SomeBean {
private volatile boolean jobDone = false;
public String execute() {
SimpleAsyncTaskExecutor tasks = new SimpleAsyncTaskExecutor();
tasks.submitListenable(new Callable<String>() {
public String call() throws Exception {
//Do long time taking job in approximately 16 seconds
doTheBigJob();
jobDone = true
return "";
}
});
return null;
}
public boolean isJobDone() {
return jobDone;
}
}
在您的页面上输入 jobDone==true
时呈现的组件。例如:
<h:outputText id="jobDoneText" rendered="#{someBean.jobDone}" value="Job finished"/>
然后使用轮询和 AJAX 更新当前页面。
在纯 JSF 中,进行轮询的唯一方法是结合使用 JavaScript 和 JSF AJAX 请求。
或者,您可以使用 Primefaces 组件 p:poll
轮询更改。
<p:poll interval="1" update="jobDoneText" />
有关 JSF 中轮询的更多信息,请参阅以下问题的答案:JSF, refresh periodically a component with ajax?