Employee Management System (EMS) is a web-based application developed using Spring Boot that helps organizations manage employee records efficiently. It provides features such as adding, updating, viewing, and deleting employee details while integrating MongoDB for data storage and Thymeleaf for dynamic UI rendering.
- Employs Bootstrap for a responsive and modern UI.
- Generates unique Employee IDs automatically.
- Provides confirmation before deleting all employee records.
Prerequisites
- Spring Boot and Spring MVC
- Thymeleaf for dynamic HTML rendering
- MongoDB for data storage
- Bootstrap for responsive UI
Employee Data Fields
Each employee record contains:
- Employee ID (auto-generated)
- Employee Name
- Employee Email
- Employee Phone Number
- Employee Gender
- Employee Salary
- Employee Role
Project Setup
Dependencies (build.gradle)
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Project Structure:

Database Configuration
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=emsspring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
Model Layer
Employee.java
package com.ems.app.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "employee")
public class Employee {
@Id
private String id;
private String employeeName;
private String employeeEmail;
private Long employeePhone;
private String employeeGender;
private String employeeSalary;
private String employeeRole;
}
Annotations:
- @Data: generates getters, setters, equals, hashCode, and toString
- @AllArgsConstructor: parameterized constructor
- @NoArgsConstructor: default constructor
- @Document: maps class to MongoDB collection
ConfirmationForm.java
Used for confirming deletion of all employees
package com.ems.app.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConfirmationForm {
private String confirmation;
}
Repository Layer
EmployeeRepo.java:
package com.ems.app.repo;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import com.ems.app.pojo.Employee;
@Repository
public interface EmployeeRepo extends MongoRepository<Employee, String>{ }
The repository extends MongoRepository providing CRUD operations for Employee.
Controller Layer
EmployeeController.java: handles HTTP requests and integrates the repository with Thymeleaf views:
@Controller
public class EmployeeController {
@Autowired
private EmployeeRepo employeeRepo;
@GetMapping("/")
public String home(Model model) {
model.addAttribute("employee", new Employee());
model.addAttribute("employees", employeeRepo.findAll());
model.addAttribute("confirmationForm", new ConfirmationForm());
return "index";
}
@PostMapping("/create")
public String newEmployee(Employee employee, Model model) {
String empId = "EMP" + (1000 + new Random().nextInt(9000));
employee.setId(empId);
employeeRepo.save(employee);
return "redirect:/";
}
@PostMapping("/update")
public String updateEmployee(@ModelAttribute Employee employee, Model model) {
Optional<Employee> existingEmployee =
employeeRepo.findById(employee.getId());
if(existingEmployee.isPresent()) {
employeeRepo.save(employee);
}
return "redirect:/";
}
@PostMapping("/remove")
public String removeEmployee(Employee employee, Model model) {
Optional<Employee> existingEmployee =
employeeRepo.findById(employee.getId());
if(existingEmployee.isPresent()) {
employeeRepo.deleteById(employee.getId());
}
return "redirect:/";
}
@PostMapping("/remove/all")
public String removeAll(
@ModelAttribute ConfirmationForm confirmationForm,
Model model) {
if("Yes".equalsIgnoreCase(
confirmationForm.getConfirmation())) {
employeeRepo.deleteAll();
}
return "redirect:/";
}
}
View Layer (index.html)
The index.html file uses Thymeleaf and Bootstrap to render employee data and forms for CRUD operations. The page includes:
- Table to display all employees
- Modal forms to add, update, delete single employee
- Modal form to delete all employees after typing “Yes”
Adding Employee Modal:
<div class="modal fade" id="exampleModalToggle1" aria-hidden="true" aria-labelledby="exampleModalToggleLabel" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<form class="p-2" th:action="@{/create}" th:object="${employee}" method="post">
<h4 class="text-center">Add Employee</h4>
<div class="row p-2">
<label>Employee Name</label>
<input type="text" th:field="*{employeeName}" class="form-control" placeholder="employee name" required>
</div>
<div class="row p-2">
<label>Email</label>
<input type="text" th:field="*{employeeEmail}" class="form-control" placeholder="email address" required>
</div>
<div class="row p-2">
<label>Phone</label>
<input type="tel" th:field="*{employeePhone}" class="form-control" placeholder="phone number" required>
</div>
<div class="row p-2">
<label>Gender</label>
<select th:field="*{employeeGender}" class="form-select" required>
<option value="" selected>select option</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
</div>
<div class="row p-2">
<label>Salary</label>
<input type="number" th:field="*{employeeSalary}" class="form-control" placeholder="salary" required>
</div>
<div class="row p-2">
<label>Employee Role</label>
<select th:field="*{employeeRole}" class="form-select" required>
<option value="" selected>select option</option>
<option value="Java">Java Developer</option>
<option value="Python">Python Developer</option>
<option value="Web">Web Developer</option>
<option value="Android">Android Developer</option>
<option value="UI">UI Developer</option>
</select>
</div>
<button type="submit" class="btn btn-success mt-3 mb-2">Add Employee</button>
</form>
</div>
</div>
</div>
</div>
Output screen of Index Page:

Insert Employee Data:
For Inserting Employee data into database I used EmployeeRepo object which provides save() methods which is used for saving employee data into database.
@PostMapping("/create")
public String newEmployee(Employee employee, Model model) {
model.addAttribute("employee", new Employee());
// creating dynamic Employee ID
String empId = "EMP";
Random random = new Random();
long randomNumber = 1000 + random.nextInt(9000);
empId = empId + randomNumber;
employee.setId(empId);
// save the employee
employeeRepo.save(employee);
return "redirect:/";
}
Output screen of Insert Employee:

Update Employee Data:
If you want to update an employee, you need existing employee ID then we can update employee data other wise not possible. It is a same Inserting data but Before inserting in this method I check if employee id exist or not. If exist I give access to update employee information.
@PostMapping("/update")
public String updateEmployee(@ModelAttribute Employee employee, Model model) {
model.addAttribute("employee", new Employee());
Optional<Employee> existingEmployee = employeeRepo.findById(employee.getId());
// checking employee exist or not
if (existingEmployee.isPresent()) {
employeeRepo.save(employee);
} else {
model.addAttribute("errorMessage", "Employee with ID " + employee.getId() + " not found.");
}
return "redirect:/";
}
Output screen of Update Employee Details:

Delete Employee Data:
For Deleting an Employee, we need Employee ID, then only we can be able to delete an existing employee otherwise it's not possible to delete. After Successful delete, the result is updated in Employee table for this I used Thymeleaf for handling the Employee pojo class.
@PostMapping("/remove")
public String removeEmployee(Employee employee, Model model) {
model.addAttribute("employee", new Employee());
Optional<Employee> existingEmployee = employeeRepo.findById(employee.getId());
if (existingEmployee.isPresent()) {
employeeRepo.deleteById(employee.getId());
}
return "redirect:/";
}
Output screen of Delete Employee:

Delete All Employees:
The Delete All employee's logic is working based on user confirmation. The Confirmation is nothing but while before deleting all data the application asks your confirmation, if you type yes in the given text field means your confirmed to delete all employee's data.
@PostMapping("/remove/all")
public String removeAll(@ModelAttribute ConfirmationForm confirmationForm, Model model) {
String confirmation = confirmationForm.getConfirmation();
if ("Yes".equalsIgnoreCase(confirmation)) {
employeeRepo.deleteAll();
} else {
return "redirect:/";
}
return "redirect:/";
}
Output Screen of Delete all Employees:

