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
Container | Servlets API | PushServlet registration | Asynchronous servlets |
---|---|---|---|
JBoss AS 6 | 3.0 | Automatic | bug, force to use blocking I/O |
JBoss AS 7 | 3.0 | Automatic | Yes |
Tomcat 7 | 3.0 | issues (see comments) | Yes |
Jetty 6 | 2.5 | Manual | No, use blocking I/O |
Jetty 7 | 2.5 | Manual | No, use blocking I/O |
Links
Following sources may help you with kicking off your project:
Component Guide: a4j:push component
Using RichFaces 4.1 push (CDI/TopicContext) for non-maven based projects
Comments