FacesContext.getCurrentInstance () возвращает значение NULL в классе Runnable - PullRequest
6 голосов
/ 10 мая 2010

Я пытаюсь получить FacesContext, вызывая FacesContext.getCurrentInstance() в методе run() класса Runnable, но он возвращает null.

public class Task implements Runnable {

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

}

Как это вызвано и как я могу решить?

1 Ответ

13 голосов
/ 10 мая 2010

FacesContext хранится как переменная ThreadLocal в потоке, отвечающем за HTTP-запрос, который вызвал FacesServlet, который отвечает за создание FacesContext. Этот поток обычно проходит только через управляемые компоненты JSF. FacesContext недоступен в других потоках, созданных этим потоком.

На самом деле у вас не должно быть необходимости в других потоках. Более того, когда ваш поток запускается и работает независимо, базовый HTTP-запрос немедленно продолжит обработку HTTP-ответа и затем исчезнет. В любом случае, вы не сможете что-то сделать с ответом HTTP.

Вам нужно решить свою проблему по-другому. Спросите себя: для чего это нужно? Чтобы получить некоторую информацию? Просто передайте эту информацию Runnable во время ее создания.

В приведенном ниже примере предполагается, что вы хотите получить доступ к некоторому объекту области сеанса в потоке.

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 можно найти в этом связанном вопросе: Обновления в реальном времени из базы данных с использованием JSF / Java EE . Если вы используете PrimeFaces, посмотрите на <p:push>. Если вы используете OmniFaces, посмотрите <o:socket>.


Не имеет отношения к конкретной проблеме, вызывает тревогу ручное создание Runnable s и создание потоков вручную в веб-приложении Java EE. Перейдите к следующим вопросам и ответам, чтобы узнать обо всех предостережениях и о том, как это на самом деле должно быть сделано:

...