Server-initiated Rendering: EJB -> FacesContext?

*爱你&永不变心* 提交于 2019-12-04 15:37:29

The FacesContext is HTTP request based and thus only available during the HTTP request processing and even then only when the request URL matches the url pattern of the FacesServlet. If you're not inside the thread which is executed by the server to process the HTTP request, then there's also no means of a FacesContext. In an EJB container there's totally no means of HTTP requests.

Technically, the only way to let EJB inform JSF about a new message is to let EJB fire a HTTP request on an URL matching the url pattern of the FacesServlet with the message as request parameter. You can use java.net.URLConnection for this. JSF in turn can then do the Comet/HTTP push like stuff to update the view with the message the IceFaces way as you mentioned.

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();

and a poll.jsf which is attached to a backing bean like this:

@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;
    }

}

Note: using JSF 2.0 annotations, but they ought to be self-explaining enough.

I'm no expert but I'd expect that the FacesContext is available only during the processing of a JSF request. I am afraid you can't do exactly what you want but you can certainly work around it. There are actually two issues:

  1. How to get the update via MDB to a JSF page?
  2. How to refresh the page on the client when the event occurs? You cannot normally send data from a server to a client, the client must requst them (though there are some workarounds such as http://en.wikipedia.org/wiki/Comet_(programming)))

I'd something like the following:

  1. In the MDB, store the updated data somewhere - such as into a global cache (stateless session bean with @Singleton and a collection or a map for the updates)
  2. Modify the JSF page so that it queries the server for updates in regular interval (preferably in the background using Ajax via some ajax-enabled JSF componet) - if there is an update received via the MDB, the server will return it and the page will re-render itself

I have a workaround which involves a Timer on the JSF side (luckily it's on the server only, no AJAX and client-server communication is necessary) which checks a Singleton and fires updates when necessary. However I still believe this is not the proper solution and that it could be done without a Timer...

I also got a response on the Icefaces forum:

org.icefaces.application.PortableRenderer provides an object that can be used on non-JSF threads to invoke push. (This is available in the svn trunk and will be provided in the next alpha (= Icefaces 2.0 alpha 3) release.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!