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. Перейдите к следующим вопросам и ответам, чтобы узнать обо всех предостережениях и о том, как это на самом деле должно быть сделано: