12.9. Third-Party Component Library Integration

Spring Faces strives to be compatible with any third-party JSF component library. By honoring all of the standard semantics of the JSF specification within the SWF-driven JSF lifecycle, third-party libraries in general should "just work". The main thing to remember is that configuration in web.xml will change slightly since Spring Faces requests are not routed through the standard FacesServlet. Typically, anything that is traditionally mapped to the FacesServlet should be mapped to the Spring DispatcherServlet instead. (You can also map to both if for example you are migrating a legacy JSF application page-by-page.) In some cases, a deeper level of integration can be achieved by configuring special flow services that are "aware" of a particular component library, and these will be noted in the examples to follow.

Rich Faces Integration

To use the Rich Faces component library with Spring Faces, the following filter configuration is needed in web.xml (in addition to the typical Spring Faces configuration):

 
<filter> 
    <display-name>RichFaces Filter</display-name> 
    <filter-name>richfaces</filter-name> 
    <filter-class>org.ajax4jsf.Filter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>richfaces</filter-name> 
    <servlet-name>Spring Web MVC Dispatcher Servlet</servlet-name>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>
            

For deeper integration (including the ability to have a view with combined use of the Spring Faces Ajax components and Rich Faces Ajax components), configure the RichFacesAjaxHandler on your FlowController:

 
<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
    <property name="flowExecutor" ref="flowExecutor" />
    <property name="ajaxHandler">
        <bean class="org.springframework.faces.richfaces.RichFacesAjaxHandler"/>
    </property>
</bean>
            

RichFaces Ajax components can be used in conjunction with the render tag to render partial fragments on an Ajax request. Instead of embedding the ids of the components to be re-rendered directly in the view template (as you traditionally do with Rich Faces), you can bind the reRender attribute of a RichFaces Ajax component to a special flowRenderFragments EL variable. For example, in your view template you can have a fragment that you would potentially like to re-render in response to a particular event:

<h:form id="hotels">
    <a4j:outputPanel id="searchResultsFragment">
        <h:outputText id="noHotelsText" value="No Hotels Found" rendered="#{hotels.rowCount == 0}"/>
        <h:dataTable id="hotels" styleClass="summary" value="#{hotels}" var="hotel" rendered="#{hotels.rowCount > 0}">
            <h:column>
                <f:facet name="header">Name</f:facet>
                #{hotel.name}
            </h:column>
            <h:column>
                <f:facet name="header">Address</f:facet>
                #{hotel.address}
            </h:column>
        </h:dataTable>
    </a4j:outputPanel>
</h:form>
            

then a RichFaces Ajax commandLink to fire the event:

<a4j:commandLink id="nextPageLink" value="More Results" action="next" reRender="#{flowRenderFragments}" />
            

and then in your flow definition a transition to handle the event:

<transition on="next">
    <evaluate expression="searchCriteria.nextPage()" />
    <render fragments="hotels:searchResultsFragment" />
</transition>
            

Apache MyFaces Trinidad Integration

The Apache MyFaces Trinidad library has been tested with the Spring Faces integration and proven to fit in nicely. Deeper integration to allow the Trinidad components and Spring Faces components to play well together has not yet been attempted, but Trinidad provides a pretty thorough solution on its own when used in conjunction with the Spring Faces integration layer.

NOTE - An AjaxHandler implementation for Trinidad is not currently provided out-of-the-box with Spring Faces. In order to fully integrate with Trinidad's PPR functionality, a custom implementation should be provided. An community-provided partial example can be found here: SWF-1160

Typical Trinidad + Spring Faces configuration is as follows in web.xml (in addition to the typical Spring Faces configuration):

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>server</param-value>
</context-param>

<context-param>
    <param-name>
        org.apache.myfaces.trinidad.CHANGE_PERSISTENCE
    </param-name>
    <param-value>session</param-value>
</context-param>

<context-param>
    <param-name>
        org.apache.myfaces.trinidad.ENABLE_QUIRKS_MODE
    </param-name>
    <param-value>false</param-value>
</context-param>

<filter>
    <filter-name>Trinidad Filter</filter-name>
    <filter-class>
        org.apache.myfaces.trinidad.webapp.TrinidadFilter
    </filter-class>
</filter>

<filter-mapping>
    <filter-name>Trinidad Filter</filter-name>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
</filter-mapping>

<servlet>
    <servlet-name>Trinidad Resource Servlet</servlet-name>
    <servlet-class>
        org.apache.myfaces.trinidad.webapp.ResourceServlet
    </servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>resources</servlet-name>
    <url-pattern>/adf/*</url-pattern>
</servlet-mapping>