Starting with RichFaces Push on Various Servlet Containers

I have identified problems with starting with RichFaces Push recently on various containers,

so I have started this article to help summarize configuration necessary.

 

Refer to Links when more information needed.

 

Please modify this article when you are missing configuration for container you are using,

or comment when you are experiencing issues.

 

 

 

Features

 

RichFaces Push functionality depends on several features, which are briefly described here

including instructions what to do when feature is not available on given container.

 

Servlet Registration

 

RichFaces Push requires PushServlet registered for web application in order to connect to container and listen for push requests.

 

In Servlets 3.0 and higher environments, automatic servlet registration is prepared, so your servlet should be initialized automatically, so no actions required by end-user application.

 

However in Servlets 2.5 and lower, servlet needs to be registered manually in web.xml:

 

<!-- Push Servlet - listens for user sessions -->
<servlet>
    <servlet-name>Push Servlet</servlet-name>
    <servlet-class>org.richfaces.webapp.PushServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Push Servlet</servlet-name>
    <url-pattern>/__richfaces_push</url-pattern>
</servlet-mapping>

<!-- setups servlet-mapping in RichFaces configuration -->
<context-param>
    <param-name>org.richfaces.push.handlerMapping</param-name>
    <param-value>/__richfaces_push</param-value>
</context-param>

 

 

Note: When you are registering servlets in Servlets 3.0 environments manually, RichFaces will detect that servlet for Push is already registered and it avoid to initialize it again, however be sure to setup PushServlet to support asynchronous servlets, then modify servlet registration in previous web.xml snippet as follows:

 

<servlet>
    <servlet-name>Push Servlet</servlet-name>
    <servlet-class>org.richfaces.webapp.PushServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

 

 

 

Asynchronous Servlets

 

RichFaces uses Atmosphere to provide Push functionality, which is able to detect whenever it can use asynchronous servlets.

 

However in some cases (you can find them in table bellow), you need to switch to use blocking I/O instead of asynchronous servlets:

 

<context-param>
    <param-name>org.atmosphere.useBlocking</param-name>
    <param-value>true</param-value>
</context-param>

 

JMS Integration

 

Warning: in RichFaces 4.2 Push has been refactored to turn off the JMS integration by default, you need to  use org.richfaces.push.jms.enable to enable it

 

RichFaces Push (in 4.1) integrates with Java Message Service, which comes with Java EE 6 compatible application servers, however when using generic servlet container, you need to either setup JMS manually or you can turn JMS integration off using following web.xml configuration:

 

<context-param>
    <param-name>org.richfaces.push.jms.disable</param-name>
    <param-value>true</param-value>
</context-param>

 

You don't need to use JMS in order to push messages, you can use alternative approaches: CDI events  or TopicsContext interface.

 

Push Initialization & Topics Creation

 

Warning: in RichFaces 4.2, topics are created on demand (when they are access first), so no custom topic initialization is required, however you may need to initialize pushContext at startup (which was ensured by custom TopicsInitializer before: web.xml context-param - org.richfaces.push.initializeOnStartup))

 

RichFaces 4.0 and 4.1 assume that topics needs to be created programatically before application is fully started.

 

You can use following TopicsInitializer class code in your project and register it at JSF startup.

 

 

TopicsInitializer.java:

 

package my.jsflisteners;


import javax.faces.event.AbortProcessingException;
import javax.faces.event.PostConstructApplicationEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;


import org.richfaces.application.push.Topic;
import org.richfaces.application.push.TopicKey;
import org.richfaces.application.push.TopicsContext;
import org.richfaces.application.push.impl.DefaultMessageDataSerializer;


public class TopicsInitializer implements SystemEventListener {


    public void processEvent(SystemEvent event) throws AbortProcessingException {
        if (event instanceof PostConstructApplicationEvent) {
            try {
                TopicsContext topicsContext = TopicsContext.lookup();
                Topic pushTopic = topicsContext.getOrCreateTopic(new TopicKey("pushTopicsContext"));
                pushTopic.setMessageDataSerializer(DefaultMessageDataSerializer.instance());
            } catch (Exception e) {
                throw new RuntimeException("Unable to initialize topics", e);
            }
        }
    }


    @Override
    public boolean isListenerForSource(Object source) {
        return true;
    }
}

 

 

faces-config.xml:

 

<?xml version="1.0"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">


    <application>
        <system-event-listener>
            <system-event-listener-class>my.jsflisteners.TopicsInitializer</system-event-listener-class>
            <system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
        </system-event-listener>
    </application>


</faces-config>

 

 

 

 

Notes

 

Servlets API support and web.xml version

 

Be aware that containers which supports Servlets 3.0 does select between Servlet API version in accordance to web.xml version - if you are using version 2.5 of web.xml, then you need to use configuration as if you container is supporting Servlet 2.5!

 

web.xml header for Servlets 3.0:

 

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

 

web.xml header for Servlets 2.5:

 

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

 

Atmosphere version support

 

If you are using Maven, be sure to use richfaces-bom to manage dependencies,

 

but in case you are configuring dependencies manually, use following summary:

 

  • RichFaces 4.0
    • Atmosphere 0.6.5
  • RichFaces 4.1
    • Atmosphere 0.8.0-RC1
  • RichFaces 4.2
    • Atmosphere 0.8.4
  • RichFaces 4.3.0
    • Atmosphere 1.0.1
  • RichFaces 4.3.1
    • Atmosphere 1.0.10

 

You can see BOM to determine current version.

 

Note: Don't try to upgrade Atmosphere versions outside of defined scope. 1. Atmosphere versions have incompatible API, 2. RF uses jquery.atmosphere.js javascript library which is tied to specific Atmosphere runtime version.

Container Support Table

 

ContainerServlets APIPushServlet registrationAsynchronous servlets
JBoss AS 63.0 Automatic bug, force to use blocking I/O
JBoss AS 73.0 Automatic Yes
Tomcat 73.0 issues (see comments)

Yes

Jetty 62.5

Manual

No, use blocking I/O

Jetty 72.5

Manual

No, use blocking I/O

 

Links

 

Following sources may help you with kicking off your project:

Component Guide: a4j:push component

Developer Guide

Using RichFaces 4.1 push (CDI/TopicContext) for non-maven based projects

Showcase: Samples of usage of a4j:push component