Question

I have a project where data from several sources are being processed into some data structures. After the program is done building these structures, I want it to set up a server that enables users to fine-tune these structures manually. I decided that Spring MVC on an embedded Tomcat server set up using Spring Boot is just what I need.

I want to use Thymeleaf as view technology, and therefore did

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Main {

    public static void main(String... args) throws Exception {
        // Lots of initialization ...

        SpringApplication.run(Main.class, args);
    }

    @Bean
    public ServletContextTemplateResolver templateResolver() {
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setPrefix("/resources/views/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("HTML5");
        resolver.setCacheable(false);
        return resolver;

    }

    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver());
        return engine;
    }

    @Bean
    public ViewResolver viewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        viewResolver.setOrder(1);
        viewResolver.setViewNames(new String[]{"*"});
        viewResolver.setCache(false);
        return viewResolver;
    }
}

and

@Controller
public class WebController {
    @RequestMapping(value="/greeting", method=RequestMethod.GET)
    public String greeting() {
        return "greeting";
    }
}

But even though there is a view file at /resources/views/greeting.html, the server's reply to the URL http://localhost:8080/greeting is

org.thymeleaf.exceptions.TemplateInputException: Error resolving template "greeting", template might not exist or might not be accessible by any of the configured Template Resolvers

After stepping through the code in a debugger it appears that at some point, ServletContext, which is supposed to return the view file as a stream, looks in a temporary folder like

C:\Users\Michael\AppData\Local\Temp\tomcat-docbase.971027024999448548.8080

which is empty.

Now I get that I need to either

  1. Have the resources deployed to the temporary folder when the server starts up

  2. Have the server operate in the directory where the resources already are

My problem just is that I don't know how to do either, or which approach is the best. Something tells me that 1 is the better wisdom, but any suggestion is welcome.

Edit

Ok, I ended up with something that seems to work. While Joe's answer definitely helped me get on the way, it also appears that I had to change my Maven configuration in a way that puzzles me.

After putting the template greeting.html into /resources/templates/greeting.html and adding resources to the build path, I got the error

javax.servlet.ServletException: Circular view path [greeting]: would dispatch back to the current handler URL [/word/greeting] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)

In other words, Thymeleaf seemed to not be properly configured. After some fiddling I ended up changing the version of spring-boot-starter-parent in pom.xml from 0.5.0.BUILD-SNAPSHOT to 0.5.0.M6:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <!--<version>0.5.0.BUILD-SNAPSHOT</version>-->
    <version>0.5.0.M6</version>
</parent>

and removing the version tag from the Thymeleaf dependency

<dependencies>
    <!-- ... -->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring3</artifactId>
        <!--<version>${thymeleaf-spring3-version}</version>-->
    </dependency>
</dependencies>

After this, it worked.

Can someone please explain why I needed to change the version of spring-boot-starter-parent to be able to remove the version tag from thymeleaf-spring3, and why that was necessary?

Was it helpful?

Solution

The servlet context root is not the best place for templates in an embedded server. There is a way to do it, but if I were you I would go with the flow and use the classpath. If you allow Spring Boot to configure the template resolver (also recommended) then it will look in classpath:/templates by default. There are several samples that use thymeleaf in the Boot code base, so it should be easy to modify one of those if you have different requirements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top