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