Java Quiz Player

Servlet updates JSF Page through Server Push

Dec 28, 2016

1. Overview

This article is about updating components on a JSF (JavaServer Faces) page from a Servlet using the server push technology.

There are various techniques related to the server push used in JavaServer Faces applications using different libraries. Generally, the server push is from within the JSF application server components; the action is triggered from a JSF page to other pages. The OmniFaces library has a feature to dynamically update the JSF page from a Servlet. OmniFaces is a utility library for JSF 2.x.

This example application has a JSF page (or view) with a list box (h:selectOneListbox) with items. A servlet is run to add a new item to the list in the JSF page and display a message. This could also add the item in a database within the same transaction, in case the database is part of the application.

This application is deployed on an Apache Tomcat 7.0.65 webserver. The following software is used to develop and run the example:

The OmniFaces APIs used in this application are as follows:

The following is the link with details and API for the @Push, PushContext and <o:socket>: http://showcase.omnifaces.org/push/socket

2. The Push Servlet

The code snippet shows the configuration of the channel and sending the push message from the servlet's service method:

    @Inject @Push(channel="pushChannel")
    private PushContext channel;

    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException, ServletException {

        String newItem = req.getParameter("newItem");

        if ((newItem == null) || (newItem.isEmpty())) {
            newItem = "Java EE Programming";
        }
	
        Map<String, String> pushData = new HashMap<>();
        pushData.put("pushItem", newItem);
        channel.send(pushData);	
        ...
    }

The OmniFaces API's @Push annotation and PushContext interface are used to configure the channel and send a message object to the push socket channel. In the above code the channel is named as pushChannel. The message object, in this case is defined as a java.util.Map object with a single item.

The PushContext's send() method sends the given message object to the push socket channel as identified by @Push. The message object will be encoded as JSON and is available to the <o:socket>'s onmessage attribute in the JSF page.

The servlet is run from the browser's address bar. The request parameter is appended to the servlet URL and is used as the push data. For example, http://localhost:8080/servlet-jsf-server-push/pushServlet?newItem=HTML+and+JavaScript

3. The JSF Page

The code snippet is from the JSF page:

    <h:form>
        <h:selectOneListbox id="list" size="10" value="#{bean.item}"
                valueChangeListener="#{bean.valueChanged}">
            <f:selectItems value="#{bean.items}"/>				
            <f:ajax execute="@this" render="msg" />				
        </h:selectOneListbox>

        <h:outputText id="msg" value="#{bean.message}"/>

        <o:socket channel="pushChannel" onmessage="pushCommandScript" />
        <o:commandScript name="pushCommandScript" 
            action="#{bean.refreshItems}" render="list msg" />
    </h:form>

The managed bean ItemsManagedBean (identified as bean in the above code) is associated with the JSF page's components. This has functions to populate and get the selected item in the listbox (<h:selectOneListbox>) and display a message respectively: <f:selectItems value="#{bean.items}"/>, value="#{bean.item}" and <h:outputText id="msg" value="#{bean.message}"/>.

The <o:socket> tag's channel attribute identifies the web socket channel. Note that the channel name (pushChannel) is the same as the one defined in the servlet from which it is receiving the message. All open websockets on the same channel can receive the same push message from the server (note that the example has only one client). The onmessage attribute is the JavaScript event handler function that is invoked when a push message is received from the server.

OmniFaces's <o:commandScript> tag is an extension to <h:commandXxx> JSF HTML tag. This <o:commandScript> generates a JavaScript function which allows to execute a JSF ajax request. The render attribute works exactly the same as in <f:ajax> JSF core tag. The action attribute works exactly the same as in <h:commandXxx>.

In the above code, the <o:commandScript>'s action attribute is the application action when this tag is activated. The attribute value is a method binding EL expression that identifies an action method: action="#{bean.refreshItems}". The render attribute updates the specified UI components in an ajax response: render="list msg".

4. The Managed Bean wired to the JSF Page

The ItemsManagedBean is the managed bean that is wired to the components in the JSF page. This bean has a method refreshItems() to add an item to the items listbox and display a message on receiving the servlet pushed data. This method receives the pushed message data from the servlet as a request parameter.

This method is invoked when the JSF page with the channel that receives the push message. In this application the page's pushCommandScript's action method triggers this method.

    public void refreshItems() {
        FacesContext fc = FacesContext.getCurrentInstance();
        HttpServletRequest req = (HttpServletRequest) fc.getExternalContext().getRequest();
        String newItem = req.getParameter("pushItem");
        // The new item is added to the application
        items.add(newItem);
        items.sort(null);
        setItem(newItem);
        setMessage(newItem + " is added.");
    }

5. Sequence of Operations

  1. Start the JSF application; this displays the page in the browser.
  2. Execute the servlet in a browser; type in the servlet URL in the address bar. The item to be added is appended to the URL as a request parameter, for example, http://localhost:8080/servlet-jsf-server-push/pushServlet?newItem=PERL_scripting.
  3. The servlet's service method runs; starts the push over the channel and sends the push message object (the request parameter value).
  4. The pushed message is received by the client (JSF page) by the push connection channel (named as pushChannel) and the action method ItemsmanagedBean.refreshItems() is executed.
  5. The action method updates the page data; adds the new item (from the push message) to the list data and the message is updated as "xxx is added thru server push.".
  6. The UI (list and the message) is refreshed by the ajax response.

6. Screenshots

The following screenshots show the JSF page when the application is started, the running of the servlet (the browser's address bar with URL, request parameter and value) and the dynamically updated items list in the JSF page respectively.

GUI image
GUI image
GUI image

7. Download

Source code: ServletJSFServerPushExample.zip

The example uses Java SE 8, JavaServer Faces 2.2 (Apache MyFaces 2.2.11), OmniFaces 2.5.1 and Weld 2.3 (for CDI) and Servlets 3.0. This was tried on Apache Tomcat 7.0.65.

8. Reference and Useful Links

Return to top