FacesContext.getCurrentInstance() 在 Runnable 类中返回 null [英] FacesContext.getCurrentInstance() returns null in Runnable class

查看:43
本文介绍了FacesContext.getCurrentInstance() 在 Runnable 类中返回 null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过在 Runnable 的 run() 方法中调用 FacesContext.getCurrentInstance() 来获取 FacesContext 类,但它返回 null.

I am trying to get the FacesContext by calling FacesContext.getCurrentInstance() in the run() method of a Runnable class, but it returns null.

public class Task implements Runnable {

    @Override
    public void run() {
        FacesContext context = FacesContext.getCurrentInstance(); // null!
        // ...
    }

}

这是怎么引起的,我该如何解决?

How is this caused and how can I solve it?

推荐答案

FacesContext 存储为 ThreadLocal 变量在负责调用 FacesServlet 的 HTTP 请求的线程中,负责创建 FacesServlet代码>FacesContext.该线程通常仅通过 JSF 托管 bean 方法.FacesContext 在该线程产生的其他线程中不可用.

The FacesContext is stored as a ThreadLocal variable in the thread responsible for the HTTP request which invoked the FacesServlet, the one responsible for creating the FacesContext. This thread usually goes through the JSF managed bean methods only. The FacesContext is not available in other threads spawned by that thread.

您实际上也不应该在其他线程中需要它.而且,当您的线程启动并独立运行时,底层的 HTTP 请求将立即继续处理 HTTP 响应然后消失.无论如何,您将无法对 HTTP 响应执行任何操作.

You should actually also not have the need for it in other threads. Moreover, when your thread starts and runs independently, the underlying HTTP request will immediately continue processing the HTTP response and then disappear. You won't be able to do something with the HTTP response anyway.

您需要以不同的方式解决您的问题.问问自己:你需要它做什么?获取一些信息?只需在构建过程中将那个信息传递给 Runnable.

You need to solve your problem differently. Ask yourself: what do you need it for? To obtain some information? Just pass that information to the Runnable during its construction instead.

以下示例假设您想访问线程中的某个会话范围对象.

The below example assumes that you'd like to access some session scoped object in the thread.

public class Task implements Runnable {

    private Work work;

    public Task(Work work) {
        this.work = work;
    }

    @Override
    public void run() {
        // Just use work.
    }

}

Work work = (Work) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("work");
Task task = new Task(work);
// ...

如果您最终需要通知客户,例如线程的工作已完成,那么您应该寻找与例如不同的解决方案添加面孔消息左右.答案是使用推".这可以通过 SSE 或 websockets 来实现.在这个相关问题中可以找到一个具体的 websockets 示例:实时使用 JSF/Java EE 从数据库更新.如果您碰巧使用 PrimeFaces,请查看.如果您碰巧使用 OmniFaces,请查看 .

If you however ultimately need to notify the client e.g. that the thread's work is finished, then you should be looking for a different solution than e.g. adding a faces message or so. The answer is to use "push". This can be achieved with SSE or websockets. A concrete websockets example can be found in this related question: Real time updates from database using JSF/Java EE. In case you happen to use PrimeFaces, look at <p:push>. In case you happen to use OmniFaces, look at <o:socket>.

与具体问题无关,在 Java EE Web 应用程序中手动创建 Runnable 和手动生成线程令人担忧.前往以下问答了解所有注意事项以及实际应该如何做:

Unrelated to the concrete problem, manually creating Runnables and manually spawning threads in a Java EE web application is alarming. Head to the following Q&A to learn about all caveats and how it should actually be done:

这篇关于FacesContext.getCurrentInstance() 在 Runnable 类中返回 null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