I have the following settings in application.properties
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=true
spring.resources.cache-period=10000
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
So cache period and strategy content works fine in all pages, but when I tried to use webflow all static doesn't get associated with the content vesrion as the other pages.
Here is my flow definition (resources/webflow/requests/new)
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<var name="uri" class="medicallab.misc.Uri"/>
<view-state id="selectPatient" view="add-request/select-patient">
<transition on="next" to="selectDoctor"></transition>
</view-state>
<view-state id="selectDoctor">
<transition on="next" to="selectTextType"></transition>
</view-state>
<view-state id="selectTestType">
<transition on="next" to="Confirm"></transition>
</view-state>
<view-state id="Confirm">
<transition on="next" to="Done" history="invalidate"></transition>
</view-state>
<end-state id="Done" view="externalRedirect:#{uri.get('requests')}">
<output name="success" value="'Request has been added successfully'"/>
</end-state>
<end-state id="cancelFlow" view="externalRedirect:#{uri.get('requests')}">
</end-state>
<global-transitions>
<transition on="cancel" to="cancelFlow" history="discard"></transition>
</global-transitions>
</flow>
And this is my WebMvcConfig class:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private WebFlowConfig webFlowConfig;
@Autowired
private SpringTemplateEngine springTemplateEngine;
@Bean
public BCryptPasswordEncoder bcryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping handlerMapping = new FlowHandlerMapping();
handlerMapping.setOrder(-1);
handlerMapping.setFlowRegistry(this.webFlowConfig.flowRegistry());
handlerMapping.setUrlDecode(true);
return handlerMapping;
}
@Bean
public FlowHandlerAdapter flowHandlerAdapter() {
FlowHandlerAdapter handlerAdapter = new FlowHandlerAdapter();
handlerAdapter.setFlowExecutor(this.webFlowConfig.flowExecutor());
handlerAdapter.setSaveOutputToFlashScopeOnRedirect(true);
return handlerAdapter;
}
@Bean
public AjaxThymeleafViewResolver ajaxThymeleafViewResolver() {
AjaxThymeleafViewResolver viewResolver = new AjaxThymeleafViewResolver();
viewResolver.setViewClass(FlowAjaxThymeleafView.class);
viewResolver.setTemplateEngine(springTemplateEngine);
return viewResolver;
}
}
Here is my WebFlowConfig
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
private WebMvcConfig webMvcConfig;
@Autowired
private List<ViewResolver> viewResolvers;
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.addFlowExecutionListener(securityFlowExecutionListener(), "*")
.build();
}
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setBasePath("classpath*:/templates")
.addFlowLocationPattern("/**/*-flow.xml")
.setFlowBuilderServices(flowBuilderServices())
.build();
}
@Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setDevelopmentMode(true)
.build();
}
@Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
viewResolvers.add(this.webMvcConfig.ajaxThymeleafViewResolver());
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setViewResolvers(viewResolvers);
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
@Bean
public SecurityFlowExecutionListener securityFlowExecutionListener() {
return new SecurityFlowExecutionListener();
}
}
Here is my thymeleaf layout (page.html):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="stylesheet" th:href="@{/css/app.css}">
<link rel="shortcut icon" type="image/x-icon" th:href="${ uri.get('favicon') }">
<!--/* Each token will be replaced by their respective titles in the resulting page. */-->
<title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE">Title</title>
</head>
<body>
<header id="page-header" layout:fragment="page-header">
<span th:replace="layouts/page-header :: page-header"></span>
</header>
<br />
<section id="page-alert" layout:fragment="page-alert">
<span th:replace="layouts/page-alert :: page-alert"></span>
</section>
<section id="page-content" layout:fragment="page-content">
page.html Page Content
</section>
<br /><br /><br /><br />
<footer id="page-footer" layout:fragment="page-footer">
<span th:replace="layouts/page-footer :: page-footer"></span>
</footer>
<script type="text/javascript" th:src="@{/js/app.js}"></script>
</body>
</html>
And here is the first flow page (add-patient.html):
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/page}">
<head>
<title th:text="#{app.page-title.requests}">RequestsPageTitle</title>
</head>
<body>
<section class="container" layout:fragment="page-content">
...
</section>
</body>
</html>
And this is the versions used (pom.xml):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<thymeleaf.version>3.0.7.RELEASE</thymeleaf.version>
<thymeleaf-springsecurity4.version>3.0.2.RELEASE</thymeleaf-springsecurity4.version>
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.4.5.RELEASE</version>
</dependency>
Here is what I found, when I use mvcResourceUrlProvider.getForLookupPath('/css/app.css')
the css file is associated with the content hash, I think the ResourceUrlProvider doesn't wrap the response that is related to webflow.
Any way how to hack it or fix something?
You can add the following code to your WebMvcConfig