I have the following thymeleaf html page:
<head th:fragment="header">
<meta charset="utf-8" />
<link rel="stylesheet" href="../../css/main.css" th:href="@{/css/main.css}" />
<title th:text="#{device.page.title}">Title</title>
</head>
<body>
<div>
<h1 th:text="#{device.table.caption}"></h1>
<hr class="fineline"/>
Select devices using the checkboxes, you can update the client version or add client commands.
<form action="#" th:action="@{/devices/modify}" th:object="${deviceCommand}" method="post">
<table border="0" cellpadding="0" cellspacing="0" class="touchTable">
<!--<thead> -->
<tr>
<td scope="col" th:text="#{device.check.label}">Select</td>
<td width="300" scope="col"><span th:text="#{device.id.label}"></span> (<span th:text="#{device.retailer.name.label}"></span>)</td>
<td scope="col" th:text="#{device.current.label}">Curr Version</td>
<td scope="col" th:text="#{device.next.label}">Next Version</td>
<td scope="col" th:text="#{device.commands.label}">Commands</td>
</tr>
<!--</thead>-->
<!--<tbody> -->
<tr th:each="d : ${devices}">
<td><input type="checkbox" th:field="*{deviceModificationIds}" th:value="${d.id}"/></td>
<td><span th:text="${d.id}"></span> (<span th:text="${d.retailerName}"></span>)</td>
<td th:text="${d.currentClientVersion}">Washington</td>
<td th:text="${d.nextClientVersion}">gwash</td>
<td th:text="${d.commands}">gwash</td>
</tr>
<tr>
<td colspan="2"></td>
<td><span th:text="#{device.change.version.label}"></span><br/><input type="text" th:field="*{newVersion}"/></td>
<td><span th:text="#{device.add.command.label}"></span><br/><input type="text" th:field="*{newCommand}"/></td>
<td><br/><button type="submit" th:text="#{device.modify.action.button}">Action</button></td>
</tr>
<!--</tbody> -->
</table>
</form>
</div>
</body>
The problem is with the css stylesheet. Basically spring doesn't seem to be able to find it, despit me placing the file in /resources/static/css/main.css
It returns the error (in the logs):
o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/css/main.css] in DispatcherServlet with name 'dispatcherServlet'
Now the doco all says that Spring Boot should automatically serve things in /resources/static
Here is my WebConfig:
@Configuration
@ComponentScan("com.txxxxcorp.txxxxpoint.resource")
@EnableWebMvc
public class WebConfig {
@Bean
MultipartConfigElement multipartConfigElement() {
MultiPartConfigFactory factory = new MultiPartConfigFactory();
factory.setMaxFileSize("4096KB");
factory.setMaxRequestSize("4096KB");
return factory.createMultipartConfig();
}
@Bean
public ViewResolver viewResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setTemplateMode("XHTML");
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".html");
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver);
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(engine);
String[] excludedViews = new String[]{
"/resources/static/**"};
viewResolver.setExcludedViewNames(excludedViews);
return viewResolver;
}
@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer servletContainer) {
((TomcatEmbeddedServletContainerFactory) servletContainer).addConnectorCustomizers(
new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
httpProtocol.setCompression("on");
httpProtocol.setCompressionMinSize(256);
String mimeTypes = httpProtocol.getCompressableMimeTypes();
String mimeTypesWithJson = mimeTypes + "," + MediaType.APPLICATION_JSON_VALUE;
httpProtocol.setCompressableMimeTypes(mimeTypesWithJson);
}
}
);
}
};
}
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("messages");
return source;
}
For some reason, the editor does not let me insert the spring security config without complaining that its not properly formatted (IntelliJ, Maven and Spring Boot disagree with this, since it compiles and works), rest assured that I have allowed the /css/main.css path to go through
Does anyone know why I cannot resolve the css file?
The fact that you have used @EnableWebMvc
turns off Spring Boot's MVC autoconfiguration (and therefor the static resource handling).
To enable the static resource handling the best solution is to remove @EnableWebMvc
and let Spring Boot do what it does best - auto-configuration.
After the change you should do some regression testing to make sure nothing else broke
@geoand's Answer is correct ,your application's static resource is turn off as you use the @enablWebMvc
. so any css file you used here been parsed by thyemeleaf ,you need to declare the class to inheritted the WebMvcAutoConfigurationAdapter
and override the addResourceHandlers
method,
the code could be like below :
@Configuration
@ComponentScan("com.txxxxcorp.txxxxpoint.resource")
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String[] STATIC_RESOURCE = {"/","classpath:/","classpath:/META-INF/resources/", "classpath:/META-INF/resources/webjars/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/"};
if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**").addResourceLocations(STATIC_RESOURCE);
}
}
.......................
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With