Using JSF with spring boot

Learn how to integrate JSF with spring boot to allow common configuration across applications

Detailed Video Notes

If you work in a large organization you may have hundred of applications that are JSF based it is unlikely you will flip a switch to move away from them. Spring boot does a very good job separating concerns and supporting various templating languages that are more familiar to front end developers. While you maintain a JSF stack you may want to take advantage of spring boot features so in this tutorial we will show how to integrate spring boot and jsf 2.2.

If you are not aware JSF 2.2 has many new features such as HTML5 support, allows a more natural templating with pass through attributes, security enhancements and much more. I still am not a fan of java code producing HTML, why not just write it. This java tutorial will focus on sun's mojarra so depending on which implementation (Apache MyFaces) there could be subtle differences.

Project set up

[0:36]

Following the spring boot tutorial and creating a project from spring initializr website we will select web and generate the project. After downloading the project we will import it into eclipse and update the dependencies we need to configure JSF.

<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-api</artifactId>
    <version>2.2.8</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-impl</artifactId>
    <version>2.2.8</version>
    <scope>compile</scope>
    <optional>true</optional>
</dependency>

Configuring faces servlet

[0:47]

JSF is just a servlet so both JSF and spring MVC can co-exist and when they do it makes for friendly way to expose REST application services that sit right next to your application. Creating a configuration class ConfigureJSF we will register faces servlet with spring boot by creating ServletRegistrationBean which has a spring friendly design to register servlets in Servlet 3.0+ containers. When spring boot starts up it will automatically find any type of ServletRegistrationBean and register it with your container. You will notice that we extend ServletRegistrationBean in order grab hold of FacesInitializer and pass in servletContext to enable us to set application configuration parameters which we will show later.

@Configuration
public class ConfigureJSF {

    @Bean
    public ServletRegistrationBean facesServletRegistration() {

        ServletRegistrationBean servletRegistrationBean = new JsfServletRegistrationBean();

        return servletRegistrationBean;
    }

    public class JsfServletRegistrationBean extends ServletRegistrationBean {

        public JsfServletRegistrationBean() {
            super();
        }

        @Override
        public void onStartup(ServletContext servletContext)
                throws ServletException {

            FacesInitializer facesInitializer = new FacesInitializer();

            Set<Class<?>> clazz = new HashSet<Class<?>>();
            clazz.add(ConfigureJSF.class);
            facesInitializer.onStartup(clazz, servletContext);
        }
    }
}

Create faces-config.xml

[2:31]

Since JSF 2 supports annotations the dependency on the faces-config.xml diminishes but we still have the need to register spring's el-resolver and phase listener. If you aren't familiar SpringBeanFacesELResolver allows you to use spring beans in JSF context and DelegatingPhaseListenerMulticaster delegates to spring WebApplicationContext. With this set up an application can use either spring manage beans or JSF annotations such as @ManagedBean. We will create faces-config.xml in in the src/main/resources/META-INF/faces-config.xml and add the el-resolver and phase-listener.

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
              version="2.2">

    <application>
        <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> 
    </application>

    <lifecycle>
        <phase-listener>org.springframework.web.jsf.DelegatingPhaseListenerMulticaster</phase-listener>
    </lifecycle>

</faces-config>

Creating sample page

[2:7]

To demonstrate that a JSF xhtml file can reference both a spring bean and a JSF managed bean we will create index.xhtml file in spring boot default location src/main/webapp. At this point we are ready to run our application and access http://localhost:8080/index.faces.

JSF managed bean

@ManagedBean
@RequestScoped
public class JsfBean {
    
    private String welcomeMessage = "Populated by JSF created bean";

    public String getWelcomeMessage() {
        return welcomeMessage;
    }

}

Spring bean

public class JSFSpringBean {

    private String welcomeMessage = "Populated by spring created bean";

    public String getWelcomeMessage() {
        return welcomeMessage;
    }
}

Template source code

<!DOCTYPE html>
<f:view xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
    encoding="UTF-8">

    <html>

    <h:head>

    </h:head>

    <!--Main Body -->
    <h:body>

        <h1>Welcome to JSF spring boot tutorial</h1>

        <h3>#{jsfBean.welcomeMessage}</h3>
        <h3>#{jsfSpringBean.welcomeMessage}</h3>
        
    </h:body>

    </html>
</f:view>

Template generated output

<html>

<head id="j_idt2"></head>

<body>
    <h1>Welcome to JSF spring boot tutorial</h1>
    <h3>Populated by JSF created bean</h3>
    <h3>Populated by spring created bean</h3></body>

</html>

JSF context parameters

[2:27]

Spring boot incorporates many servlet 3.0 features which will be an adjustment for developers as a web.xml isn't needed anymore. JavaServer Faces is configured using context parameters so we need to initializing servlet parameters programmatically using spring. To do this we will create a class that extends ServletContextInitializer a spring boot class that allows you to configure a Servlet 3.0+ context programmatically. Next since JSF has configuration that can be applied based on environment we will use @Profile and set spring.profiles.active=dev in application.properties. In our snippet what this will do is when we are in a development profile the JSF templates will refresh regularly vs in production we wouldn't.

@Configuration
@Profile("dev")
static class ConfigureJSFContextParameters implements ServletContextInitializer {

    @Override
    public void onStartup(ServletContext servletContext)
            throws ServletException {

        servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX",
                ".xhtml");
        servletContext.setInitParameter(
                "javax.faces.PARTIAL_STATE_SAVING_METHOD", "true");
        servletContext.setInitParameter("javax.faces.PROJECT_STAGE",
                "Development");
        servletContext.setInitParameter("facelets.DEVELOPMENT", "true");
        servletContext.setInitParameter(
                "javax.faces.FACELETS_REFRESH_PERIOD", "1");

    }
}

Thanks for joining in today's level up, have a great day!