Search code examples
javaspringjspspring-webflowspring-java-config

JavaConfig Spring Web Flow returns 404 not found (JSP)


I have been trying out the Java Configuration feature of Spring Web Flow 2.4 by modifying an existing project from xml configuration to JavaConfig. The XML version works, but JavaConfig doesn't. Every time I try to start the flow with URL http://localhost:8080/sia_p219_ch08_spring_web_flow_order_pizza_customer_flow_complete/pizza , it returns 404. There are no exceptions. The console show no "no request mapping found for..." message. The webpage shows The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

The project is hosted on github, the working XML version is here.

I think the problem is the request URL doesn't call the pizza flow (/WEB-INF/flows/pizza/pizza-flow.xml).

Here are some code snippets:

WebAppInitializer:

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] { RootConfig.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[] { WebConfig.class };
}

@Override
// map DispatcherServlet to /
protected String[] getServletMappings() {
    return new String[] { "/" };
}

RootConfig:

@Configuration
@Import({WebFlowConfig.class})
public class RootConfig {}

WebFlowConfig:

@Configuration
@ComponentScan({"pizza"})
public class WebFlowConfig extends AbstractFlowConfiguration {
    static{
        System.out.println("WebFlowConfig loaded");
    }

    @Autowired
    private WebConfig webMvcConfig;

    @Bean
    public FlowDefinitionRegistry flowRegistry() {
        return 
            getFlowDefinitionRegistryBuilder(flowBuilderServices())
            .setBasePath("/WEB-INF/flows")
            .addFlowLocationPattern("/**/*-flow.xml")
            .build();
    }

    @Bean
    public FlowExecutor flowExecutor(){
        return getFlowExecutorBuilder(flowRegistry()).build();
    }

    @Bean
    public FlowBuilderServices flowBuilderServices() {
        return getFlowBuilderServicesBuilder()
                .setViewFactoryCreator(mvcViewFactoryCreator())
                .setDevelopmentMode(true)
                .build();
    }

    @Bean
    public MvcViewFactoryCreator mvcViewFactoryCreator() {
        MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
        factoryCreator.setViewResolvers(Collections.singletonList(this.webMvcConfig.viewResolver()));
        factoryCreator.setUseSpringBeanBinding(true);
        return factoryCreator;
    }
}

WebConfig

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    static{
        System.out.println("WebConfig loaded");
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/flows/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    // configure static content handling
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {           
        configurer.enable();
    }

The flow definition files and JSPs are fine and you can see them on github if you want.

Thanks a lot, any help is greatly appreciated.


Solution

  • What I've found so far that the configuration definitely lacks this part of configuration in WebFlowConfig (take a look at the documentation page for integration with Spring MVC for details):

    @Bean 
    @Autowired
    public FlowHandlerAdapter flowHandlerAdapter(FlowExecutor flowExecutor) {
        FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
        flowHandlerAdapter.setFlowExecutor(flowExecutor);
    
        return flowHandlerAdapter;
    }
    
    @Bean 
    @Autowired
    public FlowHandlerMapping flowHandlerMapping(FlowDefinitionRegistry flowDefinitionRegistry) {
        FlowHandlerMapping flowHandlerMapping = new FlowHandlerMapping();
        flowHandlerMapping.setFlowRegistry(flowDefinitionRegistry);
        flowHandlerMapping.setOrder(0);
    
        return flowHandlerMapping;
    }
    

    Also remove mvcViewFactoryCreator definition and setViewFactoryCreator call from the flowBuilderServices bean definition as well. It works for me.