de.dlopes.stocks.facilitator.config.JsfMvcConfig.java Source code

Java tutorial

Introduction

Here is the source code for de.dlopes.stocks.facilitator.config.JsfMvcConfig.java

Source

/*******************************************************************************
 * Copyright (c) 2016 Dominique Lopes.
 * All rights reserved. 
 *
 * This Source Code Form is subject to the terms of the Mozilla Public 
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Contributors:
 *     Dominique Lopes - initial API and implementation
 *******************************************************************************/
package de.dlopes.stocks.facilitator.config;

import javax.faces.webapp.FacesServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.faces.mvc.JsfView;
import org.springframework.faces.webflow.JsfFlowHandlerAdapter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.UrlFilenameViewController;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
import org.springframework.webflow.mvc.servlet.FlowHandlerMapping;

import com.sun.faces.config.ConfigureListener;

import de.dlopes.stocks.facilitator.StockFacilitatorApplication;

/**
 * This class provides the annotation based JSF and Spring Web MVC config that would 
 * traditionally be located in the web.xml and application-context.xml
 * 
 * @author Dominique Lopes
 *
 */
@Configuration
public class JsfMvcConfig extends SpringBootServletInitializer {

    /*
     * configuration of context parameters is done by means of entries of 
     * server.context-parameters.* in the application.properties 
     */

    /*
     * webflow configuration is configured elsewhere, but automatically injected 
     */
    @Autowired
    private WebFlowConfig webFlowConfig;

    /*
     * configuration settings (implicitly loaded from application.yaml)
     */
    @Autowired
    private ConfigurationSettings config;

    /**
     * configure the application for packaging as deployable war 
     */
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(StockFacilitatorApplication.class);
    }

    /**
     * initialize the deployable war with a minumum set of configuration params
     */
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        /*
         * set context param 'com.sun.faces.forceLoadConfiguration' in order to force JSF
         * implementation to neglect the need of a FacesServlet(-Mapping) and ConfigureListener
         * in a web.xml and to use annotation based configuration
         */
        servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
        super.onStartup(servletContext);
    }

    /**
     * create a Spring MVC dispatcher servlet so that we can slightly modify its
     * config within the environment automatically generated by spring boot
     * 
     * Hint: if we don't do that there will be two instances and all modifications
     * to the config
     * 
     * @return the DispatcherServlet
     */
    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }

    /**
     * Register the Spring MVC dispatcher servlet under the context path '/app/*'
     * 
     * hint: we need to do this otherwise there will be an overlap with JSF's
     * FacesServlet
     * 
     * @return a ServletRegistrationBean containing the DispatcherServlet and it's 
     *          mapping
     */
    @Bean
    public ServletRegistrationBean dispatcherServletRegistration() {
        ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
        registration.addUrlMappings(config.getDispatcherServletCxtpth() + "/*");
        return registration;
    }

    /**
     * Register the JSF's Faces servlet
     * 
     * Hint: this is needed for proper initialization of JSF
     * 
     * @return a ServletRegistrationBean containing the FacesServlet
     */
    @Bean
    public ServletRegistrationBean facesServletRegistration() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new FacesServlet());
        registration.setLoadOnStartup(1);
        registration.addUrlMappings("*.faces");
        return registration;
    }

    /**
    * Register JSF's configure listener
    * 
    * Hint: this is needed for proper initialization of JSF
    * 
    * @return a ServletListenerRegistrationBean instance containing the JSF related
    *          ConfigureListener
    */
    @Bean
    public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() {
        return new ServletListenerRegistrationBean<ConfigureListener>(new ConfigureListener());
    }

    /**
    * Maps request paths to flows in the flowRegistry; e.g. a path of 
    * /stock-info looks for a flow with id "stock-info" 
    * 
    * @return a FlowHandlerMapping instance (bound to the flowRegistry defined 
    *          in {@link WebFlowConfig})
    */
    @Bean
    public FlowHandlerMapping flowHandlerMapping() {
        FlowHandlerMapping mapping = new FlowHandlerMapping();
        mapping.setOrder(1);
        mapping.setFlowRegistry(this.webFlowConfig.flowRegistry());

        /* If no flow matches, map the path to a view, e.g. "/index" maps to a 
         * view named "index" */
        mapping.setDefaultHandler(new UrlFilenameViewController());
        return mapping;
    }

    /**
     * Dispatches requests mapped to flows to FlowHandler implementations
     * 
     * @return a FlowHandlerAdapter instance
     */
    @Bean
    public FlowHandlerAdapter flowHandlerAdapter() {
        JsfFlowHandlerAdapter adapter = new JsfFlowHandlerAdapter();
        adapter.setFlowExecutor(this.webFlowConfig.flowExecutor());
        return adapter;
    }

    /**
     * Resolves views selected for rendering by controllers to .xhtml 
     * resources in the /WEB-INF/views directory 
     * 
     * @return a UrlBasedViewResolver instance
     */
    @Bean
    public UrlBasedViewResolver faceletsViewResolver() {
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();
        resolver.setViewClass(JsfView.class);
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".xhtml");
        return resolver;
    }

}