How to configure the Multi-JSF feature in EAP 7.1 ?

Solution Verified - Updated

Environment

Red Hat JBoss Enterprise Application Platform (EAP) 7.1.x

Issue

Is it possible in EAP 7.1 to use a JSF implementation that is not provided as part of the JBoss server distribution?

Resolution

Multi-JSF is a feature that allows to configure almost any JSF implementation as if it were the implementation that ships with JBoss EAP. In particular is possible to install any version of Sun Mojarra or Apache MyFaces that implements JSF specification 2.1, or later.

Notice that you should remove all references to JSF from your war file's WEB-INF/lib if they are present

  1. Add the JSF implementation JAR file.

    1.1 Create the appropriate directory structure in the EAP_HOME/modules/ directory for the JSF implementation:

    $ cd EAP_HOME/modules/
    $ mkdir -p com/sun/jsf-impl/JSF_IMPL_NAME-JSF_VERSION
    

    Notice that you should replace JSF_IMPL_NAME-JSF_VERSION to the name and version of the JSF implementation, such as mojarra-2.2.11 for Mojarra 2.2.11.

    1.2 Copy the JSF implementation JAR file to the JSF_IMPL_NAME-JSF_VERSION/ subdirectory.

    1.3 In the JSF_IMPL_NAME-JSF_VERSION/ subdirectory, create a module.xml file as following:

    • For Mojarra implementation:
    <module xmlns="urn:jboss:module:1.5" name="com.sun.jsf-impl"     slot="JSF_IMPL_NAME-JSF_VERSION">
        <properties>
            <property name="jboss.api" value="private"/>
        </properties>
    
    <dependencies>
            <module name="javax.faces.api" slot="JSF_IMPL_NAME-JSF_VERSION"/>
            <module name="javaee.api"/>
            <module name="javax.servlet.jstl.api"/>
            <module name="org.apache.xerces" services="import"/>
            <module name="org.apache.xalan" services="import"/>
            <module name="javax.xml.rpc.api"/>
            <module name="javax.rmi.api"/>
            <module name="org.omg.api"/>
        </dependencies>
    
        <resources>
            <resource-root path="jsf-impl-JSF_VERSION.jar"/>
        </resources>
    </module>
    
    • For MyFaces implementation:
    <module xmlns="urn:jboss:module:1.5" name="com.sun.jsf-impl" slot="JSF_IMPL_NAME-JSF_VERSION">
        <properties>
            <property name="jboss.api" value="private"/>
        </properties>
        
        <dependencies>
            <module name="javax.faces.api" slot="JSF_IMPL_NAME-JSF_VERSION">
                <imports>
                    <include path="META-INF/**"/>
                </imports>
            </module>
            <module name="javaee.api"/>
            <module name="javax.servlet.jstl.api"/>
            <module name="org.apache.xerces" services="import"/>
            <module name="org.apache.xalan" services="import"/>
            
            <!-- extra dependencies for MyFaces -->
            <module name="org.apache.commons.collections"/>
            <module name="org.apache.commons.codec"/>
            <module name="org.apache.commons.beanutils"/>
            <module name="org.apache.commons.digester"/>
            
            < !-- extra dependencies for MyFaces 1.1
            <module name="org.apache.commons.logging"/>
            <module name="org.apache.commons.el"/>
            <module name="org.apache.commons.lang"/> -->
            <module name="javax.xml.rpc.api"/>
            <module name="javax.rmi.api"/>
            <module name="org.omg.api"/>
        </dependencies>
    
        <resources>
            <resource-root path="JSF_IMPL_NAME-impl-JSF_VERSION.jar"/>
        </resources>
    </module>
    

    Notice that you should to use appropriate values for the replaceable variables noted.

  2. Add the JSF API JAR file.

    2.1 Create the appropriate directory structure in the EAP_HOME/modules/ directory for the JSF implementation:

    $ cd EAP_HOME/modules/
    $ mkdir -p javax/faces/api/JSF_IMPL_NAME-JSF_VERSION
    

    2.2 Copy the JSF API JAR file to the JSF_IMPL_NAME-JSF_VERSION/ subdirectory.

    2.3 In the JSF_IMPL_NAME-JSF_VERSION/ subdirectory, create a module.xml file as following:

    • For Mojarra implementation:
    <module xmlns="urn:jboss:module:1.5" name="javax.faces.api" slot="JSF_IMPL_NAME-JSF_VERSION">
        <dependencies>
            <module name="com.sun.jsf-impl" slot="JSF_IMPL_NAME-JSF_VERSION"/>
            <module name="javax.enterprise.api" export="true"/>
            <module name="javax.servlet.api" export="true"/>
            <module name="javax.servlet.jsp.api" export="true"/>
            <module name="javax.servlet.jstl.api" export="true"/>
            <module name="javax.validation.api" export="true"/>
            <module name="org.glassfish.javax.el" export="true"/>
            <module name="javax.api"/>
        </dependencies>
        
        <resources>
            <resource-root path="jsf-api-JSF_VERSION.jar"/>
        </resources>
    </module>
    
    • For MyFaces implementation:
    <module xmlns="urn:jboss:module:1.5" name="javax.faces.api" slot="JSF_IMPL_NAME-JSF_VERSION">
        <dependencies>
            <module name="javax.enterprise.api" export="true"/>
            <module name="javax.servlet.api" export="true"/>
            <module name="javax.servlet.jsp.api" export="true"/>
            <module name="javax.servlet.jstl.api" export="true"/>
            <module name="javax.validation.api" export="true"/>
            <module name="org.glassfish.javax.el" export="true"/>
            <module name="javax.api"/>
            
            <!-- extra dependencies for MyFaces 1.1
            <module name="org.apache.commons.logging"/>
            <module name="org.apache.commons.el"/>
            <module name="org.apache.commons.lang"/> -->
        </dependencies>
        
        <resources>
            <resource-root path="myfaces-api-JSF_VERSION.jar"/>
        </resources>
    </module>
    
  3. Add the JSF injection JAR file. Note this step may need to be repeated when updating EAP (7.4.2+ particularly) per java.lang.IncompatibleClassChangeError: Found interface org.jboss.as.web.common.WebInjectionContainer, but class was expected.

    3.1 Create the appropriate directory structure in the EAP_HOME/modules/ directory for the JSF implementation:

    $ cd EAP_HOME/modules/
    $ mkdir -p org/jboss/as/jsf-injection/JSF_IMPL_NAME-JSF_VERSION
    

    3.2 Copy the wildfly-jsf-injection and weld-core-jsf JAR files from EAP_HOME/modules/system/layers/base/org/jboss/as/jsf-injection/main/ to the JSF_IMPL_NAME-JSF_VERSION/ subdirectory. If running a CP be sure to copy from any latest available CP jsf-injection overlay jars:

    $ cp EAP_HOME/modules/system/layers/.overlays/layer-base-jboss-eap-7.4.<version>.CP/org/jboss/as/jsf-injection/main/*.jar /path/to/org/jboss/as/jsf-injection/JSF_IMPL_NAME-JSF_VERSION
    

    3.3 In the JSF_IMPL_NAME-JSF_VERSION/ subdirectory, create a module.xml file as following:

    • For Mojarra implementation:
    <module xmlns="urn:jboss:module:1.5" name="org.jboss.as.jsf-injection" slot="JSF_IMPL_NAME-JSF_VERSION">
        <properties>
            <property name="jboss.api" value="private"/>
        </properties>
        
        <resources>
            <resource-root path="wildfly-jsf-injection-INJECTION_VERSION.jar"/>
            <resource-root path="weld-core-jsf-WELD_VERSION.jar"/>
        </resources>
        
        <dependencies>
            <module name="com.sun.jsf-impl" slot="JSF_IMPL_NAME-JSF_VERSION"/>
            <module name="javax.api"/>
            <module name="org.jboss.as.web-common"/>
            <module name="javax.servlet.api"/>
            <module name="org.jboss.as.ee"/>
            <module name="org.jboss.as.jsf"/>
            <module name="javax.enterprise.api"/>
            <module name="org.jboss.logging"/>
            <module name="org.jboss.weld.core"/>
            
            <module name="javax.faces.api" slot="JSF_IMPL_NAME-JSF_VERSION"/>
        </dependencies>
    </module>
    
    • For MyFaces implementation:
    <module xmlns="urn:jboss:module:1.5" name="org.jboss.as.jsf-injection" slot="JSF_IMPL_NAME-JSF_VERSION">
        <properties>
            <property name="jboss.api" value="private"/>
        </properties>
        
        <resources>
            <resource-root path="wildfly-jsf-injection-INJECTION_VERSION.jar"/>
            <resource-root path="weld-core-jsf-WELD_VERSION.jar"/>
        </resources>
        
        <dependencies>
            <module name="com.sun.jsf-impl" slot="JSF_IMPL_NAME-JSF_VERSION"/>
            <module name="javax.api"/>
            <module name="org.jboss.as.web-common"/>
            <module name="javax.servlet.api"/>
            <module name="org.jboss.as.ee"/>
            <module name="org.jboss.as.jsf"/>
            <module name="javax.enterprise.api"/>
            <module name="org.jboss.logging"/>
            <module name="org.jboss.weld.core"/>
            <module name="org.wildfly.security.elytron"/>
            
            <module name="javax.faces.api" slot="JSF_IMPL_NAME-JSF_VERSION"/>
        </dependencies>
    </module>
    
  4. Add the commons-digester JAR file if you are installing MyFaces.

    4.1 Create the appropriate directory structure in the EAP_HOME/modules/ directory for the commons-digester JAR:

    $ cd EAP_HOME/modules/
    $ mkdir -p org/apache/commons/digester/main
    

    4.2 Download the Content from search.maven.org is not included.commons-digester JAR file and copy it to the main/ subdirectory.

    4.3 In the main/ subdirectory, create a module.xml file with the following:

    <module xmlns="urn:jboss:module:1.5" name="org.apache.commons.digester">
        <properties>
            <property name="jboss.api" value="private"/>
        </properties>
        
        <resources>
            <resource-root path="commons-digester-VERSION.jar"/>
        </resources>
        
        <dependencies>
            <module name="javax.api"/>
            <module name="org.apache.commons.collections"/>
            <module name="org.apache.commons.logging"/>
            <module name="org.apache.commons.beanutils"/>
        </dependencies>
    </module>
    
  5. Set the default JSF implementation.

    5.1 Run the following management CLI command to set the new JSF implementation as the default implementation:

    /subsystem=jsf:write-attribute(name=default-jsf-impl-slot,value=JSF_IMPL_NAME-JSF_VERSION)
    

    5.2 Restart the JBoss EAP server for the changes to take effect.

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.