To load the changes to the resources (HTML, js, CSS, etc), we can
- Restart the application every time- which is of course not a good idea!
- Recompile the resources using CTRL+F9 on IntelliJ or (CTRL+SHIFT+F9 if you are using eclipse keymap) or simply Right Click and Click Compile
- Or a better solution as described below !!
Thymeleaf includes a file-system based resolver, this loads the templates from the file-system directly not through the classpath (compiled resources).
See the snippet from DefaultTemplateResolverConfiguration#defaultTemplateResolver
@Bean public SpringResourceTemplateResolver defaultTemplateResolver() { SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); resolver.setApplicationContext(this.applicationContext); resolver.setPrefix(this.properties.getPrefix());
Where the property prefix is defaulted to "classpath:/template/". See the snippet ThymeleafProperties#DEFAULT_PREFIX
public static final String DEFAULT_PREFIX = "classpath:/templates/";
The Solution:
Spring Boot allows us to override the property 'spring.thymeleaf.prefix' to point to source folder 'src/main/resources/templates/ instead of the default "classpath:/templates/" as folllows.In application.yml|properties file:
spring: thymeleaf: prefix: file:src/main/resources/templates/ #directly serve from src folder instead of target
This would tell the runtime to not look into the target/ folder. And you don't need to restart server everytime you update a html template on our src/main/resources/template
What about the JavaScript/CSS files?
You can further go ahead and update the 'spring.resources.static-locations' to point to your static resource folder (where you keep js/css, images etc)spring: resources: static-locations: file:src/main/resources/static/ #directly serve from src folder instead of target cache: period: 0
The full code:
It a good practice to have the above configuration during development only. To have the default configuration for production system, you can use Profiles and define separate behaviour for each environment.Here's the full code snippets based on what we just described!
Project Structure:
Pom.xml:<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>my-sample-app</artifactId> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>11</java.version> </properties> <dependencies> <!-- the basic dependencies as described on the blog --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> <build> <finalName>${build.profile}-${project.version}-app</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <profiles> <!-- Two profiles --> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <spring.profiles.active>dev</spring.profiles.active> <build.profile>dev<build.profile> </properties> </profile> <profile> <id>prod</id> <properties> <spring.profiles.active>prod</spring.profiles.active> <build.profile>prod<build.profile> </properties> </profile> </profiles> </project>
The property files (yml)
application-dev.yml
spring: profiles: active: dev thymeleaf: cache: false prefix: file:src/main/resources/templates/ #directly serve from src folder instead of target resources: static-locations: file:src/main/resources/static/ #directly serve from src folder instead of target cache: period: 0
application-prod.yml (doesn't override anything)
spring: profiles: active: prod
Hope this helps!