SpringMVC JavaConfig and Thymeleaf with Maven

Tech stack used: Spring MVC 4.2.2.RELEASE, Thymeleaf 3.0.0.BETA01, Java 1.8. Refer to project POM for more details.

The Maven project behind this article is publicly available on gitHub so feel free to check it out: https://github.com/gmihaylov840/SpringMVCThymeleafMaven.git

Thymeleaf is a trending web page templating framework that operates in the “View” part of the MVC architecture. It’s capable of processing and generating HTML, XML, JavaScript, CSS, and text which makes it the perfect replacement for dynamic web page generating technologies like JSP, Tiles, etc. Example replacing JSP and Tiles with Thymeleaf can be found here.

One of its distinguished feature is the “natural” setup of its templates. Thymeleaf templates can be viewed in static mode (from browser without running server). That is possible because templates can render HTML that actually have default values when the server data is missing. Needless to say, with Thymeleaf the UI team can start working on web page without server side implementation being ready yet.

Other than that Spring fans will be thrilled to know that Thymeleaf has build in support for Spring MVC, Spring Security, Spring WebFlow support.

There is also expression evaluation with OGNL (Standard), Spring Expression Language (SpringStandard), and Internationalization.

This article aim to cover only basic example project setup and will not examine all Thymeleaf features, which are quite a lot. Yeah, yeah … I know, I know, the web is already full any kinds of basic project setups for this, but this one is worth checking out, because:

  1. It’s all configured with Java annotations, so no extra XML files;
  2. Uses Java 1.8;
  3. Uses Thymeleaf templating framework. Not so many examples out there right now, especially for the new release;
  4. It’s actually working. Anyone who spend hours trying to fork decently working example will know what I mean;

As usual I strongly encourage you to dive into the original documentation and feature list.

And whatever you do, don’t miss the official tutorials on:

Thymeleaf Workflow

Following the Spring MVC diagram above, the workflow will work like this:

  1. Incoming request hist the Front Controller; The Front Controller delegates the request to specific controller (usually based on URL pattern) after consulting mapping settings.
  2. The specific controller calls app APIs to collect needed data for the HTML page and stores that data in a Model object which is then returned to the Front Controller.
  3. The Front Controller will then finally delegate the Model object, template file name, and the response rendering to the appropriate View Resolver class. In our case that will be the ThymeleafeViewResolver and the template file name was passed down from the specific controller. Here is where Thymeleaf magic happens and template file will be filled with data from the Model object.
  4. Once HTML response is rendered control is returned once again to the Front Controller that returns the generated response to the client.

In the context of Spring MVC, Thymeleaf will generate the desired HTML result when the proper View resolver is plugged into Servlet context at app startup and when that resolver is pointing to a Thymeleaf HTML template file, like this one:

Since this operation is still happening on the server side, like JSP, the template file has access to all available business java objects and beans (prod) and their field data (prod.name). All Thymeleaf directives are prefixed with “th:”. This means that Thymeleaf will evaluate the values in the brackets and put them in those HTML tags.

A quick look at this piece of code reveals internationalization expressions (#{…}), variable/model-attribute evaluation expressions (${…}) and even utility functions (#numbers.formatDecimal(…)). It also shows that this fragment of HTML code can be perfectly displayed by a browser as a static prototype, without being executed at all — natural template.

Configuring SpringMVC via JavaConfig

First thing that needs to be done is to setup Spring of course. Thymeleaf will be added later.

The ApplicationConfiguration file is Spring’s starting point that replaces the old XML configuration.

package thymeleaf.mvc.setup;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "thymeleaf.setup", "thymeleaf.mvc.controller" })
public class ApplicationConfiguration {
}

Few things to note here:

  1. The @Configuration annotation tells Spring to use this file as, well… configuration, instead of the regular XML config file;
  2. The @EnableWebMvc is equivalent to <mvc:annotation-driven /> in regular XML config. It enables support for @Controller-annotated classes that use @RequestMapping to map incoming requests to a certain method. More on how to configuring Spring MVC can be found here;
  3. The @ComponentScan annotation is an equivalent for Spring XML’s <context:component-scan/>. It tells Spring where to look for other annotated classes that may represent beans or configurations. More on Spring’s annotation driven configuration here. In this case, Spring find Thymeleaf config and controller at the specified locations;

