Rendu initié par le serveur: EJB -> FacesContext?


2

J'ai déjà posé cette question sur le forum Icefaces, mais entre-temps j'ai réalisé qu'il s'agit d'un problème plus générique.

Je voudrais mettre à jour des parties d'une page JSF quand j'obtiens un message dans ma MDB.

Le problème est, comment obtenir le FacesContext à partir du conteneur EJB?

Dans la fonction de traitement de messages, FacesContext.getCurrentInstance() renvoie null.

J'ai également essayé de transformer un bean géré par JSF en un MDB, mais je n'ai pas pu le faire (il semble que vous ne puissiez pas avoir les deux dans la même classe?).

Depuis que je suis un débutant dans le monde JSF je suis coincé maintenant. Y a-t-il un moyen de le faire fonctionner?

(Glassfish v3 + Netbeans 6.8, JSF2 + Icefaces 2.0 alpha2)

2

Le FacesContext est basé sur une requête HTTP et donc seulement disponible pendant le traitement de la requête HTTP et même seulement quand l'URL de la requête correspond au modèle d'URL du serveur FacesServlet. Si vous n'êtes pas dans le thread qui est exécuté par le serveur pour traiter la requête HTTP, il n'y a pas non plus de moyen d'un FacesContext. Dans un conteneur EJB, il n'y a aucun moyen de requêtes HTTP. Techniquement, la seule façon de permettre à EJB d'informer JSF d'un nouveau message est de laisser EJB déclencher une requête HTTP sur une URL correspondant au modèle d'URL de FacesServlet avec le message en tant que paramètre de requête. Vous pouvez utiliser java.net.URLConnection pour cela. JSF à son tour peut ensuite faire le Comet/HTTP pousser comme des choses pour mettre à jour la vue avec le message de la manière IceFaces comme vous l'avez mentionné.

E.g.

URL url = new URL("http://example.com/context/poll.jsf?msg=" + URLEncoder(msg, "UTF-8")); 
URLConenction connection = url.openConnection(); 
InputStream response = connection.getInputStream(); 

et un poll.jsf qui est attaché à un backing bean comme ceci:

@ManagedBean 
public class Poll { 

    @ManagedProperty(value="#{param.msg}") 
    private String msg; 

    @PostConstruct 
    public void init() { 
     // Do something with msg. 
    } 

    public void setMsg(String msg) { 
     this.msg = msg; 
    } 

} 

Remarque: en utilisant JSF 2.0 annotations, mais ils doivent être auto-suffisante pour expliquer.

+1

Merci pour la réponse. Cela fonctionne, bien que ce ne soit pas la solution la plus propre à mon avis (pourquoi le serveur d'application EE n'a-t-il pas un moyen interne de le faire, sans appeler le servlet en externe?), Mais acceptable. 21 avril. 102010-04-21 08:05:59


1

Je ne suis pas expert, mais je vous attendez que le FacesContext est disponible uniquement lors du traitement d'une demande de JSF. J'ai peur que vous ne puissiez pas faire exactement ce que vous voulez, mais vous pouvez certainement contourner ce problème. Il existe en fait deux problèmes:

  1. Comment obtenir la mise à jour via MDB vers une page JSF?
  2. Comment actualiser la page sur le client lorsque l'événement se produit? Vous ne pouvez pas envoyer normalement des données d'un serveur à un client, le client doit les requst (bien qu'il existe quelques solutions de contournement telles que http://en.wikipedia.org/wiki/Comet_(programming)))

je ferais quelque chose comme ce qui suit:

  1. Dans la MDB, stockez les données mises à jour quelque part - par exemple dans un cache global (bean session sans état avec @Singleton et une collection ou une carte pour les mises à jour)
  2. Modifiez la page JSF afin qu'elle interroge le serveur pour les mises à jour dans intervalle régulier (de préférence dans le backgrou e en utilisant Ajax via un ajax activé JSF componet) - si une mise à jour reçue par le MDB, le serveur retourne et la page va se réengendrer
  0

Salut, merci pour la réponse. # 2 est facile, car Icefaces 2.0 a sa classe PushRenderer, qui fonctionne bien. # 1 est la question: comment puis-je faire référence à une instance de classe gérée par le serveur FacesServlet, si je suis à l'extérieur? Les EJB s'exécutent dans un conteneur différent ... 20 avril. 102010-04-20 10:30:27

  0

@egbokul # 1 ne traite pas du tout JSF, il stocke simplement les données dans un bean @Singleton, auquel JSF peut accéder. C'est donc JSF -> EJB et non vice versa. Mais avec le PortableRenderer que vous mentionnez, vous pouvez espérer transférer les données de la MDB directement à JSF. Je suis curieux de savoir comment cela fonctionne :-) Bonne chance! 22 avril. 102010-04-22 13:03:28


0

J'ai une solution de contournement qui implique une minuterie sur le côté JSF (heureusement c'est sur le serveur seulement, pas de communication AJAX et client-serveur nécessaire) qui vérifie un Singleton et déclenche des mises à jour si nécessaire. Cependant je continue de croire que ce n'est pas la bonne solution et qu'elle pourrait être faite sans un temporisateur ...


0

J'ai aussi obtenu une réponse sur le forum Icefaces:

org.icefaces.application.PortableRenderer fournit un objet qui peut être utilisé sur les sujets non-JSF pour appeler pousser. (Ceci est disponible dans le tronc svn et sera fourni dans la prochaine version alpha (= Icefaces 2.0 alpha 3).)