2010-05-10 15 views
5

Je suis en train d'obtenir le FacesContext en appelant FacesContext.getCurrentInstance() dans la méthode run() d'une classe Runnable, mais il retourne null.FacesContext.getCurrentInstance() retourne null en classe Runnable

public class Task implements Runnable { 

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

} 

Comment cela est-il causé et comment puis-je le résoudre?

Répondre

12

Le FacesContext est stockée en tant que variable ThreadLocal dans le fil chargé de la requête HTTP qui a invoqué le FacesServlet, le responsable de la création de la FacesContext. Ce thread passe généralement par les méthodes du bean géré par JSF uniquement. Le FacesContext n'est pas disponible dans les autres threads générés par ce thread.

Vous ne devriez pas en avoir besoin dans d'autres threads. De plus, lorsque votre thread démarre et s'exécute de manière indépendante, la requête HTTP sous-jacente continue immédiatement le traitement de la réponse HTTP, puis disparaît. De toute façon, vous ne pourrez pas faire quelque chose avec la réponse HTTP.

Vous devez résoudre votre problème différemment. Demandez-vous: pour quoi en avez-vous besoin? Pour obtenir des informations? Il suffit de passer que informations à la Runnable lors de sa construction à la place.

L'exemple ci-dessous suppose que vous souhaitez accéder à certains objets de session dans le 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); 
// ... 

Si toutefois vous avez besoin finalement d'informer le client par exemple que le travail du thread est terminé, alors vous devriez chercher une solution différente de celle par exemple. ajouter un message de visages ou plus. La réponse est d'utiliser "push". Cela peut être réalisé avec SSE ou websockets. Un exemple concret de websockets peut être trouvé dans cette question connexe: Real time updates from database using JSF/Java EE. Dans le cas où vous utilisez PrimeFaces, regardez <p:push>. Dans le cas où vous utilisez OmniFaces, regardez <o:socket>.


non apparentés au problème du béton, ce qui crée manuellement Runnable s et des fils de ponte manuellement dans une application web Java EE est alarmante. Tête à ce qui suit Q & A à en savoir plus sur toutes les mises en garde et comment il devrait effectivement se faire: