1. Introduction to Thymeleaf (Video)
In this walk-through, we would build an application to store student records. Users would be able to:
- access list of students in html page
- add new student
- update student
- delete student
We would learn the following technologies:
- Springboot
- JPA Repository
- H2 In-Memory Database
- Thymeleaf
- Javascript, Bootstrap and JQuery
- and more!
What is Thymeleaf? Thymeleaf is a server side template engine for processing pages (HTML5, XML, XHTML)
Thing to install:
MySQL – The free community edition can be gotten from here
Spring Tool Suite – download for free from here
2. Project Setup in Spring Initializr (Video)
Goto start.spring.io and create a project. Use the following settings:
- Project: Maven Project
- Language: Java
- Spring Boot: 2.1.6
- Group: com.kindsonthegenius (you can change this )
- Artifact: thymeleaf-app
- Name: thymeleaf-app
- Description: Thymeleaf Application
- Package Name: com.kindsonthegenius.thymeleaf-app
- Packaging: Jar
- Java: 8
Add the following dependencies: H2 Database, MySql Driver, Spring Data JPA, Thymeleaf, Spring web starter
Generated the project. So the the project is downloaded as as zip file
Unzip the file and open it in Spring Tool Suite
3. Add Additional Dependencies (Video)
Open the pom.xml file to ensure the dependencies are specified
Add the following additional dependencies:
- spring-web
- spring-context
- Bootstrap (4.3.1)
- JQuery (3.4.1)
This dependencies are gotten from Maven Repository
Remove the versions tag from spring-web and spring-context
Save the project
The general architecture or our application is given below
4. Create a html and Test Thymeleaf (Video)
Create a class called HomeController in the com.kindsonthegenius.thymeleafapp package
Annotate this class with the @Controller annotation
Write a String method called test to return “index”.
Annotate this method with @RequestMapping(“/home”)
The content of the HomeController.java file is as shown below
@Controller public class HomeController { @RequestMapping("/home") public String test() { return "index"; } }
Create a html file inside the templates folder. The templates folder is inside the src/main/resources folder.
The content of the html file is as shown below
Run the application
Then visit http://localhost:8080/home and ensure the page displays
5. Setup and test H2 Database (Video)
Open the application.properties file and add the following directives
spring.h2.console.enabled=true spring.datasource.platform=h2 spring.datasource.url=jdbc:h2:mem:studentdb spring.jpa.hibernate.ddl-auto=update
Run the application
Then visit http://localhost:8080/h2-console
Ensure the name of the database is studentdb
Then click on connect. You will now see the h2-console open up.
6. Setup MySQL Database (Video)
Open the application.properties file again
Add the following code to configure MySQL datasource
Note the the datasource configuration for H2 database has been commented out. This is because you can have two datasources at the same time
#H2 Database Configuration #spring.h2.console.enabled=true #spring.datasource.platform=h2 #spring.datasource.url=jdbc:h2:mem:studentdb #spring.jpa.hibernate.ddl-auto=update #MySQL Database Configuration spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.password=root spring.datasource.username=root spring.datasource.url=jdbc:mysql://localhost:3307/student spring.jpa.hibernate.ddl-auto=update spring.datasource.initialization-mode=always #if you receive Timezone error, then replace the datasource url with the one below #spring.datasource.url=jdbc:mysql://localhost:3301/student?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
7. Create the Model (the Student class) (Video)
Create a class called Student in the models package
The class should have the following member variables:
- Id (Integer)
- name (String)
- department (String)
- updatedBy (String)
- updatedOn (Date
Annotate the class with the @Entity annotion
Annotate the Id field with the @Id annotation
Annotate the updatedOn field with the @DataTimeFormat(pattern=”yyyy-MM-dd”) annotation
The class would be as shown below
@Entity public class Student { @Id private Integer Id; private String name; private String department; private String updatedBy; @DateTimeFormat(pattern="yyyy-MM-dd") private String updatedOn; }
Generated the constructors, getter and setters and the toString method
8. Write and Test Database Initialization Query (Video)
Create a file called data.sql in the src/main/resources folder
Write a query the insert some initial data. The content of the file would be as shown below;
insert into student values(1, 'Kindson Munonye', 'Computer Science', 'The Tech Pro', '2019-06-27'); insert into student values(2, 'Kate Winston', 'Managment', 'The Tech Pro', '2019-06-27'); insert into student values(3, 'Solace Okeke', 'Data Science', 'The Tech Pro', '2019-06-27');
Now, test the application.
First, check that the the Student table is created in the mySQL server and the data is inserted
Next, do the same for the H2 database
Remember to modify the application.properties file before you test each of the databases;
9. Create the Crude Repository (Video)
Create an interface called StudentRepository in the repositories folder
Make this interface extend CrudRepository
Specify the class and Id type as Student and Integer respectively
Annotate the class with the @Repository annotation
10. Create the Business Service (Video)
Create a class called StudentService in the services folder
Annotate this class with the @Service annotation
Autowire the StudentRepository into the StudentService
11. Create the Controller (Video)
Create a class called StudentController
Annotate the class with the @Controller annotation
Annotate this class with the @RequestMapping(“/students”)
Autowire the StudentService into the StudentController
12. Write the getAll() Method (Video)
In the StudentService, write a GetAll method . This method should call the findAll() method of the repository.
This method should return a List<Student>
In the StudentController, write the getAll method. This method should call the getAll method of the service
Annotate this method with @RequestMapping(“/getAll”)
This method should return a string of “students”
The code is shown below
@RequestMapping("/getAll") public String getAll(Model model) { List<Student> students = studentService.getAll(); model.addAttribute("students", students); return "students"; }
13. Setup and test the html page (Video)
To ensure that that StudentController can serve a page using Thymeleaf;
Create a html page in the templates folder and call it students.html
Write some text in the page.
The go ahead to run the application.
Navigate to http://localhost:8080/students/getAll. Confirm that the html page display
Optional: Change the @Controller annotation to @RestController. Also modify the function to return List<Student>. Then test if it actually return the data.
14. Setup Bootstrap and JQuery (Video)
In the html page, include in the header section:
- the link to bootstrap.css
- jquery.js script
- bootstrap.js script
For me, it is as shown below:
<link href="/webjars/bootstrap/4.3.1/css/bootstrap.css" rel="stylesheet" /> <script type="text/javascript" src="/webjars/bootstrap/4.3.1/js/bootstrap.min.js"></script> <script type="text/javascript" src="/webjars/jquery/3.4.1/jquery.min.js"></script>
Create a simple table and test it using table table-stripped class
Note: if the link and script doesn’t work, try using the CDN links from the website
15. Send data from Controller to View (Video)
Modify the getAll method in the controller, add a model object as parameter
Now call the service to return a list of students.
Then assign this list as an attribute to the model object. In this way, this list would be available in the view.
The method would then be as shown below:
@RequestMapping("/getAll") public String getAll(Model model) { List<Student> students = studentService.getAll(); model.addAttribute("students", students); return "students"; }
16. Receive data in the View (html page) (Video)
Modify the table in the html page to have five columns and two rows.
Then add the Thymeleaf markup to display the data from the models.
The final table would be as shown below
<table class="table table-stripped"> <thead> <tr> <td>Id</td> <td>Name</td> <td>Department</td> <td>Updated By</td> <td>Updated On</td> </tr> </thead> <tr th:each="student:${students}"> <td th:text="${student.Id}">Id</td> <td th:text="${student.name}">Name</td> <td th:text="${student.department}">Department</td> <td th:text="${student.updatedBy}">Updated By</td> <td th:text="${student.updatedOn}">Updated On</td> </tr> </table>
Run the application and check that the data is displayed in the page
17. Write and test the getOne() method (Video)
In the Service class, write a the method getOne() to return a single record.
In the Controller class, write the method getOne()
It is going to return a single Student. Also, it would take an Integer parameter, Id.
Annotate this method with @RequestMapping(“/getOne”)
At the the, the getOne method in the controller would look like this:
@RequestMapping("/getOne") @ResponseBody public Optional<Student> getOne(Integer Id) { return studentService.getOne(Id); }
18. Write the addNew Method (Video)
In the StudentService, write the addNew method.
This method would take a Student object and save it to the repository.
In the StudentController, writhe the addNew method
Annotate the method with the @RequestMapping(value=”/addNew” method=”post”)
@PostMapping(value="/addNew") public String addNew(Student student) { studentService.addNew(student); return "redirect:/students/getAll"; }
Note: there is not spaces in the redirect statement!
19. Set up the AddModal Dialog (Video)
The easiest way to do this is to go to the Bootstrap website and get a modal form template. Copy and add the code to the students.html page.
Copy the code for the button as well
Move the form tag to the uppermost level div tag!
Modify the name and text in the add button.
Then modify the form to add the textfields.
Change the Ids of the textfield to something relevant.
Test the application to see the appearance
20. Complete and Test the Insert operation (Video)
Give the textfields name attributes that corresponds to the name used in the model.
Change the type of button for the Save operation from “button” to “submit”
Set the th:action of the form to @”{/students/addNew}”.
Set the method to post
Test the application and try to insert data into the database. If it works, congrats!
If not, watch the video and leave me a comment to let me know so I can help you.
21. Write the Update Methods (Video)
In the Student Service, write the update method. This method should call the save() method of the repository.
Also, in the Controller, write the update method.
This method take a single parameter of Student.
Annotates this method with @RequestMapping…….
It returns a redirect to the students/findAll url
The final update() method for the controller is shown below
@RequestMapping(value="/update", method = {RequestMethod.PUT, RequestMethod.GET}) public String update(Student student) { studentService.update(student); return "redirect:/students/getAll"; }
22. Setup the Edit Modal (Video)
The easiest way to do this is to make a copy of the existing addModal. Then change the name to editModal
Change the names of the textfields to something relevant
Set the action of the editModal like this – th:action = “@{/students/update}”
Now, in the table, add a sixth column and name it Edit.
Then add a button and set its data-target attribute to #editModal (we would later change it to a link)
Set the class of this button to “btn btn-warning”
Test the application to ensure that the modal displays
Then change the button to an anchor tag
23. Create the Custom js File (Video)
Now, if you test the application, you will see that nothing happens when we click on the Edit button. We would write a custom script that runs when the button is clicked.
Inside the static folder of the src/main/resources, create a folder js.
Then create a file called main.js.
In the students.html page, add a link to this file in the head section. The link would be as follows:
<script type="text/javascript" src="../static/js/main.js" th:src="@{/js/main.js}"></script>
Note: Make sure to get this right!
Inside this file, write a function to display the editModal. The file would be as follows:
$('document').ready(function(){ $('.table #editButton').on('click',function(event){ event.preventDefault(); $('#editModal').modal(); }); });
Note: no space between ‘click’ and function
Note: the event.preventDefault() stops the link from navigating to a response page. Try to remove it an rerun the application so you understand how it works.
Then test the application and ensure the editModal form displays
24. Complete and Test the Edit Method (Video)
Two things should when the editButton is clicked:
- request is sent to /students/getOne?Id={Id} to retrieve a particular record
- the values retrieved are assigned to the edit text fields
Add the href attribute to the editButton. The attribute is as shown below:
th:href="@{/students/getOne/(Id=${student.Id})}"
Now modify the main.js file. Write the codes to assign the values of the student record to the textfields. At the end the final code would be:
25. Write the Delete Method (Video)
Write the delete method in the studentService.
Also write the delete method in the StudentController file
The delete method would take on parameter which is the Id of record to be deleted.
The delete() method is shown below:
@RequestMapping(value="/delete", method = {RequestMethod.DELETE, RequestMethod.GET}) public String delete(Integer Id) { studentService.delete(Id); return "redirect:/students/getAll"; }
26. Setup the Delete Modal (Video)
Now that the add and update is working well, I’l say congrats to you!
To add the delete we would a modal from the bootstrap website.
Place the modal in the page and give it an id of deleteModal
Change the texts on it to something relevant.
Change button to an anchor tag and add the href set to “”
Add a delete link in the table just like the Edit link, but this time to the /delete endpoint
Modify the main.js file to display the deleteModal
Test the application and check that the modal displays.
27. Complete and Test the Delete Modal (Video)
Now give the button in the deleteModal an id of delRef
In the main.js file, write the code to complete the delete operation
The js code for the deleteButton is shown below:
$('.table #deleteButton').on('click',function(event){ event.preventDefault(); var href = $(this).attr('href'); $('#deleteModal #delRef').attr('href', href); $('#deleteModal').modal(); });
Test the application to make sure it works.
28. Display Logged In Username with Thymeleaf (Video)
User authentication and authorization are covered under spring security. I’m currently working on the tutorials on Spring Security and would publish it in the next few day.
For now, the easiest way to pass the logged in user details to the view is to place it in the model. This can be done in the getAll function since that is the only page we are working with.
Just write this one line of code in the getAll() method:
String username = "Kindson"; model.addAttribute("username", username);
Then in the students.html page, you can retrieve the value using the code below:
Welcome, <span th:text="${username}">Welcome guest!
29. Using BootStrap for UI
(Only Video!)
can you the code share?
Sure. You are free to clone it.
https://github.com/KindsonTheGenius/ThymeleafApp
thank you Mr I never forget your help by sharing this videos tutorial
Thanks Gral for being there for me!
I don’t find any video here, can u pls share the video or advice how can i find those
Oh…sorry I forgot to add. I have updated the link now. So you can check now
You can also go directly to the videos here https://www.youtube.com/playlist?list=PL9l1zUfnZkZnEqlZLA_GI8vySZCZ7EBk9
Sir thank you for the tutorials but please help my form is not displaying when adding the modal i included jquery before bootstrap still its not working…..Any help?