Building a simple MVC Application using Spring and Thymeleaf
Tags: java, spring, thymeleaf
Published: 2021-01-13 23:43:58

In this post I am going to build a simple MVC application using Spring , Thymeleaf library. This code is a part of my assignment of my Java BootCamp at http://coderscampus.com/bootcamp .

**Gist of the MVC application :** We are having a text file with some mock data for a bank transactions. We will be storing this in a ArrayList (Mocking a Database) . We will request for the transactions page(http://localhost:8080/transactions) and the web app lists this data . We can check on individual transaction details by clicking on the id of the transaction and end point http://localhost:8080/transactions/{transactionid} will be fetch the details.

**Step 1 :** We will get the initial project setup done using https://start.spring.io/ starter kit. The options that i picked for this project 

**Dependency Management :** Maven
**Language :** Java 11 (Open JDK)
**Spring Boot :**2.4.1
**Packaging :** jar
**Dependencies :**
**Spring Web** - (Since we are building a web application and this comes with built in Tomcat server)
**Spring Boot Dev Tools** - This helps in making changes to html without restarting the server - live server
**Thymeleaf** - We will be working with html and java and this library helps with the interaction.

**Step 2:** We will generate the Spring Boot application using the setup mentioned in the step 1. We will import this project into eclipse as an existing Maven Project.

**Step 3 :** We will get the transactions.txt file and place them in the project folder. So we will be creating a repository class TransactionRepository.java . This class will hold the ArrayList and will return the data requested by the user. In this class we will create a private method to parse the text file and load the ArrayList with the data. The POJO for this transaction data will contain the following fields:

      private Long id;

	private String retailer;

	private String description;

	private LocalDateTime date;

	private BigDecimal amount;

	private String type;
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getRetailer() {
		return retailer;
	}
	public void setRetailer(String retailer) {
		this.retailer = retailer;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public LocalDateTime getDate() {
		return date;
	}
	public void setDate(LocalDateTime date) {
		this.date = date;
	}
	public BigDecimal getAmount() {
		return amount;
	}
	public void setAmount(BigDecimal amount) {
		this.amount = amount;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	@Override
	public String toString() {
		return "Transaction [id=" + id + ", retailer=" + retailer + ", description=" + description + ", date=" + date
				+ ", amount=" + amount + ", type=" + type + "]";
	}
	 

**Step 4 :** We will next create a Transaction Service and Transaction Controller classes. The TransactionController.java will be a plain Controller(Java class with @Controller annotation) which will be listening to the incoming requests. TransactionService.java (Java class with @Service annotation)will route the request from the Controller to the Repository class. The best practice is always have Controller, Service and Repository classes separately.

**Step 5:** We will create get mapping for /transactions endpoint. The getAllTransactions method will call the TransactionService which in turn load the data into the List.  This list of transactions will be put into ModelMap( hashMap which will hold keys and values which can be accessed in the html page or view ) and returns a string which is basically the name of the html page.

**Step 6 :** We will create a transaction.html file (src->main->resources->templates) . Initially we will just create a basic html page with the welcome note. The name of the html should be same as the string returned from the TransactionController.java.

```
package com.assignment11.BankTxnViewer.web;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import com.assignment11.BankTxnViewer.domain.Transaction;
import com.assignment11.BankTxnViewer.repository.TransactionRepository;
import com.assignment11.BankTxnViewer.service.TransactionService;

@Controller
public class TransactionsController {
	
	@Autowired
	private TransactionService txnService;
	
	@GetMapping("/transactions")
	public String getAllTransactions(ModelMap map) {
		
		List<Transaction> txnList = txnService.getAllTransactions();
		System.out.println(txnList.get(1).getType());
		map.put("transactions", txnList);
		
		
		return "transaction";
	}
	
	@GetMapping("/transactions/{transactionId}")
	public String getTransactionById(@PathVariable Long transactionId, ModelMap map) {
		
		Transaction txnRecord = txnService.getTransactionById(transactionId );
		
		
		
		map.put("transaction", txnRecord);
		
		
		return "transaction_detail";
	}

}

```  

**Step 7:** We will build the application and run it . We will check for endpoint http://localhost:8080/transactions. We should be able to see the Welcome note from the html page.
**Common Gotchas :** 
1. If you are unable see the html page welcome note. Please check if thymeleaf dependency is added to the pom.xml.
2. If you need to make changes to just the html file and not keep restarting the server, then we can add a property to the application properties file . spring.thymeleaf.cache = false. Some times just adding this property works but some times we need to add the dev tools dependency in the pom.xml.


**Step 8:** Now we need to populate the data from the list into the html page. We need to access the java objects from html . This is possible with Thymeleaf library. We need to include the thymeleaf namespace in the html tag.

```
<html xmlns:th="http://thymeleaf.org"> 
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
<title>Transaction History</title>
<style>
tr:nth-child(even) {
  background-color: #dddddd;
}
</style>
</head>
<body>
    <h1>Transaction History</h1>
    
    <table style="width:50%">
     <tr style="background-color:black; color:white;">
      <th>ID</th>
       <th>Date</th>
        <th>Retailer</th>
         <th>Funds In</th>
          <th>Funds Out</th>
        </tr>
        
        <tr th:each="txn:${transactions}" >
          <td th:inline="text">
          <a th:href="@{/transactions/{transactionId}(transactionId=${txn.id})}">[[${txn.id}]]</a>
          </td>
           <td th:inline="text">[[${txn.date}]]</td>
            <td th:inline="text">[[${txn.retailer}]]</td>
          
            <td>
               <th:block th:if="${txn.type == 'C'}" th:inline="text">[[${txn.amount}]]</th:block>
            </td>
            
              <td>
               <th:block th:if="${txn.type == 'D'}" th:inline="text">[[${txn.amount}]]</th:block>
            </td>
            
        </tr>
     
    </table>
  
</body>
</html>
```

**Step 9:** Once we have the namespace defined we can access the java objects inside the html tags coupled with the namespace prefix using Spring expression language.

**Step 10:** In the html we will be using th:each to loop through the list of data and display each of them on the web page. Based on the type of the transactions we will display of the transaction is a debit or credit type. We will use th:if to do the conditional statement.

**Step 11:** We will providing hyperlinks on the ID of the transactions and when the user clicks on this we th:href to provide a link with the id as a parameter. We will hit the  /transactions/{transactionid} end point.

**Step 12 :** When /transactions/{transactionid} end point is hit we will fetch the detail of the transaction. This detail will be populated on a new html.

**Github link to Code :** https://github.com/santhoshima10/Java_Bootcamp/tree/main/Assignment11