Quick Guide to Spring MVC with Velocity

1. Introduction

Velocity is a template engine from the Apache Software Foundation that can work with normal text files, SQL, XML, Java code and many other types.

In this article we’re going to focus on utilizing Velocity with a typical Spring MVC web application.

2. Maven Dependencies

Let’s start by enabling the Velocity support – with the following dependencies:

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>
        
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-tools</artifactId>
    <version>2.0</version>
</dependency>

The newest versions of both can be found here: velocity and velocity-tools.

3. Configuration

3.1. Web Config

If we don’t want to use an web.xml, let’s configure our web project using Java and an initializer:

public class MainWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
        root.register(WebConfig.class);

        sc.addListener(new ContextLoaderListener(root));

        ServletRegistration.Dynamic appServlet = 
          sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext()));
        appServlet.setLoadOnStartup(1);
    }
}

Alternatively, we can of course use the traditional web.xml:

<web-app ...>
    <display-name>Spring MVC Velocity</display-name>
    <servlet>
        <servlet-name>mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-servlet.xml</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
    <url-pattern>/*</url-pattern>
    </servlet-mapping>
 
    <context-param>
        <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Notice that we mapped our servlet on the “/*” path.

3.2. Spring Config

Let’s now go over a simple Spring configuration – again, starting with Java:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {
  "com.maixuanviet.mvc.velocity.controller",
  "com.maixuanviet.mvc.velocity.service" }) 
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
          .addResourceHandler("/resources/**")
          .addResourceLocations("/resources/");
    }
 
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public ViewResolver viewResolver() {
        VelocityLayoutViewResolver bean = new VelocityLayoutViewResolver();
        bean.setCache(true);
        bean.setPrefix("/WEB-INF/views/");
        bean.setLayoutUrl("/WEB-INF/layouts/layout.vm");
        bean.setSuffix(".vm");
        return bean;
    }
    
    @Bean
    public VelocityConfigurer velocityConfig() {
        VelocityConfigurer velocityConfigurer = new VelocityConfigurer();
        velocityConfigurer.setResourceLoaderPath("/");
        return velocityConfigurer;
    }
}

And let’s also have a quick look at the XML version of the configuration:

<beans ...>
    <context:component-scan base-package="com.maixuanviet.mvc.velocity.*" />
    <context:annotation-config /> 
    <bean id="velocityConfig" 
      class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath">
            <value>/</value>
        </property>
    </bean> 
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
        <property name="cache" value="true" />
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="layoutUrl" value="/WEB-INF/layouts/layout.vm" />
        <property name="suffix" value=".vm" />
    </bean>
</beans>

Here we are telling Spring where to look for annotated bean definitions:

<context:component-scan base-package="com.maixuanviet.mvc.velocity.*" />

We are indicating we are going to use annotation-driven configuration in our project with the following line:

<context:annotation-config />

By creating “velocityConfig” and “viewResolver” beans we are telling VelocityConfigurer where to look for templates, and VelocityLayoutViewResolver where to find views and layouts.

4. Velocity Templates

Finally, let’s create our templates – starting with a common header:

<div style="...">
    <div style="float: left">
        <h1>Our tutorials</h1>
    </div>
</div>

and footer:

<div style="...">
    @Copyright maixuanviet.com
</div>

And let’s define a common layout for our site where we are going to use above fragments with parse in the following code:

<html>
    <head>
        <title>Spring & Velocity</title>  
    </head>
    <body>
        <div>
            #parse("/WEB-INF/fragments/header.vm")
        </div>  
        <div>
            <!-- View index.vm is inserted here -->
            $screen_content
        </div>  
        <div>
            #parse("/WEB-INF/fragments/footer.vm")
        </div>
    </body>
</html>

You can check that $screen_content variable has the content of the pages.

Finally, we’ll create a template for the main content:

<h1>Index</h1>
 
<h2>Tutorials list</h2>
<table border="1">
    <tr>
        <th>Tutorial Id</th>
        <th>Tutorial Title</th>
        <th>Tutorial Description</th>
        <th>Tutorial Author</th>
    </tr>
    #foreach($tut in $tutorials)
    <tr>
        <td>$tut.tutId</td>
        <td>$tut.title</td>
        <td>$tut.description</td>
        <td>$tut.author</td>
    </tr>
    #end
</table>

5. Controller Side

We have created a simple controller which returns a list of tutorials as content for our layout to be populated with:

@Controller
@RequestMapping("/")
public class MainController {
 
    @Autowired
    private ITutorialsService tutService;

    @RequestMapping(value ="/", method = RequestMethod.GET)
    public String defaultPage() {
        return "index";
    }

    @RequestMapping(value ="/list", method = RequestMethod.GET)
    public String listTutorialsPage(Model model) { 
        List<Tutorial> list = tutService.listTutorials();
        model.addAttribute("tutorials", list);
        return "index";
    }
}

Finally, we can access this simple example locally – for example at: localhost:8080/spring-mvc-velocity/

6. Conclusion

In this simple tutorial, we have configured Spring MVC web application with Velocity template engine.

The full sample code for this tutorial can be found in our GitHub repository.

Related posts:

Một số ký tự đặc biệt trong Java
Java – Convert File to InputStream
Concrete Class in Java
Bootstrap a Web Application with Spring 5
A Guide to Spring Cloud Netflix – Hystrix
Java Program to Implement Graham Scan Algorithm to Find the Convex Hull
Java Program to Implement the Hill Cypher
Quick Guide to Spring Controllers
Introduction to Spring MVC HandlerInterceptor
Spring Boot - Tomcat Port Number
Spring MVC Tutorial
Validate email address exists or not by Java Code
Java Program to Implement Hamiltonian Cycle Algorithm
Hướng dẫn sử dụng Java String, StringBuffer và StringBuilder
Java Program to find the maximum subarray sum O(n^2) time(naive method)
Java Program to Implement Horner Algorithm
Spring REST API + OAuth2 + Angular (using the Spring Security OAuth legacy stack)
Java Program to Implement the Vigenere Cypher
Jackson – JsonMappingException (No serializer found for class)
Vấn đề Nhà sản xuất (Producer) – Người tiêu dùng (Consumer) và đồng bộ hóa các luồng trong Java
Spring Boot: Customize Whitelabel Error Page
Get and Post Lists of Objects with RestTemplate
Java Program to Find Hamiltonian Cycle in an UnWeighted Graph
Spring WebClient and OAuth2 Support
Java Program to Implement Dijkstra’s Algorithm using Priority Queue
Tính đóng gói (Encapsulation) trong java
Lập trình mạng với java
Java Program to Implement Fermat Primality Test Algorithm
Java Program to Implement VList
CyclicBarrier in Java
Spring Boot - Sending Email
Sắp xếp trong Java 8