【问题标题】:Spring AsyncTask: update jsf view componentSpring AsyncTask:更新 jsf 视图组件
【发布时间】:2015-05-01 07:58:02
【问题描述】:

我有一个长期的工作必须在后台运行,完成后我想更新 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

提前致谢。

【问题讨论】:

  • 这里没有春季知识,但我怀疑这是否会起作用。我知道如何从异步调用(ejb,而不是 spring)更新视图的唯一方法是使用基于 websockets 的推送机制,例如气氛(所以老客户的后备发生)
  • 感谢您的建议,但 Dawit 的回答正是我想要的
  • :-) 如果我写了一个完整的答案,他写的正是我会写的,不同之处在于他建议轮询 (p:poll) 而我会建议 websockets (p:socket) .但是很好用

标签: spring jsf asynchronous


【解决方案1】:

FacesContext.getCurrentInstance() 返回null,因为它试图从thread local variable 获取上下文。但是由于执行线程不是由 JSF 初始化(由 javax.faces.webapp.FacesServlet 完成)而是由 executor 创建的,所以线程局部变量为 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?

【讨论】:

    猜你喜欢
    • 2019-05-23
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多