6
votes

I have an app which is a simplified version of the Spring Bookmark tutorial. In it, Controllers are annotated with @RestController and the app only returns JSON.

I've added to mine the ability to return HTML via Thymeleaf templates. My templates are being returned, but they don't seem to be processed by Thymeleaf. I'm using spring-boot, and I've spring-boot-starter-thymeleaf to my build.gradle file, but that doesn't seem to be enough.

For example, here's a simple controller for the root:

package com.latencyzero.hoa;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;



@Controller
@RequestMapping("/")
class
MainController
{
    @RequestMapping(method = RequestMethod.GET)
    ModelAndView
    index()
    {
        ModelAndView mav = new ModelAndView("index");
        mav.addObject("version", "0.1");
        return mav;
    }
}

and src/main/resources/templates/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>HOA v${version}</title>
</head>
<body>
<h1>HOA v${version}</h1>
</body>
</html>

Results in the following page being rendered:

enter image description here

The examples I've found suggest this is all I need to do, but it's not working. Do I need some additional configuration annotations somewhere?

Thanks.

2
@RestController will not work you need a @Controller for that.M. Deinum
From the docs, a @RestController is just a @Controller with @ResponseBody. Nevertheless, it doesn't work with @Controller, either.Rick
Correct. Which means that EVERY methods return value will be marshaller and not passed on to the view resolution mechanism. Add a controller to your question and some configuration...M. Deinum
It does exactly what you told it to do. That is not the way to replace / use EL. You will need to use th:text you cannot (afaik) use inline variables with thyme leaf.M. Deinum
@Rick you can use <th:block th:text="${smth}" /> to avoid extra span element. Or if you use thymeleaf 3 you can use inline text thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#inliningdestan

2 Answers

8
votes

These are the 2 options based on Thymeleaf Tutorials

Inlining Expression

- MainController.java

package com.latencyzero.hoa;

import org.springframework.stereotype.Controller;    
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/")
class MainController
{
    @RequestMapping(method = RequestMethod.GET)
    ModelAndView
    index()
    {
        ModelAndView mav = new ModelAndView("index");
        mav.addObject("version", "0.1");
        return mav;
    }
}


- index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8"/>
    <title>HOA v[[${version}]]</title>
</head>
<body>
<h1>HOA v[[${version}]]</h1>
</body>
</html>

Natural Template

- MainController.java

package com.latencyzero.hoa;

import org.springframework.stereotype.Controller;    
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/")
class MainController
{
    @RequestMapping(method = RequestMethod.GET)
    ModelAndView
    index()
    {
        ModelAndView mav = new ModelAndView("index");
        mav.addObject("hoa_version", "HOA v0.1");
        return mav;
    }
}


- index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8"/>
    <title th:text="${hoa_version}">Default Title</title>
</head>
<body>
<h1 th:text="${hoa_version}">Default Header</h1>
</body>
</html>
8
votes

I had faced the similar problem with the @RestController when I replaced it with @Controller it worked as expected.