Search code examples
springfreemarker

Spring Boot and FreeMarker


I'm trying to work through a simple example of Spring Boot and FreeMarker integration (based on tutorials I've found on the web). For some reason my view is not being resolved to the FreeMarker template (I think that's the issue).

The result when launched in a browser is simply to return the name of the TFL view file i.e. "index". So the controller is being called and returning the string "index", but there seems to be no trigger to pull in the FTL file itself. Any help would be appreciated...

I have the following configuration class where I define the view resolver and the Free Maker config.

@Configuration
public class MvcConfigurer extends WebMvcConfigurerAdapter {
    @Bean
    public ViewResolver viewResolver() {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
        resolver.setCache(true);
        resolver.setPrefix("");
        resolver.setSuffix(".ftl");
        resolver.setContentType("text/html; charset=UTF-8");
        return resolver;
    }

    @Bean
    public FreeMarkerConfigurer freemarkerConfig() throws IOException, TemplateException {
        FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();
        factory.setTemplateLoaderPaths("classpath:templates", "src/main/resource/templates");
        factory.setDefaultEncoding("UTF-8");
        FreeMarkerConfigurer result = new FreeMarkerConfigurer();
        result.setConfiguration(factory.createConfiguration());
        return result;
    }
}

Then I have the following controller:

@RestController
public class HelloController {

    /**
     * Static list of users to simulate Database
     */
    private static List<User> userList = new ArrayList<User>();

    //Initialize the list with some data for index screen
    static {
        userList.add(new User("Bill", "Gates"));
        userList.add(new User("Steve", "Jobs"));
        userList.add(new User("Larry", "Page"));
        userList.add(new User("Sergey", "Brin"));
        userList.add(new User("Larry", "Ellison"));
    }

    /**
     * Saves the static list of users in model and renders it 
     * via freemarker template.
     * 
     * @param model 
     * @return The index view (FTL)
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(@ModelAttribute("model") ModelMap model) {

        model.addAttribute("userList", userList);

        return "index";
    }

    /**
     * Add a new user into static user lists and display the 
     * same into FTL via redirect 
     * 
     * @param user
     * @return Redirect to /index page to display user list
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String add(@ModelAttribute("user") User user) {

        if (null != user && null != user.getFirstname()
                && null != user.getLastname() && !user.getFirstname().isEmpty()
                && !user.getLastname().isEmpty()) {

            synchronized (userList) {
                userList.add(user);
            }
        }
        return "redirect:index.html";
    }
}

Then finally I have the following FTL file stored in "src/main/resource/templates"

<html>
<head><title>ViralPatel.net - FreeMarker Spring MVC Hello World</title>
<body>
<div id="header">
<H2>
    <a href="http://viralpatel.net"><img height="37" width="236" border="0px" src="http://viralpatel.net/blogs/wp-content/themes/vp/images/logo.png" align="left"/></a>
    FreeMarker Spring MVC Hello World
</H2>
</div>

<div id="content">

  <fieldset>
    <legend>Add User</legend>
  <form name="user" action="add.html" method="post">
    Firstname: <input type="text" name="firstname" /> <br/>
    Lastname: <input type="text" name="lastname" />   <br/>
    <input type="submit" value="   Save   " />
  </form>
  </fieldset>
  <br/>
  <table class="datatable">
    <tr>
        <th>Firstname</th>  <th>Lastname</th>
    </tr>
    <#list model["userList"] as user>
    <tr>
        <td>${user.firstname}</td> <td>${user.lastname}</td>
    </tr>
    </#list>
  </table>

</div>  
</body>
</html> 

Solution

  • The problem is that your controller has the wrong annotation. You should use @Controller instead of @RestController

    @RestController is used to tell that the response sent from your controller should be sent to the browser, usually an object mapped to json. It is the same as adding @ResponseBody.