Next file of interest is the ApplicationInitializer class.

package thymeleaf.mvc.setup;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class ApplicationInitializer implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext container) throws ServletException {

		// Create the 'root' Spring application context
		AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
		rootContext.register(ApplicationConfiguration.class);

		// Manage the life-cycle of the root application context
		container.addListener(new ContextLoaderListener(rootContext));

		// Create the dispatcher servlet's Spring application context
		AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();

		// Register and map the dispatcher servlet
		ServletRegistration.Dynamic dispatcher = container.addServlet(
				"dispatcher", new DispatcherServlet(dispatcherContext));
		dispatcher.setLoadOnStartup(1);
		dispatcher.addMapping("/");
	}

}

It’s onStartup() method defines which configurations will get loaded during web application startup. This is the place where you plug-in all java configurations needed. The configurations are then loaded using AnnotationConfigWebApplicationContext (duhh..) class by registering the already mentioned ApplicationConfiguration class to it using method .register(ApplicationConfiguration.class).

From then on things are pretty straightforward. The servletContainer adds ContextLoaderListener to manage the lifecycle of the root application context. And a DispatcherServlet is added to the container with mapping for root URL (“/”).

Now that there is a DispatcherServlet to handle URLs all this project needs is a Spring MVC controller to further process requests. In this case there is the HelloController class.

package thymeleaf.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/")
public class HelloController {

	@RequestMapping(method = RequestMethod.GET)
	public String printWelcome(ModelMap model) {
		model.addAttribute("title", "Spring MVC with Thymeleaf");
		model.addAttribute("pageHeading", "Spring MVC with Thymeleaf");
		model.addAttribute("imgUrl", "http://www.thymeleaf.org/doc/tutorials/2.1/images/header.png");
		return "index";
	}

}

Two points of interest here:

  1. The @Controller annotation, that defines this class as Spring controller class;
  2. The @RequestMapping annotation on class level tells Spring MVC’s dispatcher servlet which URLs are to be handled by this specific controller;
  3. The @RequestMapping annotation on method level is used to bound single methods to requests based on URL and HTTP request types;

More about Spring MVC acritechture can be found here

Configuring Thymeleaf

Now that Spring MVC is finally set up and working the time has come to add Thymeleaf into the picture. Enter the ThymeleafConfig class.

package thymeleaf.setup;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;

@Configuration
public class ThymeleafConfig {

	@Bean
	public ITemplateResolver templateResolver() {
		SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
		templateResolver.setPrefix( "/WEB-INF/templates/" );
		templateResolver.setSuffix( ".html" );
		templateResolver.setTemplateMode( "HTML5" );

		return templateResolver;
	}

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

	@Bean
	public ViewResolver viewResolver() {
		ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
		viewResolver.setTemplateEngine( templateEngine() );
		viewResolver.setOrder( 1 );

		return viewResolver;
	}

}

Since this is a configuration class it is of course annotated with @Configuration.
Thymeleaf is a HTML templating framework so it need to know where to look for its templates. In this case the method templateResolver() is providing templates location.

Another interesting this here is the use of SpringTemplateEngine class. That class is actually part of Spring integration that Thymeleaf provides out of the box.

And finally, since Spring MVC is working with views resolvers, in order to use Thymeleaf for processing HTTP responses Spring has to have Thymeleaf view resolver. And it does with ThymeleafViewResolver class, which is yet another cool Spring integration feature.

Project Structure

Running the app

That part is easy thanks to Maven. Just issue the following command to Maven “jetty:run” and embedded Jetty server will automatically get deployed and started. To view the example index.html file, open browser and request http://localhost:8080/myApp

Links & Resources

Spring MVC: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html
Thymeleaf Tutorial: http://itutorial.thymeleaf.org
Thymeleaf + Spring Tutorial: http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html
Thymeleaf Interactive Tutorial: http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html
Thymeleaf: http://www.thymeleaf.org
My GitHub repo: https://github.com/gmihaylov840/SpringMVCThymeleaf

Advertisements

2 thoughts on “SpringMVC JavaConfig and Thymeleaf with Maven

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s