0% found this document useful (0 votes)
78 views41 pages

Full Stack Java Developer Training

The 12-week Full Stack Java Developer Training focuses on building an Employee Management System (EMS) as a capstone project, covering technologies such as Java, MySQL, Spring Framework, and ReactJS. Each week introduces new concepts and tools, progressing from core Java and OOP principles to advanced topics like exception handling and file I/O. By the end of the course, participants will have developed a fully functional web application that demonstrates various features and best practices in full-stack development.

Uploaded by

Karnam Kiran
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
78 views41 pages

Full Stack Java Developer Training

The 12-week Full Stack Java Developer Training focuses on building an Employee Management System (EMS) as a capstone project, covering technologies such as Java, MySQL, Spring Framework, and ReactJS. Each week introduces new concepts and tools, progressing from core Java and OOP principles to advanced topics like exception handling and file I/O. By the end of the course, participants will have developed a fully functional web application that demonstrates various features and best practices in full-stack development.

Uploaded by

Karnam Kiran
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

12-Week Full Stack Java Developer Training

(Employee Management System Capstone)


Course Overview: This 12-week training program is a comprehensive journey through full-stack Java
development, using an Employee Management System (EMS) as a running capstone project. Each week
focuses on specific technologies and concepts, incrementally building the EMS from a simple Java program
into a fully functional web application with a Java backend and a ReactJS frontend. We will use the
Eclipse IDE for Java development, MySQL as the database, and integrate tools such as Spring Framework,
Spring Boot, Hibernate (JPA), and ReactJS. By the end of the course, you will have a complete EMS
project demonstrating the following features:

 Core Java & OOP: Employee classes with inheritance and abstraction.
 JDBC & SQL: Storing and querying employee data in a MySQL database.
 Servlets & JSP: Web pages for employee registration/login using sessions.
 Spring Core & MVC: A layered architecture (Controller-Service-DAO) managing employees.
 Spring Boot REST APIs: Exposing employee CRUD operations as RESTful services.
 Hibernate ORM: Mapping Employee objects to MySQL tables using JPA for data persistence.
 ReactJS Frontend: A single-page application that consumes the REST APIs to list, add, update, and
delete employees.

Below is a high-level architecture of the final application, showing how the React frontend, Spring Boot
backend, and MySQL database interact:

Figure: Full Stack Architecture – React frontend calls Spring Boot REST APIs, which use Service and
Repository layers to perform CRUD on the MySQL database (via Hibernate/JPA). Controllers handle
HTTP requests, Services encapsulate business logic, and Repositories handle data access.

Tools and Technologies


The following table summarizes the key tools, languages, and frameworks we will use throughout the
course and their purpose:

Technology/Tool Purpose in This Course


Java 11+ (JDK) Core programming language for back-end (OOP, Threads, etc.)
Eclipse IDE Primary IDE for coding Java (projects, debugging, building)
MySQL Relational database to store employee records (CRUD operations)
JDBC Java API (driver) for connecting to MySQL and executing SQL
Apache Tomcat Web server/Servlet container for running JSP/Servlets
JSP (JavaServer Pages) Templating technology for server-side rendering of HTML
Spring Core Framework Framework for Dependency Injection (IoC container for beans)
Spring MVC Web framework (DispatcherServlet, Controllers, Views)
Framework to rapidly create Spring applications (embedded server, auto-
Spring Boot
config)
Spring Data JPA ORM for mapping Java entities to database tables (Employee entity to
(Hibernate) MySQL)
REST (Spring MVC/Boot) Building RESTful web services (JSON-based APIs for CRUD)
ReactJS (Latest version) Frontend library for building dynamic user interfaces
HTML5/CSS3/Bootstrap Markup and styling for web pages (forms, layout, responsiveness)
JavaScript/ES6 Programming language for web frontend (in React and for basic scripts)
Node.js & npm Tooling for React (development server, build process)
Postman Utility to test REST APIs (sending HTTP requests to endpoints)
Git & GitHub Version control to manage code and collaborate (optional)
Maven (build tool) Dependency management and build automation for Java projects
Lombok (optional) Java library to reduce boilerplate (e.g., getters/setters)
(Docker, Jenkins, AWS) – for deployment, CI/CD, cloud hosting (beyond
Optional DevOps
scope of this manual)
Each week’s module will introduce or deepen the use of some of these tools. Now, let’s dive into the
week-by-week breakdown of the curriculum.

Week 1: Core Java – OOP Fundamentals


Topics: Introduction to Object-Oriented Programming in Java – classes, objects, methods, encapsulation,
inheritance, abstraction, polymorphism. We begin building the Employee Management System by
defining basic classes (e.g., an Employee class) and demonstrating Object-Oriented Programming (OOP)
concepts using these classes.

1.1 Introduction to OOP and Java Classes

Java is an object-oriented programming language that enables us to model real-world entities as objects
within our code. In OOP, we bundle data and the functions that operate on that data into classes, which
act as blueprints for objects. This approach makes code more modular, reusable, and easier to maintain.
Java strictly follows principles like DRY (“Don’t Repeat Yourself”), meaning common logic is written once
(e.g., in a parent class) and reused, resulting in code that is easier to maintain and debug.

Classes and Objects: A class in Java is a template that defines state (attributes) and behaviour (methods)
for objects. An object is an instance of a class, representing a specific entity with actual values for the
attributes. For our EMS project, we will start with an Employee class. Each Employee object will represent
an individual employee with properties such as id, name, email, etc., and possibly behaviours like “display
details” or “compute salary”.

Below is a simple Employee class with encapsulated fields and methods:


public class Employee {
// Instance variables (state)
private int id;
private String name;
private String email;
private String position;
private float salary;

// Constructor
public Employee(int id, String name, String email, String position, float salary) {
this.id = id;
this.name = name;
this.email = email;
this.position = position;
this.salary = salary;
}

// Getter and Setter methods (encapsulation)


public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// ... (email, position getters/setters)
public float getSalary() { return salary; }
public void setSalary(float salary) { this.salary = salary; }

// Behavior: display employee details


public void displayDetails() {
System.out.println("Employee: " + name);
System.out.println("Position: " + position);
System.out.println("Salary: " + salary);
}

// Main method for a quick test


public static void main(String[] args) {
Employee emp = new Employee(101, "Alice", "[email protected]", "Developer", 50000.0f);
emp.displayDetails();
}
}

This class encapsulates the data (fields are private, and accessed via public getters/setters), which is an
example of encapsulation – hiding internal details and requiring access through methods. In the code
above, the displayDetails() method prints the object's state; running the main would produce output like:
Employee: Alice
Position: Developer
Salary: 50000.0

(In a real application, we might not have a main in the model class, but this is just to illustrate usage.)

1.2 The Four Pillars of OOP in EMS

Java’s OOP has four core principles: Abstraction, Encapsulation, Inheritance, Polymorphism.

 Encapsulation: As seen, we use private fields and public methods to protect data. This ensures that,
for example, Employee data can’t be arbitrarily changed from outside the class without using its
methods. In our Employee class, fields like id and name are private, and we provide setName(), getName(),
etc. for controlled access. This “protective shield” around data improves code reliability.
 Inheritance: Inheritance allows a new class to reuse and extend the behavior of an existing class. We
could have specialized employee types. For instance, suppose we create a subclass HRManager that
extends Employee. An HR Manager is an employee who can perform additional actions, like hiring
new employees. Using inheritance, HRManager will automatically have all properties of Employee (id,
name, etc.) and can define extra methods or override behavior.

Example – Inheritance and Method Overriding:


We define HRManager as a subclass of Employee, adding a method to hire or add an employee. We
also override the work() method to provide a role-specific message.
// Parent class
class Employee {
private float salary;
public Employee(float salary) { this.salary = salary; }
public void work() {
System.out.println("Working as a regular employee.");
}
public float getSalary() { return salary; }
}

// Child class
class HRManager extends Employee {
public HRManager(float salary) {
super(salary); // call parent constructor
}
@Override
public void work() {
System.out.println("Managing employees and HR tasks.");
}
public void addEmployee(Employee e) {
System.out.println("Hiring new employee: " + e.getName());
// ... (logic to add employee to system)
}
}

In this snippet, HRManager inherits the getSalary() method and salary field from Employee. It overrides
work(): if we call work() on an Employee instance, it prints "Working as a regular employee.", but on an
HRManager instance it prints "Managing employees and HR tasks." – demonstrating polymorphism
(the same method call work() behaves differently based on the object type). Also, HRManager
introduces a new method addEmployee() that regular employees don’t have. This models real life – an
HR Manager can hire people, whereas a general employee might not.

Polymorphism: This term literally means “many forms.” In Java, it appears when a subclass
overrides a method of its superclass, or when one interface is implemented by different classes. For
example, if we had a work() method in multiple subclasses (Developer.work(), HRManager.work(), etc.), we
could treat all employees generally but each will execute its own version of work() at runtime. We
could write:
Employee e1 = new Employee(40000f);
Employee e2 = new HRManager(70000f);
e1.work(); // prints "Working as a regular employee."
e2.work(); // prints "Managing employees and HR tasks."

Even though e2 is declared as Employee, it references an HRManager object, so Java will invoke the
overridden work() of HRManager – this is runtime polymorphism via method overriding.

 Abstraction: Abstraction means exposing only the necessary features of an object while hiding
complex implementation details. In Java, abstraction is often achieved using abstract classes or
interfaces. For example, we might define an EmployeeDAO interface with abstract methods like
save(Employee e), delete(int id), etc., without specifying how these work. Different implementations (e.g.,
one using a file, another using a database) can provide the details. In Week 3 and Week 8, we’ll see
abstraction in action when designing data access layers (using interfaces for DAO and implementing
them with JDBC or JPA). At this stage, just note that abstraction helps separate what an object does
from how it does it.

1.3 Mini-Project Task – Week 1

By the end of Week 1, you should be able to create simple Java classes and use them. As a hands-on
exercise:

 Define the Employee class (as above or with your own fields). Ensure proper encapsulation (private
fields, getters/setters).
 Create a few Employee instances in a main method (or a separate test class) to simulate some
operations:
o Instantiate an Employee and set its properties.
o Print out its details.
o (Optional) Create a subclass like Manager or HRManager that extends Employee. Override a
method (e.g., toString() or a custom work() method) and demonstrate the difference in behavior.
 Run these tests in Eclipse to familiarize yourself with editing, compiling, and running Java programs.
Practice using the Eclipse debugger to inspect object states at runtime.

Summary – Week 1: We established the foundation of our EMS by modeling employees as Java objects.
Key takeaways:

 Java classes encapsulate data and provide methods to operate on that data (e.g., Employee with fields
and methods).
 OOP principles make our code organized: we can extend base classes to create specialized ones
(inheritance), and override methods for polymorphic behavior.
 We now have an Employee class that we will enrich in future weeks and eventually persist and
manage through various layers of the application.

Week 2: Core Java – Advanced Concepts (Exceptions, File I/O,


Collections, Threads)
Topics: Diving deeper into Java language features: exception handling for robust code, file input/output
(I/O) for data storage, collections (like ArrayList, HashMap) for managing groups of objects, and an intro to
multithreading. We will apply these concepts to enhance our EMS console application – for example,
storing a list of employees, reading/writing employee data to a file, and ensuring the program handles
errors gracefully.

2.1 Exception Handling in Java

In real-world programs (and certainly in a full stack app), things can go wrong: a database might not
connect, or an input might be invalid. Java’s exception handling mechanism allows us to catch runtime
errors and handle them without crashing the program. In other words, “Exception handling lets you catch
and handle errors during runtime – so your program doesn’t crash.”

 Try-Catch: We wrap code that might throw an exception in a try block, and provide one or more
catch blocks to handle specific exceptions. “The try statement allows you to define a block of code to
be tested for errors while it is being executed. The catch statement allows you to define a block of
code to be executed if an error occurs in the try block.” For example, reading from a file or parsing
input could throw exceptions.

Example: Suppose we have a text file "employees.txt" and we want to load employees from it. We can
use a try-catch when opening and reading the file:
try {
BufferedReader reader = new BufferedReader(new FileReader("employees.txt"));
String line;
while ((line = reader.readLine()) != null) {
// parse the line and create Employee object
}
reader.close();
} catch (FileNotFoundException e) {
System.err.println("Error: File not found: " + e.getMessage());
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
}

Here we catch two types of exceptions: FileNotFoundException if the file is missing, and a general
IOException for other I/O errors. Instead of the program crashing, we handle the error by printing a
message. We could also recover or default to some behavior if needed.

 Finally: An optional finally block can be added after catch blocks. Code in finally runs regardless of
whether an exception occurred, typically used for cleanup (like closing a file or database
connection). For instance, in the above code we might move the reader.close() call to a finally block to
ensure the file is closed even if an error occurs.

By using exceptions properly, we make our EMS more robust. For example, when adding a new
employee via console input, we can catch invalid inputs (like non-numeric ID or salary) and prompt the
user again, rather than the program terminating with an error.

2.2 File I/O – Saving and Loading Employee Data

In Week 1, our data was in-memory only (when the program ends, the employees are gone). Before we
introduce databases, a simple way to persist data is using files. File I/O in Java is done through classes in
java.io package such as FileReader, FileWriter, BufferedReader, BufferedWriter, etc.

 Writing to a File: We can save employee records in a text file (CSV format, for instance). Example:
 FileWriter fw = new FileWriter("employees.txt", true); // true for append mode
 BufferedWriter bw = new BufferedWriter(fw);
 // Suppose emp is an Employee object
 bw.write(emp.getId() + "," + emp.getName() + "," + emp.getEmail() + "," + emp.getPosition());
 bw.newLine();
 bw.close();

This would append a line like 101,Alice,[email protected],Developer to the file.

 Reading from a File: As shown earlier, use BufferedReader to read each line, then split by comma and
create Employee objects:
 String line = "101,Alice,[email protected],Developer";
 String[] parts = line.split(",");
 int id = Integer.parseInt(parts[0]);
 String name = parts[1];
 String email = parts[2];
 String position = parts[3];
 Employee emp = new Employee(id, name, email, position, 0.0f);

(We used a dummy salary of 0.0 here since our file didn’t include salary.)

Using file I/O, you can implement a simple persistence for the EMS console application:

 Add Employee: Append a line to employees.txt.


 List Employees: Read all lines from employees.txt and display them.
 Search Employee by ID: Read lines until you find the matching ID.

Keep in mind, file I/O is slower than in-memory operations and lacks structure (no query language), so as
we move to Week 3 and beyond, we’ll migrate this data to a relational database. But understanding file
I/O is important (for configuration files, logging, etc., in real apps).

2.3 Collections – Managing Groups of Employees

Java provides the Collections Framework (in java.util) to handle groups of objects dynamically (resizable
arrays, sets, maps, etc.). In an EMS, you might have a list of all employees or a map of employees by their
ID.

Key collection types:

 List (ArrayList): An ordered collection (like a dynamic array). We can use ArrayList<Employee> to store
Employee objects. It allows duplicates and preserves insertion order. Example:
 List<Employee> employees = new ArrayList<>();
 employees.add(emp1);
 employees.add(emp2);
 System.out.println("Total employees: " + employees.size());

You can loop through the list to display or process each Employee.
 Set (HashSet): Unordered collection that disallows duplicates. This could be useful to ensure no two
employees with the same ID or email are added (though more typically you’d enforce uniqueness
by checking before add, or using a Map).
 Map (HashMap): A key-value structure. We could map employee ID to the Employee object:
Map<Integer, Employee> empMap = new HashMap<>(); empMap.put(emp.getId(), emp);. This makes lookups by
ID efficient (constant time on average). For example, empMap.get(101) would directly give Employee
with ID 101 if present.

In our console EMS, we might maintain an ArrayList<Employee> as the master list of employees in memory
while the program runs. When adding or removing employees, we update this list (and also update the
file for persistence). Using collections makes it easy to manage the dynamic set of employees without
worrying about array resizing or other low-level details.

Example – Using ArrayList: After reading from file:


List<Employee> employees = new ArrayList<>();
// ... in file reading loop:
Employee emp = new Employee(id, name, email, position, salary);
employees.add(emp);
// Later, to list all employees:
for (Employee e : employees) {
System.out.println(e.getId() + " - " + e.getName() + " (" + e.getPosition() + ")");
}

Collections also come with utility methods and algorithms (sorting, searching, etc.). You could, for
instance, sort the employees list by name or salary using Collections.sort with a custom Comparator.

2.4 Basic Multithreading

Threads allow a program to do multiple tasks concurrently. While a full EMS might not need complex
multithreading at this stage, it’s useful to know the basics for scenarios like handling multiple user requests
simultaneously on a server (which web servers do using threads).

 A thread in Java is a separate path of execution. The main program runs on the "main thread". You
can create new threads by either extending Thread class or implementing Runnable.

Why threads? “Threads allow a program to operate more efficiently by doing multiple things at the same
time… perform complicated tasks in the background without interrupting the main program.” For
example, in a UI application, one thread can handle user interface events while another thread performs a
long computation in background.

Creating a Thread – Example: Suppose we want to simulate a background task in EMS, like sending a
notification email whenever a new employee is added, without pausing the main flow of the program.
class EmailNotifier implements Runnable {
private Employee newEmp;
public EmailNotifier(Employee emp) { this.newEmp = emp; }
@Override
public void run() {
// Simulate sending email
System.out.println("Sending welcome email to " + newEmp.getEmail());
// ... actual email sending code (omitted)
System.out.println("Email sent for new employee " + newEmp.getName());
}
}

// Somewhere in code after adding an employee:


Employee e = new Employee(...);
employees.add(e);
// start background email notification
Thread emailThread = new Thread(new EmailNotifier(e));
emailThread.start();
System.out.println("Main thread continues while email is being sent...");

In this snippet, EmailNotifier implements Runnable (so it can be executed by a Thread). We create a new Thread
with this task and call start(), which causes the run() method to execute in a separate thread. The main
thread can continue (e.g., accept next input) concurrently. The output might intermix, for example:
Main thread continues while email is being sent...
Sending welcome email to [email protected]
Email sent for new employee Alice
demonstrating parallel execution.

For our training, it's sufficient to grasp how to start threads and the concept of race conditions (if multiple
threads access shared data like the employees list, we’d need to synchronize access). In a web context, each
client request might be handled in its own thread by the server – we won't manage those threads directly,
but knowing the concept helps in writing thread-safe code.

2.5 Mini-Project Task – Week 2

Extend your EMS console program with the following features:

 Exception Handling: Wrap user input parsing in try-catch. For example, if prompting for an
employee’s salary which should be a number, catch NumberFormatException and ask again rather than
crashing.
 File Persistence: Implement saving the employees list to a file (e.g., upon program exit or after each
add/delete operation). Also implement loading from the file at program start. This way, data is
retained between runs.
 Use Collections: Instead of an array or individual variables, use an ArrayList<Employee> to store
employees in memory. Implement functions to add, remove, search, and list employees using this
list.
 (Optional) Threads: As an extra challenge, simulate a background task such as periodic autosave.
For instance, start a thread that every 30 seconds writes the current employees list to file (you can
use Thread.sleep(30000) within a loop for this thread). Ensure proper termination of this thread when
program exits (or mark it as daemon thread).

Test your program for various scenarios:

 Adding multiple employees, exiting and restarting to see if file load works.
 Trying invalid inputs (letters where a number is expected) to see if exceptions are handled.
 Searching for an employee that doesn't exist, etc.

Summary – Week 2: We strengthened our Java foundations with advanced concepts:

 Exceptions: You learned to use try-catch to make the program handle errors (like file not found or
bad input) gracefully.
 File I/O: We added rudimentary persistence by reading/writing a text file with employee data.
 Collections: Instead of fixed arrays, we manage dynamic lists of employees using ArrayList, making it
easier to scale our program as the number of employees grows.
 Threads: Gained a basic understanding of multi-threading, which will be useful when we move to
server-side programming (where numerous client requests may be handled in parallel).
 At this point, we have a simple EMS running in the console, with data persistence via a flat file.
Starting next week, we transition to using a database for more robust data storage and begin
building a web interface.

Week 3: JDBC and SQL – Connecting to MySQL Database


Topics: Setting up a MySQL database for the EMS, learning basic SQL (DDL and DML for creating tables
and querying data), and using JDBC (Java Database Connectivity) to connect our Java program to
MySQL. By the end of this week, our Employee data will be stored in a database rather than a text file.
We will implement CRUD (Create, Read, Update, Delete) operations on employees through SQL queries
in Java code.

3.1 Introduction to MySQL and SQL for EMS

Relational Database & SQL: MySQL is a popular open-source relational database. In a relational database,
data is organized into tables consisting of rows and columns. SQL (Structured Query Language) is used to
define and manipulate data in these tables. For our EMS, we will create a table employees to store
employee records.

Let’s define a simple schema for employees table:

 id– integer, primary key (unique identifier for each employee, perhaps auto-incremented).
 name – varchar (string for name).
 email – varchar (string for email, unique constraint can be added if needed).
 position – varchar (job title).
 salary – float (or decimal for salary).

In MySQL, the SQL to create this table would be:


CREATE DATABASE EMS; -- create a database (if not already created)
USE EMS;
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL,
position VARCHAR(50),
salary DECIMAL(10,2)
);

We can execute these commands using MySQL client or a tool like MySQL Workbench. (Note: We might
add UNIQUE(email) if we want to ensure no duplicate emails.)

Basic SQL operations for employees:

 INSERT: add a new employee row.


 SELECT: retrieve employee data (all employees, or a specific one).
 UPDATE: change details of an existing employee.
 DELETE: remove an employee.

Example SQL:
INSERT INTO employees (name, email, position, salary)
VALUES ('Alice', '[email protected]', 'Developer', 50000.00);

SELECT * FROM employees; -- retrieve all columns for all employees

UPDATE employees SET salary = 52000.00 WHERE id = 1;

DELETE FROM employees WHERE id = 2;

We will use these queries via JDBC in our Java code.

3.2 Setting Up JDBC Connection

JDBC is a standard Java API for database connectivity. Using JDBC, our Java program can send SQL
statements to MySQL and get the results. To use JDBC with MySQL, you need the MySQL Connector/J
driver (a JAR file). If using Maven, adding the dependency mysql:mysql-connector-java will include it. In
Eclipse, you can add the JAR to the classpath. (If using an IDE with build tools, this may be handled by
Maven/Gradle – but ensure the connector is available.)

Steps to connect to MySQL via JDBC:

1. Load the JDBC driver: In old JDBC, you would call Class.forName("com.mysql.cj.jdbc.Driver"); to load the
driver class. In modern JDBC (JDBC 4+), this is not always required explicitly, as the driver can
auto-register.
2. Obtain a Connection object: Use DriverManager.getConnection(url, username, password). The URL format for
MySQL is jdbc:mysql://<host>:<port>/<database>. For example:
3. String url = "jdbc:mysql://localhost:3306/EMS";
4. Connection conn = DriverManager.getConnection(url, "root", "password");

This attempts to connect to the database EMS on local MySQL server at port 3306 with user "root"
and the given password.

5. Create a Statement: There are two main ways – using a Statement or a PreparedStatement (the latter is
preferred for parameterized queries and to prevent SQL injection). For now, we can use Statement for
simplicity:
6. Statement stmt = conn.createStatement();
7. Execute SQL queries: For a query that returns results (SELECT), use stmt.executeQuery(sql) which returns
a ResultSet. For updates (INSERT/UPDATE/DELETE), use stmt.executeUpdate(sql) which returns the
number of affected rows.
8. Process results: If we got a ResultSet (from SELECT), iterate over it to read rows:
9. ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
10. while(rs.next()) {
11. int id = rs.getInt("id");
12. String name = rs.getString("name");
13. // ... fetch other columns
14. System.out.println(id + ": " + name);
15. }
16. rs.close();
17.Close connection: When done, call conn.close() to release the database resource (or use try-with-
resources to auto-close).

Example – Reading from DB via JDBC: Suppose we want to retrieve all employees and print their names:
try {
Class.forName("com.mysql.cj.jdbc.Driver"); // load driver (optional in modern JDBC)
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/EMS", "root", "password");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name, email, position, salary FROM employees");
while(rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name") +
" - " + rs.getString("position"));
}
rs.close();
stmt.close();
conn.close();
} catch(Exception e) {
e.printStackTrace();
}

This snippet shows the core pattern: open connection → execute query → process results → close. We
handle exceptions with a broad catch for simplicity (printing stack trace), but in a real application, you’d
have specific error handling (like if connection fails, maybe retry or display a user-friendly message).

illustrates similar code: establishing connection and querying a table using JDBC.

3.3 Implementing CRUD with JDBC in EMS

Now, integrate JDBC into the EMS application:

 Create (INSERT): When a new employee is added via the program (or later via a web form),
instead of writing to file, use an INSERT SQL. For example:
 String sql = "INSERT INTO employees (name, email, position, salary) VALUES ('"
 + emp.getName() + "','" + emp.getEmail() + "','"
 + emp.getPosition() + "'," + emp.getSalary() + ")";
 stmt.executeUpdate(sql);

Using string concatenation like this is functional but not secure (SQL injection risk). A better
approach is:
PreparedStatement ps = conn.prepareStatement(
"INSERT INTO employees(name, email, position, salary) VALUES (?, ?, ?, ?)");
ps.setString(1, emp.getName());
ps.setString(2, emp.getEmail());
ps.setString(3, emp.getPosition());
ps.setDouble(4, emp.getSalary());
ps.executeUpdate();

The ? placeholders and corresponding setX methods prevent SQL injection and handle quoting for
us.

 Read (SELECT): We already saw selecting all employees. If we need to find one employee by ID:
 PreparedStatement ps = conn.prepareStatement("SELECT * FROM employees WHERE id = ?");
 ps.setInt(1, searchId);
 ResultSet rs = ps.executeQuery();
 if(rs.next()) {
 // found the employee
 Employee emp = new Employee(rs.getInt("id"),
 rs.getString("name"),
 rs.getString("email"),
 rs.getString("position"),
 rs.getFloat("salary"));
 // use emp as needed
 } else {
 System.out.println("Employee not found!");
 }
 Update: Suppose we want to give a raise or change an employee’s position:
 PreparedStatement ps = conn.prepareStatement("UPDATE employees SET salary = ? WHERE id = ?");
 ps.setDouble(1, newSalary);
 ps.setInt(2, empId);
 int rows = ps.executeUpdate();
 if(rows > 0) {
 System.out.println("Employee salary updated.");
 }
 Delete:
 PreparedStatement ps = conn.prepareStatement("DELETE FROM employees WHERE id = ?");
 ps.setInt(1, empId);
 ps.executeUpdate();
 System.out.println("Employee deleted from database.");

Ensure to handle exceptions around these calls (e.g., SQL syntax errors, unique constraint violations, etc.).

Tip: Use try-with-resources for Connection, Statement, and ResultSet to auto-close them:
try(Connection conn = DriverManager.getConnection(url, user, pass);
PreparedStatement ps = conn.prepareStatement("...")) {
// use ps, maybe get a ResultSet
} catch(SQLException ex) {
// handle
}

This pattern is cleaner and ensures resources are closed even if exceptions occur.

3.4 JDBC in Eclipse and Testing

In Eclipse, you should configure the MySQL Connector/J on your project’s build path. If using Maven,
include in pom.xml:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version> <!-- or latest available -->
</dependency>

(If not using Maven, manually adding the JAR to the project’s libraries is needed.)

Testing the database connection: Before integrating with your EMS logic, write a small test in main to
ensure you can connect and run a simple query:
public static void main(String[] args) {
try(Connection conn = DriverManager.getConnection(url, user, pass)) {
System.out.println("Database connection successful!");
} catch(SQLException e) {
e.printStackTrace();
}
}

If this prints the success message, you’re connected. If not, check that MySQL is running, the
URL/credentials are correct, and the connector JAR is properly included.

Once confirmed, replace file I/O operations in your EMS with JDBC calls:

 On program start, populate the employees list by selecting all records from DB (or you can directly
operate on the database without keeping an in-memory list, but caching in a list could still be useful
for quick read access – however, consider sync issues if direct DB updates).
 On adding an employee, do an INSERT.
 On removing, do a DELETE.
 For listing, either use the cached list or fetch fresh from DB via SELECT.
 For search, use a SELECT with WHERE id = ... or filter the cached list.

This essentially turns your console EMS into a two-tier application (client and database) instead of relying
on flat files.

3.5 A Note on SQL Joins (Beyond Single Table)

The curriculum mentions SQL joins – while our EMS at this point has a single employees table, in a more
realistic scenario, you might have related tables (e.g., a department table and an employee table, where each
employee is linked to a department). A JOIN in SQL allows combining rows from two or more tables
based on a related column between them.

For example, if we had departments table (dept_id, dept_name) and employees had a dept_id foreign key, we
could run:
SELECT e.name, e.position, d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id
WHERE d.dept_name = 'Engineering';

This would list all employees in the Engineering department (combining data from both tables). While our
current EMS doesn’t involve joins yet, understanding them is crucial as systems grow (and we will see
some join-like behavior when we use Hibernate relationships in Week 8).

For now, ensure you understand one-to-many relationships conceptually (one department has many
employees, one employee belongs to one department, etc.), since it will inform how we structure data
later.

3.6 Mini-Project Task – Week 3

By the end of this week, your EMS should be backed by MySQL. Complete the following:

 Install MySQL (if not already) and create the EMS database and employees table as discussed.
 Migrate data: If you had employees in the file, consider writing a small script or program to read
the file and INSERT them into the database so you don’t start from scratch.
 Update EMS code: Remove or bypass file storage; use JDBC for all data operations.
 Implement all CRUD operations in the console menu (e.g., add employee, view all, search by ID,
update salary/position, delete employee).
 Test thoroughly: Add a few employees, restart program (it should load from DB the existing
entries), update an employee and ensure changes reflect in DB, delete an employee and check DB,
etc. Use MySQL Workbench or the MySQL command-line to verify data in the table after each
operation.

Summary – Week 3: We have transitioned from file-based storage to a real database:

 Set up a MySQL database and used SQL to define the employees table.
 Learned fundamental SQL commands (CREATE TABLE, INSERT, SELECT, UPDATE, DELETE) and
how to use them to manage data.
 Used JDBC in Java to connect to the database and execute SQL statements from our program.
 We built a simple “DB CRUD App” for employees – our EMS can now create, read, update, and
delete employee records in MySQL.
 This foundation will support our web application development. From next week onward, we shift
focus to building a web interface (first using Servlets/JSP, then Spring) while continuing to use this
database for persistence.

Week 4: Web Development with Servlets and JSP


Topics: Introduction to Java web development – deploying our application on a server using Servlets
(Java classes that handle HTTP requests) and JSP (JavaServer Pages) for generating dynamic HTML. We
will create a basic web interface for the EMS: a page to list employees, a form to add a new employee,
and maybe a simple login page to demonstrate session handling. The goal is a “Mini web app” version of
EMS running on Tomcat (or a similar servlet container).

4.1 Understanding Servlets and the Web Application Model

A Servlet is a Java class that runs on a server and responds to HTTP requests (usually from a web
browser). It’s part of Java’s Java EE (Jakarta EE) specifications for building dynamic web content. Think of
a servlet as similar to a console main program, but instead of reading/writing from the console, it reads
HTTP requests and writes HTTP responses (usually HTML).

How web requests work with servlets:

1. A client (browser) makes an HTTP request (e.g., GET /listEmployees).


2. The request hits the web server (e.g., Tomcat), which forwards it to the appropriate servlet based
on configuration (either via web.xml or annotations).
3. The servlet’s method (doGet or doPost) executes, can interact with the database or other logic (like
our EMS data), and produces an output (often HTML).
4. The servlet sends an HTTP response back to the client (like an HTML page).
This flow is managed by the Servlet container. The lifecycle of a servlet involves initialization (init()
method called once), handling requests (service() method which dispatches to doGet(), doPost(), etc.), and
eventual destruction (destroy() on server shutdown).

JSP is a templating technology that allows writing HTML pages with embedded Java code or expressions.
JSPs are translated by the server into servlets under the hood. They make it easier to generate HTML than
writing out print statements in a servlet.

We will use a combination of servlets and JSP to implement a simple MVC-like pattern:

 A Servlet acts as a Controller (processing input, interacting with the model – e.g., using JDBC/DB –
and deciding what view to display).
 A JSP acts as the View (presenting data in HTML).

4.2 Setting Up a Web Application (Eclipse Dynamic Web Project or Maven)

Using Eclipse, you can create a Dynamic Web Project or use Maven’s archetype for a webapp. Key pieces:

 Deployment Descriptor (web.xml): Defines servlet mappings if not using annotations, and other
config. For simplicity, we may skip detailed web.xml by using servlet 3.0+ annotations
(@WebServlet).
 Tomcat Server: In Eclipse, add Tomcat to server runtime. When you run the web project, Eclipse
will deploy it to Tomcat.

Ensure your project structure has a WebContent (or src/main/webapp for Maven) folder for HTML/JSP files, and
that you have the servlet API available (Eclipse adds it if you target a runtime like Tomcat).

4.3 Building EMS Web Pages – Servlets & JSP

Scenario: We create a basic EMS portal with:

 listEmployees.jsp– shows a table of all employees.


 addEmployee.jsp – a form to input new employee details.
 AddEmployeeServlet – handles form submission (on doPost).
 ListEmployeeServlet – retrieves employee list (perhaps by querying DB via JDBC as done in Week 3) and
forwards to listEmployees.jsp for display.
 (Optional) login.jsp and LoginServlet – simulate a simple login to demonstrate sessions.

Servlet Example – ListEmployeeServlet (doGet):


@WebServlet("/listEmployees")
public class ListEmployeeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. Get employee data from DB (reuse JDBC code or call a DAO method)
List<Employee> employees = EmployeeDAO.findAll(); // assume we have a DAO with this method
// 2. Store data in request scope
request.setAttribute("employeeList", employees);
// 3. Forward request to JSP for rendering
RequestDispatcher rd = request.getRequestDispatcher("listEmployees.jsp");
rd.forward(request, response);
}
}

In this servlet, we gather data and then forward to a JSP. The JSP will use the employeeList attribute to
display the data. Forwarding is done with RequestDispatcher.forward() which transfers control to the JSP on the
server side (the browser’s URL still shows /listEmployees – the user isn’t redirected). This is a common
pattern: Servlet as controller, JSP as view.

JSP Example – listEmployees.jsp:


<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.List, com.yourapp.Employee" %>
<html>
<head><title>Employee List</title></head>
<body>
<h2>All Employees</h2>
<table border="1">
<tr><th>ID</th><th>Name</th><th>Position</th><th>Email</th><th>Salary</th></tr>
<%
List<Employee> emps = (List<Employee>) request.getAttribute("employeeList");
if(emps != null) {
for(Employee e : emps) {
%>
<tr>
<td><%= e.getId() %></td>
<td><%= e.getName() %></td>
<td><%= e.getPosition() %></td>
<td><%= e.getEmail() %></td>
<td><%= e.getSalary() %></td>
</tr>
<%
}
} else { %>
<tr><td colspan="5">No employees to display.</td></tr>
<% } %>
</table>
<a href="addEmployee.jsp">Add New Employee</a>
</body>
</html>

This JSP uses Java code within <% ... %> to iterate over the list and <%= ... %> to output values. This is
one approach; a better approach is to use JSP Expression Language (EL) and JSTL tags to avoid Java
scriptlets. For example, with JSTL, one could do:
<c:forEach var="e" items="${employeeList}">
<tr><td>${e.id}</td> ... </tr>
</c:forEach>

assuming proper taglib directives. The codejava excerpt shows an example of using ${name} in JSP after
setting it in servlet, and using <c:forEach> to iterate collections.

For simplicity, our example above used scriptlets, but be aware that modern JSP practice favors JSTL/EL.

Form Handling with Servlets:


We need a form to add employees. In addEmployee.jsp:
<form action="addEmployee" method="post">
Name: <input type="text" name="name" /><br/>
Email: <input type="email" name="email" /><br/>
Position: <input type="text" name="position" /><br/>
Salary: <input type="number" name="salary" step="0.01" /><br/>
<input type="submit" value="Add Employee"/>
</form>

This form will send a POST request to the URL addEmployee (which we will map to AddEmployeeServlet).

Servlet Example – AddEmployeeServlet (doPost):


@WebServlet("/addEmployee")
public class AddEmployeeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. Read form fields
String name = request.getParameter("name");
String email = request.getParameter("email");
String position = request.getParameter("position");
String salaryStr = request.getParameter("salary");
float salary = Float.parseFloat(salaryStr);
// 2. Create Employee and save to DB
Employee emp = new Employee(0, name, email, position, salary);
EmployeeDAO.save(emp); // assume this inserts into DB and sets an ID
// 3. Redirect to list page
response.sendRedirect("listEmployees");
}
}

Here we use request.getParameter("fieldName") to retrieve form data. We parse numeric fields as needed. After
saving the new employee (via some DAO or direct JDBC inside servlet), we use sendRedirect to redirect the
client to the list page. We choose redirect here (as opposed to forward) because after a form submission,
a redirect implements the PRG pattern (Post-Redirect-Get) to avoid duplicate form submissions on refresh.
The user’s browser will now issue a GET for /listEmployees and get the updated list.

Sessions and Login Example (optional):


To introduce session management, you could create a simple login mechanism:

 A login.jsp with a form (username & password). On submit, goes to LoginServlet.


 LoginServlet checks credentials (hardcoded for demo, e.g., "admin"/"pass"). If valid:
 HttpSession session = request.getSession();
 session.setAttribute("username", user);
 response.sendRedirect("listEmployees");

If invalid, maybe redirect back to login.jsp with an error message.

 In ListEmployeeServlet (and maybe others), check if user is logged in:


 HttpSession session = request.getSession(false);
 if(session == null || session.getAttribute("username") == null) {
 response.sendRedirect("login.jsp");
 return;
 }

This ensures only logged-in users can access employee pages. We can also display the username in
JSP by pulling from session via EL: ${sessionScope.username}.

 A logout link can invalidate the session: request.getSession().invalidate() and redirect to login.

This is a rudimentary illustration of session usage; real apps use frameworks or filters for authentication,
but understanding the HttpSession API is valuable. A session allows data to persist across multiple requests
from the same client (like a user login state).

4.4 Running and Testing the Mini Web App

 Deploy on Tomcat: In Eclipse, run the project on the server. Ensure the context path is correct
(often the project name).
 Access in browser: Open http://localhost:8080/YourApp/listEmployees (or whatever initial page you set,
maybe login.jsp). You should see either a login or the list page. Initially the list might be empty (if
DB has no data).
 Test adding employees: Navigate to "Add New Employee" page, fill the form, submit. The browser
should redirect to the list page now showing the new employee. Check the database table to
confirm the row is inserted.
 Session test (if implemented): Try accessing a page without login (should redirect to login). Login
and then try the pages (should succeed). Log out and test protection again.
 Error handling: If any exceptions occur in servlets (e.g., DB connection issues), the default is Tomcat
will show a stack trace page. We can configure error pages in web.xml if desired, but at this stage
the focus is on functionality. Monitor the server console for any System.out.println or stack traces for
debugging.

4.5 Mini-Project Task – Week 4

Create the web front-end for EMS:

 Develop the JSP pages for list and add (and optionally login).
 Write the corresponding servlets to handle data retrieval and submissions.
 Reuse your JDBC code from Week 3 within servlets or, better, refactor a bit: you might create a
utility class or DAO (Data Access Object) class for Employee that has static methods like findAll(),
save(Employee), etc., to avoid duplicating JDBC logic in multiple servlets.
 Use sessions to handle a simple authentication state (optional but recommended for learning).
 Ensure that after adding or deleting an employee via the web interface, the changes reflect in the
database and in subsequent page views.

This week essentially produces a “Mini web app” version of the EMS. While it may not be pretty (basic
HTML styling) or fully secure, it demonstrates the end-to-end flow: client -> HTTP -> servlet -> JDBC ->
database, and back to client with dynamically generated content.

Summary – Week 4: We have taken a big step into web development:

 Learned what Servlets are and how the Servlet container (like Tomcat) routes requests to our code.
 Created dynamic JSP pages and used them to present employee data nicely in an HTML table.
 Handled form input and learned to retrieve form parameters in servlets.
 Implemented navigation flows using request forwarding (server-side inclusion of JSP) and
redirection (instructing the browser to issue a new request).
 Used HttpSession to maintain user login state across requests, illustrating how sessions allow us to
treat multiple HTTP requests as a continuous interaction.
 Our EMS can now be accessed via a web browser, making it far more user-friendly than the old
console version. Up next, we will improve the design and structure of our application using the
Spring framework, which will streamline many of these tasks and prepare our app for even more
features.

Week 5: Spring Core – Inversion of Control and Beans


Topics: Introduction to the Spring Framework Core module – focusing on Inversion of Control (IoC) and
Dependency Injection (DI). We will refactor our application to use Spring’s container to manage our
objects (beans) instead of manually instantiating and wiring them. We’ll set up a basic layered architecture
(e.g., separate service and repository beans for employee operations) as a prelude to using Spring MVC
and other Spring modules.

5.1 Why Spring? Understanding IoC and DI

As our application grows, managing object creation and dependencies becomes complex. For instance, in
Week 4, servlets might directly call JDBC code. Ideally, we want a cleaner separation:

 Controller (Servlet or Spring MVC Controller) – handles web layer.


 Service – contains business logic (e.g., validations, calculations).
 DAO/Repository – handles data access (JDBC or JPA calls).
 Model – simple POJOs like our Employee class.

The Spring Framework helps by providing an IoC container which will create and manage the lifecycle of
objects (called beans) and inject dependencies where needed. “Inversion of Control (IoC) is a design
principle where the control of object creation and lifecycle is managed by a framework or container
rather than by the developer. Spring's IoC container creates, configures, and manages objects (beans) and
injects their dependencies.”. This means instead of our code doing new EmployeeDAO() or new EmployeeService(),
we declare these in Spring config, and Spring will supply them to our classes.

Dependency Injection (DI) is the mechanism by which the IoC container provides the needed
dependencies to a bean. Rather than a bean looking up or creating its collaborators, it is given to it
(injected) by the container. “Dependency Injection allows objects to be injected with their dependencies
rather than creating those dependencies themselves”. This leads to looser coupling and easier unit testing
(we can swap out mock dependencies, etc.).

In simpler terms: We define beans (like EmployeeService, EmployeeRepository) in Spring configuration, and we
declare in our code what we need (e.g., EmployeeService needs an EmployeeRepository). Spring will inject an
instance of EmployeeRepository into EmployeeService automatically, as long as it knows about both and the
relationship (via annotations or XML config).

5.2 Setting Up Spring in Our Project

We will use Spring Framework (version 5 or above). If using Maven, include dependencies for Spring
Context:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.30</version>
</dependency>

Also include spring-beans and spring-core (these might be transitively included with context). Since eventually
we want Spring MVC, we will include those in the next week, but for now focusing on core.

Defining Beans: There are two main ways – XML configuration or annotation-based with classpath
scanning. Modern Spring favors annotations:

 Annotations: Use @Component (or @Service, @Repository, etc.) on classes to mark them as beans. Enable
component scanning so Spring finds them.
 XML: Define <bean id="employeeService" class="com.example.EmployeeService"> etc. and their property
injection in an XML file (like beans.xml).

We’ll demonstrate annotation approach as it's prevalent:

 Mark our classes:


 @Service
 public class EmployeeService {
 @Autowired
 private EmployeeRepository repo;
 // business methods...
 }
 @Repository
 public class EmployeeRepository {
 // maybe uses JDBC or JPA to interact with DB...
 }

Here @Service and @Repository are specializations of @Component (they act the same for component
scanning but convey the role). @Autowired on the repo field tells Spring to inject an EmployeeRepository
bean here.

 Create a configuration:
We can either use an XML file or a Java config class. For variety, let's use a Java config:
 @Configuration
 @ComponentScan(basePackages="com.example")
 public class AppConfig {
 // If any manual bean definitions needed, we could add @Bean methods here.
 }

indicates this class defines beans (it can also just be used to trigger scanning).
@Configuration
@ComponentScan tells Spring which packages to scan for @Component classes.

 Initialize Spring container:


In a standalone app (or in tests), we would do:
 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
 EmployeeService service = context.getBean(EmployeeService.class);

In a web app, Spring’s ContextLoaderListener or Spring Boot (next weeks) would manage this for
us. But for now, to see IoC in action, you might write a test or a main method to retrieve beans
from the container.

What happens: Spring scans com.example package, finds EmployeeService and EmployeeRepository
classes with relevant annotations. It creates one EmployeeRepository bean and one EmployeeService bean. When
creating EmployeeService, it sees the @Autowired dependency on EmployeeRepository and injects the instance
of EmployeeRepository into it. Now, whenever we request EmployeeService from context, we get a fully
initialized object with its repo field set.

This inversion of control means our service class didn’t have to find or create the repository – it just
declares it needs one. The container took care of supplying it.

Bean scopes: By default, Spring beans are singleton (one instance for the container). So both our service
and repository are singletons used throughout. Spring supports other scopes (prototype, request, session,
etc.) but default singleton is fine for now.

5.3 Layered Architecture with Spring

We will refactor EMS to use a Service layer and Repository (DAO) layer:

 EmployeeRepository (DAO): Responsible for all data operations (previously done via JDBC code).
Could use JDBC template or raw JDBC calls. For now, we can wrap our Week 3 JDBC logic here.
For example:
 @Repository
 public class EmployeeRepository {
 // DataSource or Connection info could be here (or better, use JdbcTemplate)
 public List<Employee> findAll() {
 // JDBC code to SELECT * FROM employees and return list
 }
 public void save(Employee emp) {
 // JDBC code to insert emp
 }
 // etc. (findById, update, delete)
 }
 EmployeeService: Sits above repository. It can contain business rules. For example, before saving,
maybe check that email is unique (could call repository to find by email). Or could apply some logic
like setting default values.
 @Service
 public class EmployeeService {
 @Autowired
 private EmployeeRepository repo;

 public List<Employee> getAllEmployees() {
 return repo.findAll();
 }
 public void addEmployee(Employee emp) {
 // perhaps some validation:
 if(emp.getName() == null || emp.getName().isEmpty()) {
 throw new IllegalArgumentException("Name is required");
 }
 repo.save(emp);
 }
 // similarly updateEmployee, deleteEmployee, etc.
 }

Now our servlets (or later controllers) will interact only with EmployeeService, not directly with JDBC. This
separation improves maintainability:

 If we change how data is stored (say move from JDBC to JPA/Hibernate), we only change
EmployeeRepository implementation.
 If we add business rules, they go into EmployeeService without cluttering the web layer.

Integrating Spring with the Web (in this basic app): We can use Spring in servlets by either using Spring’s
WebApplicationContext or by manually fetching beans. A simple approach: in ListEmployeeServlet, we could
obtain the Spring context from a context listener or static initializer. Alternatively, use
WebApplicationContextUtils:

WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());


EmployeeService service = ctx.getBean(EmployeeService.class);
List<Employee> list = service.getAllEmployees();

Then set request attribute and forward to JSP. However, since next week we move to Spring MVC, we
might not spend too much time integrating servlets with Spring manually. It’s good to conceptually know
that in a Spring MVC app, controllers are Spring beans themselves and automatically get their
dependencies injected.

For now, you can simulate usage of the service in a unit test or a main outside of the web context:
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
EmployeeService service = ctx.getBean(EmployeeService.class);
// test retrieval
service.getAllEmployees().forEach(emp -> System.out.println(emp.getName()));
ctx.close();
}

This should print names of employees from DB, using the repository bean inside service.

Note: For repository to connect to DB, we need a DataSource bean or similar. We might configure a
DataSource in Spring (via XML or Java config) and inject it into EmployeeRepository. Or the repository can use
DriverManager internally (not ideal for resource mgmt). A simple approach: use Spring’s
DriverManagerDataSource:

@Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/EMS");
ds.setUsername("root");
ds.setPassword("password");
return ds;
}

Then in EmployeeRepository, use @Autowired DataSource ds; and get Connection from it. Or better, use Spring’s
JdbcTemplate which simplifies JDBC usage.

However, since Spring Boot (Week 7) will simplify a lot of this configuration, we might not delve deep
here. It's enough to grasp IoC/DI concept.

5.4 Mini-Project Task – Week 5

Refactor EMS backend using Spring IoC:

 Create EmployeeRepository and EmployeeService classes annotated with @Repository and @Service.
 Move JDBC code from servlets to EmployeeRepository.
 Add any needed business logic in EmployeeService (even if just a pass-through for now).
 Configure Spring (via XML or annotations) and initialize the Spring container when the web app
starts. You can add Spring’s ContextLoaderListener in web.xml to load AppConfig:
 <context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>com.example.AppConfig</param-value>
 </context-param>
 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

This will start Spring’s root WebApplicationContext when the webapp deploys.

 Modify servlets to obtain beans from Spring context instead of creating their own connections or
logic:
e.g., EmployeeService service = (EmployeeService) ctx.getBean("employeeService"); (bean name defaults to class
name with lowercase first letter if not specified).
 Test the application – functionality should remain same (list/add works) but now powered by
Spring-managed beans.

Summary – Week 5: We introduced Spring to manage our application’s components:

 IoC Container: We let Spring create and manage objects, which decouples component creation
from usage.
 Dependency Injection: Used @Autowired to have Spring supply dependencies rather than using new in
our code. This makes it easy to swap implementations (for example, we could have a different
EmployeeRepository impl for testing that doesn’t hit a real DB).
 Layering: We structured the app into a Service layer and Repository (DAO) layer, each a Spring
bean. This makes our design more modular and in line with enterprise best practices (Controller →
Service → DAO).
 Although our web interface still used servlets, we’ve prepared the backend to be consumed easily
by Spring MVC controllers next week. We also get benefits like easier unit testing (we could test
EmployeeService by injecting a mock EmployeeRepository thanks to DI) and clearer separation of concerns.

Next, we will leverage Spring MVC to replace our servlets and JSPs, integrating smoothly with these
service beans.

Week 6: Spring MVC – Building Web Applications the Spring Way


Topics: Using Spring MVC framework to handle web requests instead of manual servlets. We’ll create
Spring Controllers to replace our servlets, use Spring’s view resolution (with JSP or Thymeleaf) for
rendering, and see how the DispatcherServlet works as the front controller. By end of week, our EMS web
app will be running on Spring MVC, with a cleaner configuration and easier integration with Spring’s
features.

6.1 Spring MVC Overview

Spring MVC follows the Model-View-Controller pattern:

 DispatcherServlet: The front controller provided by Spring. It intercepts all incoming requests (via a
URL pattern mapping, usually "/*" or specific suffix).
 Controller (@Controller classes): These are analogous to servlets, but as Spring beans with
annotation mappings. They handle requests and prepare data for view.
 Model: Typically the data (like our Employee objects, or a list of employees) that the controller
adds to the model for the view to render.
 View: The UI representation, often a JSP or Thymeleaf template, responsible for presenting the
model data.

The flow:

1. Client hits an URL (e.g., /employees).


2. DispatcherServlet receives it (configured via web.xml or in Spring Boot auto-config).
3. It finds which controller method is mapped to /employees (using @RequestMapping or newer
@GetMapping, etc.).
4. Calls that controller method. The method can use EmployeeService (injected) to get data.
5. The method returns a view name (e.g., "employeeList"), and the controller may have added attributes
to a Model.
6. DispatcherServlet consults ViewResolver to resolve the view name to an actual JSP page (e.g.,
employeeList.jsp).
7. The view is rendered with model data and sent to client.

This is somewhat similar to what we did with servlets + JSP, but Spring MVC abstracts a lot of boilerplate:

 No need for manual RequestDispatcher forwarding; just return a string.


 Automatic data binding of form inputs to objects (for creating employees, etc.).
 Easy integration of validation, conversion, etc.

6.2 Converting Servlets to Spring Controllers

Let’s convert our previous ListEmployeeServlet and AddEmployeeServlet to Spring MVC:


@Controller
public class EmployeeController {

@Autowired
private EmployeeService employeeService;

@GetMapping("/employees") // handles GET /employees to list all


public String listEmployees(Model model) {
List<Employee> employees = employeeService.getAllEmployees();
model.addAttribute("employeeList", employees);
return "employeeList"; // view name (Spring will resolve to employeeList.jsp)
}

@GetMapping("/employees/new") // show form


public String showNewEmployeeForm(Model model) {
model.addAttribute("employee", new Employee());
return "employeeForm"; // a JSP with form bound to 'employee'
}

@PostMapping("/employees") // handles form submission for creating employee


public String saveEmployee(@ModelAttribute("employee") Employee emp) {
employeeService.addEmployee(emp);
return "redirect:/employees"; // PRG: redirect to list after save
}
}

A few things to note:

 @Controller designates this class as a web controller (so it's also a candidate for component scanning
like @Component).
 We injected EmployeeService so we can call business methods.
 @GetMapping and @PostMapping are shorthand for @RequestMapping(method=GET/POST). The paths are
relative to a base (depending on how DispatcherServlet is mapped, often root).
 Methods return String which is interpreted as view name. We could also return ModelAndView or other
types, but simple string is fine for static view name.
 We directly use Model parameter to add attributes. Spring will provide a Model object when we
declare it in method signature.
 In the POST handler, we used @ModelAttribute("employee") Employee emp. This tells Spring to bind form
fields to an Employee object (property names must match). So if our employeeForm.jsp has form fields
with name="name", name="email", etc., Spring will populate a new Employee instance with those values
for us. This avoids manually calling request.getParameter.
 After saving, we return "redirect:/employees" to avoid double submission. redirect: prefix in view name
signals Spring to send a redirect.

We need to set up Spring MVC infrastructure:

 Declare DispatcherServlet in web.xml (if not using Spring Boot). For example:
 <servlet>
 <servlet-name>springDispatcher</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <init-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>/WEB-INF/spring-mvc-config.xml</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
 <servlet-name>springDispatcher</servlet-name>
 <url-pattern>/</url-pattern> <!-- map all to Spring -->
 </servlet-mapping>

and create spring-mvc-config.xml or corresponding Java config. This config would enable component
scanning (for controllers & other beans) and configure view resolver:
<context:component-scan base-package="com.example"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>

If we follow this, a return "employeeList" will resolve to /WEB-INF/views/employeeList.jsp.

We also need to integrate with our Spring IoC context from Week 5. There are two contexts: one is
the root (loaded by ContextLoaderListener with AppConfig) which holds services and repos, and
one is the DispatcherServlet context (for web components). Usually, the root context is a parent of
the servlet context. In XML config, we might do:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

to load AppConfig. Then DispatcherServlet will load its own. Beans in root (services, repos) are
accessible in controllers because DispatcherServlet’s context inherits from root.

 Or, simpler: we could combine all config in one if desired (for a small app), but knowing the
distinction is useful.

View (JSP) changes: Our JSP pages can now use Spring's model attributes and form tags:

 employeeList.jspcan remain similar, accessing ${employeeList} in JSTL or using <c:forEach>. Because we add
employeeList to model, Spring automatically exposes it to JSP (which is processed by JSTL).
 employeeForm.jsp (for new employee) could use Spring’s form tag library to bind to the employee
modelAttribute. For example:
 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
 <form:form modelAttribute="employee" action="${pageContext.request.contextPath}/employees" method="post">
 Name: <form:input path="name" /> <br/>
 Email: <form:input path="email" type="email" /> <br/>
 Position: <form:input path="position" /> <br/>
 Salary: <form:input path="salary" type="number" step="0.01" /> <br/>
 <input type="submit" value="Save"/>
 </form:form>

The Spring form tags know to get and set values from the employee model attribute. If we had errors
(via Spring's validation), we could also use <form:errors> tags.

Benefits observed:

 No need to manually extract request parameters or manually set as request attributes; Spring does
data binding and adds to Model behind scenes.
 Clear separation: Controller methods are concise and declarative.
 Easier to test controllers (you can test the method by simulating a Model and verifying outputs
without running a server, or using Spring’s MockMvc).
 The DispatcherServlet with its config handles view resolving and more, reducing boilerplate mapping
code in each servlet.

6.3 Testing Spring MVC EMS

Deploy the app with Spring MVC:

 Ensure all servlets from Week4 are removed or not conflicting (our DispatcherServlet mapping
might override them anyway).
 Access http://localhost:8080/YourApp/employees. Spring’s DispatcherServlet will call our listEmployees()
method, which fetches data and returns view. If correctly configured, you should see the list page
with employees.
 Try the "Add New Employee" flow:
o Go to /employees/new (we might have a link on list page pointing there). This should display the
form.
o Submit with details. Spring will bind to Employee, call saveEmployee(), and redirect. The new
employee should appear in the list (and in DB).
 Test without logging in if you removed login filter (since we haven't integrated Spring Security yet,
we might keep app open or implement a simple check manually in controller if desired).
 If any issue arises (like 404 mappings), check that your controller is being scanned and that the
DispatcherServlet mapping covers your URLs.

6.4 Mini-Project Task – Week 6

Migrate the web layer to Spring MVC:

 Create a Spring MVC configuration (either XML or Java class with @EnableWebMvc).
 Define a controller (or multiple) for handling EMS web routes (/employees, /employees/new, etc.).
 Remove the old servlets from deployment (or simply don’t invoke them).
 Update JSPs if needed to use Spring’s tags or at least to match model attribute names.
 Test all functionalities through the browser. The outcome should be identical to last week’s app
from user perspective, but internally, we are now using Spring MVC controllers calling Spring
services.

Summary – Week 6: Our application’s web layer is now powered by Spring MVC:

 The DispatcherServlet is fronting all requests and dispatching to appropriate controller methods.
 We defined Spring Controllers using annotations, which made the code succinct and removed a lot
of boilerplate. We utilize annotations like @GetMapping to map URLs to methods, and simple return
values for view names.
 We leveraged Spring’s model binding to automatically populate objects from form data and
simplified form handling with @ModelAttribute and form tags.
 The project structure is a proper 3-tier architecture now: controllers (web) -> services (business) ->
repositories (data). Spring manages the dependencies at each layer.
 This layered, Spring-powered setup is more professional and scalable. We can easily add features
like validation (Spring’s JSR303 support) or internationalization if needed without changing the
fundamental structure.
 With the core application in place, next we’ll use Spring Boot to further streamline configuration
and create RESTful APIs, and later integrate a modern frontend (React) to consume those APIs.

Week 7: Spring Boot – Rapid Application Development and REST APIs


Topics: Introduction to Spring Boot – a framework that builds on Spring to simplify configuration (no
more lengthy XML) and provide an embedded server. We will use Spring Boot to quickly set up our
application and focus on creating RESTful APIs for the EMS. By the end, we’ll have an Employee REST API
(endpoints returning JSON) running, which will be consumed by the React frontend later.

7.1 What is Spring Boot and Why Use It?

Spring Boot makes it easy to create stand-alone Spring applications with minimal fuss. “Spring Boot makes
it easy to create stand-alone, production-grade Spring-based applications with minimal configuration.”.
Key benefits:

 Starter dependencies: Bring in a bunch of relevant libraries with one dependency. E.g., spring-boot-
starter-web includes Spring MVC, Tomcat, Jackson (for JSON).
 Auto-configuration: Boot can auto-configure beans based on classpath. E.g., if mysql-connector-java is
on classpath and you set DB properties, it auto-configures a DataSource and JPA EntityManager (if
using Spring Data JPA).
 Embedded server: You can run the app as a jar with embedded Tomcat (no need to deploy to
external server), great for development and microservices.
 Actuator & more: Provides production features like monitoring with minimal setup (not our focus
now).

In short, Boot will reduce our boilerplate further. Our previous Spring MVC config can largely be replaced
by Boot's auto-config.
7.2 Initializing the Spring Boot Project

We typically create a Spring Boot project using Spring Initializr (start.spring.io) or via IDE. For a Full Stack
EMS, we want:

 Spring Web (for MVC/REST).


 Spring Data JPA (for database access via Hibernate).
 MySQL driver.
 Spring Boot DevTools (optional, for hot reloading).
 Possibly Thymeleaf if we were doing server-side views (but since we plan React, our focus is on
REST).

But we'll likely still use at least a simple HTML or two for demonstration or docs.

Using Spring Initializr or Maven coordinates:


<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- etc., possibly thymeleaf or validation -->
</dependencies>

This includes everything for web (Spring MVC + Tomcat) and JPA (Hibernate + Spring Data), and MySQL
driver.

We then create an Application class:


@SpringBootApplication // this includes @Configuration, @EnableAutoConfiguration, @ComponentScan
public class EmsApplication {
public static void main(String[] args) {
SpringApplication.run(EmsApplication.class, args);
}
}

Running this main method will start the Spring Boot app (Tomcat listening on port 8080 by default).

We need to configure database props in application.properties:


spring.datasource.url=jdbc:mysql://localhost:3306/EMS?useSSL=false
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update # auto-creates/updates tables based on entities
spring.jpa.show-sql=true # prints SQL for debug

Now, Boot will auto-configure a DataSource using these credentials, and because we have Spring Data
JPA, it expects entity classes.

7.3 Converting to Spring Data JPA Entities and Repositories

Rather than our manual EmployeeRepository with JDBC, we can use JPA:

 Mark Employee class with @Entity and @Table("employees"), and @Id on primary key field. Possibly use
@GeneratedValue(strategy=GenerationType.IDENTITY) if we rely on MySQL auto-increment.
 Use a Spring Data JPA Repository interface:
 import org.springframework.data.jpa.repository.JpaRepository;
 @Repository
 public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
 // JpaRepository provides CRUD methods out of the box
 // We can define custom query methods if needed, like:
 List<Employee> findByNameContaining(String keyword);
 }

Because we extend JpaRepository, Spring Data will provide implementation at runtime. Common
methods: findAll(), findById(), save(), deleteById(), etc., are inherited.

 Spring Boot will scan for repositories if @SpringBootApplication is in the same package or a parent
package (it scans sub-packages by default). Otherwise use @EnableJpaRepositories.

Now our EmployeeService can be simplified to use this repository:


@Service
public class EmployeeService {
@Autowired
private EmployeeRepository repo;
public List<Employee> getAllEmployees() { return repo.findAll(); }
public Employee getEmployeeById(int id) { return repo.findById(id).orElse(null); }
public Employee createEmployee(Employee emp) { return repo.save(emp); }
public void deleteEmployee(int id) { repo.deleteById(id); }
// etc...
}

We might not even need a separate service if logic is trivial, but it’s good practice to keep it for future
business logic or transaction management.

Exposing REST Controllers:


We will create REST controllers to provide JSON endpoints. Spring Boot with spring-boot-starter-web and
Jackson can automatically convert objects to JSON (via @ResponseBody or using @RestController).
Example:
@RestController
@RequestMapping("/api/employees")
public class EmployeeRestController {

@Autowired
private EmployeeService service;

@GetMapping
public List<Employee> getAllEmployees() {
return service.getAllEmployees();
}

@GetMapping("/{id}")
public ResponseEntity<Employee> getEmployee(@PathVariable int id) {
Employee emp = service.getEmployeeById(id);
if(emp != null) {
return ResponseEntity.ok(emp);
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
}

@PostMapping
public Employee createEmployee(@RequestBody Employee emp) {
// Assuming employee JSON is sent without id (or id ignored)
return service.createEmployee(emp);
}

@PutMapping("/{id}")
public ResponseEntity<Employee> updateEmployee(@PathVariable int id, @RequestBody Employee empDetails) {
Employee existing = service.getEmployeeById(id);
if(existing == null) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
// update fields
existing.setName(empDetails.getName());
existing.setEmail(empDetails.getEmail());
existing.setPosition(empDetails.getPosition());
existing.setSalary(empDetails.getSalary());
Employee updated = service.createEmployee(existing);
return ResponseEntity.ok(updated);
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteEmployee(@PathVariable int id) {
Employee existing = service.getEmployeeById(id);
if(existing == null) {
return ResponseEntity.notFound().build();
}
service.deleteEmployee(id);
return ResponseEntity.noContent().build();
}
}

Notes:

 @RestControlleris like @Controller + @ResponseBody on all methods, so each method returns data
(serialized to JSON) rather than a view.
 We use @RequestMapping("/api/employees") at class level to prefix all routes, and then specific method
mappings.
 @PathVariable to extract {id} from URL.
 @RequestBody to bind JSON request body to Employee object (needs default constructor and setters or
Lombok @Data to work).
 Return types: We use ResponseEntity for control over status codes (especially for not found, no
content). For simple cases (like GET all or POST returning created object), we can just return the
object (Spring will serialize and use 200 OK by default).
 We might add @CrossOrigin annotation on class or methods to allow our React app (likely running on
a different port) to call these APIs (CORS).

Testing the REST API:


Run the Spring Boot application (it will start on localhost:8080). Use a tool like Postman or curl:

 GET http://localhost:8080/api/employees -> should return JSON list of employees.


 GET http://localhost:8080/api/employees/1 -> returns single or 404 if not exist.
 POST http://localhost:8080/api/employees with JSON body:
 {
 "name": "John Doe",
 "email": "[email protected]",
 "position": "Developer",
 "salary": 60000
 }

should create and return the created employee (with an id).

 PUT to update, DELETE to remove.


Check database to ensure changes reflect.

Spring Boot by default returns JSON in response because it auto-configures Jackson (provided by starter-
web) and message converters.

7.4 Spring Boot and Project Simplification

Notice how many configurations were eliminated:

 No web.xml; Spring Boot auto-configures DispatcherServlet.


 No separate application context config; @SpringBootApplication took care of component scan and
autoconfig. Our EmployeeRepository interface was picked up by Spring Data and implemented at
runtime.
 The app can be run by just running the main class. We can package it as a jar (mvn package) and run
java -jar emsapp.jar to start the server, which makes deployment easier (one jar contains everything
including Tomcat).

We should also ensure to disable or secure the old JSP pages if any left. But since the final UI will be
React, we might drop server-side HTML altogether or keep just for admin/troubleshooting.

One more Boot feature: Spring Boot Actuator if we include it, can give health endpoints, metrics, etc.
Another nice feature is using spring-boot-devtools for auto-restart on code changes during dev, and using
application.properties to configure logging, etc.

7.5 Mini-Project Task – Week 7

Migrate the application to Spring Boot:

 Create a new Spring Boot project (or modify existing) with the necessary starters.
 Configure database connection in application.properties.
 Mark Employee as JPA @Entity and create a Spring Data JPA repository for it.
 Replace manual JDBC code with repository calls. (Your service might now call
employeeRepository.findAll() etc. through Spring Data).
 Implement REST controller(s) for employee operations as above.
 Test all API endpoints thoroughly (GET all, GET one, POST, PUT, DELETE). Use Postman or curl
and verify database changes.
 The output of this week is a RESTful backend ready for integration with a frontend. Optionally,
document the API (you could integrate Swagger via springdoc-openapi for interactive docs, as
mentioned).
 (Optional) Also verify that if you run the Boot app, the old Spring MVC controllers or JSPs if
present are either working or disabled as needed. We mainly need the REST now.

Summary – Week 7: We introduced Spring Boot and transformed our application:

 Eliminated a lot of configuration overhead by using Boot’s auto-configuration and starters. Our app
is now packaged and run as a self-contained unit.
 Built a full REST API for Employee management following REST principles (stateless operations on
resources identified by URIs, returning JSON).
 Using Spring Data JPA, we abstracted away the low-level SQL. We defined an Employee entity and an
interface EmployeeRepository that Spring implemented at runtime, giving us CRUD operations with one
line of code.
 Our service/business logic can still enforce rules, but much of the repetitive code is gone, thanks to
JPA and Boot.
 We have set up the foundation for the frontend integration: the React app will communicate with
these /api/employees endpoints to display and modify data.

At this point, our backend is essentially complete and professional-grade: a Spring Boot RESTful service
with a proper structure (controllers, services, repositories, entities). Next, we will ensure some basics of
frontend (HTML, CSS, JS) are understood and then dive into building the ReactJS client for this API.

Week 8: Hibernate ORM and Advanced JPA (Relationships & HQL)


Topics: Delving into Hibernate ORM and JPA features – mapping relationships (One-to-Many, Many-to-
One between entities), using HQL/JPQL for queries, and understanding the power of an ORM. Although
our EMS is simple (single table), we will discuss how to extend it (e.g., employees belong to departments)
to demonstrate relationships. We’ll also ensure our JPA usage is optimized (e.g., lazy vs eager loading,
etc.).

(Note: Much of this week overlaps with what we already did using Spring Data JPA in Week 7. We will
reinforce those concepts and go a bit deeper.)

8.1 Review: Object-Relational Mapping with Hibernate/JPA

Hibernate is the implementation of JPA we’re using (Spring Boot starter brings in Hibernate). It maps Java
classes to database tables and manages state of objects:

 We annotate Java classes to represent tables, and relationships via annotations like @OneToMany,
@ManyToOne, etc.
 JPA allows us to write queries in terms of objects (JPQL or HQL) instead of raw SQL.

In our EMS, Employee is mapped to employees table. If we had another entity, say Department, we might map
like:
@Entity
@Table(name="departments")
public class Department {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(mappedBy="department", cascade=CascadeType.ALL)
private List<Employee> employees;
// getters, setters
}

And in Employee:
@ManyToOne
@JoinColumn(name="dept_id")
private Department department;

This indicates each employee row has a dept_id foreign key referencing departments(id). With
mappedBy="department" in Department, it means the employees list is mapped by the department field in
Employee. CascadeType.ALL means if we persist a Department, all its employees are persisted too (if
new).

Using Spring Data JPA, if we had a DepartmentRepository extends JpaRepository<Department, Integer> and
EmployeeRepository as before, we could:

 Find all employees of a department either via a query method (findByDepartmentId(int deptId)) or by
accessing dept.getEmployees() if the collection is loaded.

We should consider fetch types: by default, @OneToMany is LAZY (meaning dept.getEmployees() will fetch
from DB only when accessed), and @ManyToOne is EAGER (employee.getDepartment() fetched
immediately). For efficiency, we might leave it default or tune as needed.

HQL/JPQL: These are query languages similar to SQL but use entity/class names and property names.
Example JPQL:
@Query("SELECT e FROM Employee e WHERE e.salary > :minSal")
List<Employee> findHighEarners(@Param("minSal") float minSal);

Spring Data allows writing such queries in @Query annotation on repository methods. Or we can use the
repository’s derived query keywords for many cases (e.g., findByDepartmentName(String name) – Spring will
auto-generate the query to join Employee and Department to filter by department’s name).

While our current application likely doesn't need custom JPQL since basic CRUD is enough, knowledge of
JPQL/HQL matters for more complex filtering or batch updates.

Transactions: Spring Data JPA repository methods are transactional by default (the starter configures
transaction manager). Our service can also use @Transactional if we want a method to ensure atomicity
across multiple operations.

8.2 Using Hibernate Console (optional)

For learning, one can enable SQL logging (we did with spring.jpa.show-sql=true) to see the queries being run.
It’s instructive to see how hibernate does lazy loading, etc. We might also use logging for
org.hibernate.SQL and org.hibernate.loader to understand performance.

Second-level cache (EhCache, etc.) or other advanced Hibernate features are beyond scope, but good to
be aware that JPA can cache entities across sessions to reduce DB hits if configured.

8.3 Ensuring ORM-backed Model in EMS

Given our EMS is now ORM-backed, some tasks:

 Confirm that Employee entity is correct and table is in sync. The ddl-auto=update property in Boot will
auto create/alter tables. For production, one might use migrations instead, but for dev this is fine.
 If we had added Department entity, check Boot created the department table and the foreign key in
employees.

We might not actually implement departments in code since original scope didn’t specify, but it was listed
as Capstone idea suggestion. However, explaining it meets the Week 8 objective of showing relationships.

As an exercise:
Create a Department entity, repository, and a small piece of UI or API to link employees to departments.
For example:

 Add a field deptId in Employee DTO/JSON to assign department when creating employee through
REST.
 In EmployeeRestController.createEmployee, after service.createEmployee(emp), if you wanted to include
department, you’d need to fetch the Department object and set it to employee before saving, since
JPA needs actual object or id mapping.
 If DepartmentRepository exists, dept = deptRepo.findById(deptId).orElseThrow(), then emp.setDepartment(dept).
This shows how ORM manages references: after saving, emp.getDepartment().getName() would be accessible,
possibly lazy loaded if not fetched earlier.

HQL Example in context: Perhaps define in EmployeeRepository:


@Query("FROM Employee e WHERE e.department.name = :deptName")
List<Employee> findByDepartmentName(@Param("deptName") String deptName);

This would allow retrieving employees by department using a join internally.

8.4 Mini-Project Task – Week 8

 If not already, ensure Employee is a proper JPA entity with any needed annotations (@Id, etc.).
 Expand the data model by adding a related entity (Department). Connect employees to
departments with JPA annotations.
 Update the REST API if needed to handle department info (maybe add endpoints for departments,
or include department details in employee JSON).
 Use repository methods or JPQL to implement a feature like "List employees by department" or "List
employees with salary above X".
 Test these new queries or relationships via API calls.

Summary – Week 8: We reinforced our understanding of ORM (Object-Relational Mapping) in Java:

 Configured JPA/Hibernate through Spring Data JPA. Without writing SQL, we can manipulate
database records by operating on Java objects. For example, calling employeeRepository.save(emp)
behind the scenes performs an INSERT or UPDATE.
 Mapped relationships using annotations like @OneToMany and @ManyToOne, which let us navigate
between entities in Java just as naturally as linking objects in memory, while Hibernate handles the
foreign key constraints in the DB.
 Discussed HQL/JPQL, which provide database querying capability in object terms (e.g., using entity
attributes in queries rather than column names), making it easier to maintain queries when the
database schema or class structure changes.
 Ensured our EMS is truly an ORM-backed model – meaning our primary way of interacting with the
data is via the JPA entity model (Employee objects and EmployeeRepository), not via hand-written SQL or
result sets.
 These abstractions will let us develop faster (no need to convert between JDBC ResultSet and
objects manually) and with less error-proneness. We also gained database independence to a
degree; switching to another SQL database (PostgreSQL, etc.) would be as simple as changing the
JDBC URL and driver dependency, since our code is not MySQL-specific (this is one benefit of using
JPA).

Now our backend is fully fleshed out. In the final stretch, we turn to the frontend technologies: first
revisiting basics of web frontend (HTML, CSS, JS) in Week 10, then building the React app in Week 11,
and finally wrapping up the integrated project in Week 12.

(Weeks 9 and 10 in the curriculum focus on RESTful services (which we have done in week 7/8) and
frontend basics respectively. We've somewhat merged RESTful service creation into week 7. We'll proceed
to Week 10 now.)

Week 9: (Buffer/Extended REST) – (This week is often about documenting


APIs with Swagger and maybe securing them. We’ll mention Swagger
since the curriculum noted Swagger docs for REST. We can include an
intro to Swagger.)
(The original plan had Week 9 as RESTful Services in general. We already built REST APIs. We can use this
week to discuss REST API best practices, JSON format, and documenting APIs with Swagger/OpenAPI.)

Topics: Deepening understanding of REST principles, ensuring our API follows best practices (correct use
of HTTP methods and status codes, statelessness, resource-based URLs). Introduce Swagger/OpenAPI for
API documentation. Possibly mention using Postman or writing integration tests for the API.

9.1 REST API Design Best Practices


Our /api/employees API already adheres to a typical RESTful pattern:

 Resource URI: /employees represents the collection, /employees/{id} for single resource.
 HTTP Methods: GET for read, POST for create, PUT for update (replace) – though one might use
PATCH for partial update, and DELETE for delete.
 Status Codes: We used 200 OK, 201 Created (if we adjust POST to return that), 204 No Content
for delete, 404 Not Found when appropriate. Using correct codes is important for clients to
interpret responses.
 Hypermedia (HATEOAS): We won’t dive deep, but a truly RESTful service might include links in
responses for navigation. For example, each Employee JSON might contain a link to itself or related
resources. Spring has Spring HATEOAS to assist, but that’s advanced usage.

JSON format: We by default produce JSON via Spring Boot. It’s human-readable and widely accepted.
We might ensure consistency in field naming (maybe lower_case or camelCase, and not leaking internal
DB ids if not needed). In our case, the JSON of Employee likely includes all fields. We might also consider
not exposing certain fields (like if there were passwords, etc., but in EMS it's fine). Jackson can be
configured to ignore fields via annotations.

Versioning: Over time, one might need to version APIs (e.g., /api/v1/ vs /api/v2/ or via headers) – a note
for future extension but not needed now.

Security: Our API as is open. In real scenario, we'd protect it (via tokens, etc., often using Spring Security
+ JWT). This might be beyond our current scope, but it's worth noting that a production REST API should
have authentication/authorization so only authorized users can perform certain actions. Possibly an admin
role to add/delete employees, etc.

9.2 API Documentation with Swagger (OpenAPI)

To help consumers of our API (like front-end developers), documenting it is crucial. Swagger (now
OpenAPI specification) is a standard for describing REST APIs. Springdoc or Springfox can generate a
Swagger UI and JSON spec from our controllers.

We can integrate springdoc-openapi:


Add dependency:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.9</version>
</dependency>

This auto-generates OpenAPI docs and provides Swagger UI at /swagger-ui/index.html (and JSON at /v3/api-
docs) by default in Spring Boot.

We can enhance documentation using annotations:


@RestController
@RequestMapping("/api/employees")
@Tag(name = "Employee", description = "Employee management APIs")
public class EmployeeRestController {

@Operation(summary = "Get all employees", description = "Returns a list of all employees")


@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "List of employees")
})
@GetMapping
public List<Employee> getAllEmployees() { ... }

@Operation(summary = "Get an employee by ID")


@ApiResponses({
@ApiResponse(responseCode = "200", description = "Employee found"),
@ApiResponse(responseCode = "404", description = "Employee not found")
})
@GetMapping("/{id}")
public ResponseEntity<Employee> getEmployee(@PathVariable int id) { ... }

// ... similarly for other endpoints


}

With these, the Swagger UI will show descriptions for each operation, parameter, response codes, etc.
Testing with Swagger UI: Run the app and navigate to http://localhost:8080/swagger-ui/index.html. You should
see a UI listing the Employee API endpoints, models, etc., and can even execute test calls from the
browser.

This makes it easier for developers (e.g., React devs) to understand how to use the API, without reading
code.

9.3 Using Postman for API Testing

We likely have already tested with Postman. It’s good to mention using Postman:

 You can create a collection of requests for employees, with examples for each operation, and even
write tests (Postman scripts) to automate API testing.
 In a team, Postman collections or Swagger docs can be shared with frontend devs to guide their
integration.

9.4 Mini-Project Task – Week 9

 Integrate Swagger/OpenAPI in the Spring Boot project. Verify that API docs are generated correctly.
 Write meaningful annotations for documentation if time permits, or at least verify that the basics
(path, methods, etc.) appear.
 Optionally, write a simple integration test or two using Spring’s MockMvc to programmatically call
the API and assert responses (this can ensure your API works as expected and catches regressions).
 Prepare for front-end usage: e.g., if any adjustments needed to make the API more convenient for
the React app (maybe add an endpoint for a summary or something).

Summary – Week 9: Our RESTful service is refined and documented:

 We ensured our design aligns with REST principles (proper use of methods, status codes, and
stateless handling of requests).
 Implemented API documentation using Swagger/OpenAPI, which generates an interactive UI for
exploring and testing our API endpoints. This will be incredibly useful for front-end integration and
for any future developers on the project, as they can see what endpoints exist and what data they
expect.
 Learned that thorough documentation and testing of an API are as important as the implementation
– they improve reliability and ease integration.
 With a robust, well-documented Employee Management API in place, the stage is set to develop a
rich client-side application.

Now we pivot to the frontend side. Next, we will brush up on foundational web frontend technologies
(HTML, CSS, JavaScript) which underpin frameworks like React, and then proceed to build the React
application that will serve as the user interface for our EMS.

Week 10: Frontend Basics – HTML5, CSS3, and JavaScript Essentials


Topics: A crash course in core web frontend technologies:

 HTML5 – structuring content with elements.


 CSS3 – styling content (layout, colors, fonts, responsive design basics).
 JavaScript (ES6+) – making pages dynamic; we’ll also touch on how vanilla JS can interact with
REST APIs (using Fetch API).
 We’ll also mention modern tooling (like bundlers) and maybe a CSS framework (Bootstrap) since it
was listed, to quickly make things look decent.

This knowledge will be directly useful when we start building with React (which uses JSX, similar to
HTML, and CSS for styling, and obviously JavaScript for logic).

10.1 HTML5 – Structure of Web Pages

HTML (HyperText Markup Language) provides the structure of web pages. It uses elements denoted by
tags (e.g., <p> for paragraph, <h1> for a top-level heading, etc.). HTML5 introduced semantic elements
like <header>, <footer>, <article>, <section> to better organize content.

A basic HTML5 page boilerplate:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Employee Management System</title>
</head>
<body>

<header>
<h1>Employee Management System</h1>
</header>

<main>
<section id="employee-list">
<h2>Employees</h2>
<table>
<tr><th>ID</th><th>Name</th><th>Position</th></tr>
<!-- Data rows will go here -->
</table>
</section>
<section id="employee-form">
<h2>Add Employee</h2>
<form id="addEmpForm">
Name: <input type="text" name="name" required><br/>
Email: <input type="email" name="email" required><br/>
Position: <input type="text" name="position"><br/>
Salary: <input type="number" name="salary" step="0.01"><br/>
<button type="submit">Add</button>
</form>
</section>
</main>

<footer>
<p>&copy; 2025 My Company</p>
</footer>

</body>
</html>

Key points:

 The <!DOCTYPE html> declares HTML5.


 <meta name="viewport" ...> is important for mobile responsiveness (makes layout scale to device
width).
 We organized content into semantic sections. This aids both in clarity and accessibility (screen
readers, etc., know the structure).
 Forms have fields with attributes like required which is HTML5 validation. The form has an id so we
can target it in JS.

“HTML describes the structure of a web page”: indeed, we use tags to mark headings, paragraphs, lists,
etc. The content itself (text like "Employees") is inside these tags. For a developer, HTML is about
choosing the right tags for the content.

Common HTML elements:

 Headings: <h1> to <h6> (h1 is largest/most important).


 Paragraph: <p>.
 Links: <a href="..."> (hyperlinks to other pages).
 Lists: <ul> (unordered/bullet list), <ol> (ordered/numbered list), with <li> for each item.
 Tables: <table>, with <tr> (row), <th> (header cell), <td> (data cell).
 Forms: <form> which can contain <input>, <select>, <textarea>, etc., and a submit <button>.
 Semantic divisions: <div> (generic block) and <span> (generic inline) are often used for grouping, but
HTML5 adds <section>, <article>, <nav>, etc. which convey meaning.

Bootstrap (CSS Framework):


HTML by itself is unstyled beyond a browser’s default. A CSS framework like Bootstrap provides ready-
made styles for layout and components. For example, using Bootstrap classes, we could turn our form
and table into a nicely padded, responsive layout by adding class attributes:
<table class="table table-striped">
<!-- ... -->
<form id="addEmpForm" class="form">
<!-- form fields with classes like form-control on inputs -->
Bootstrap also has a grid system for layout. It's not mandatory to use, but it speeds up development. We
might use it in React for consistency (React can use Bootstrap via CSS or libraries like React-Bootstrap).

10.2 CSS3 – Styling and Layout

CSS (Cascading Style Sheets) controls the presentation (visual style) of HTML elements. You can set colors,
fonts, positioning, etc. CSS3 adds features like transitions, transforms, flexbox and grid for layout.

We can apply CSS in three ways:

 Inline (avoid when possible): e.g., <p style="color:blue">.


 Internal (within <style> tag in head): good for single-page specific styles.
 External stylesheet (recommended): <link rel="stylesheet" href="styles.css"> in head.

Example CSS:
body {
font-family: Arial, sans-serif;
margin: 20px;
}
header, footer {
background-color: #f8f9fa;
padding: 10px;
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
table, th, td {
border: 1px solid #ddd;
}
th, td {
padding: 8px;
}
th {
background-color: #343a40;
color: #fff;
}
form {
max-width: 300px;
background: #f1f1f1;
padding: 10px;
}
form input {
width: 100%;
margin-bottom: 5px;
padding: 5px;
}

This CSS:

 Sets a global font and margin on body.


 Styles header/footer with light background and center text.
 Makes table full-width, collapses borders (makes it a single border grid), and adds border to cells.
 Styles the table header with dark background and white text.
 Form styling: give it a light gray background and padding, make inputs full width.

Result: A modestly styled page: table headers have a dark band, there's spacing in table cells, form inputs
stretch the form width, etc.

Responsive design: Notice we included <meta viewport>. That ensures on small screens, the CSS is
interpreted relative to device width. We could use CSS media queries to adjust layout for mobile. E.g.:
@media (max-width: 600px) {
table, thead, tbody, th, td, tr {
display: block; /* stack cells vertically on narrow screens */
}
}

This would transform the table to a block layout on small devices (each cell as a row). However, often
we rely on frameworks like Bootstrap which handle a lot of responsiveness with classes.
CSS Flexbox and Grid: Modern CSS provides powerful layout. For example, to layout two sections side
by side:
main {
display: flex;
}
#employee-list, #employee-form {
flex: 1;
margin: 10px;
}

This would place the two sections side by side taking equal space, with margin around them.

10.3 JavaScript – Making Pages Dynamic

JavaScript is the programming language of the web – it runs in the browser, enabling interactivity.
Modern JavaScript (ES6 and beyond) introduced many features (let/const, arrow functions, promises,
modules, etc.).

We will use JavaScript to call our REST API and update the HTML dynamically, which is essentially what
React does but React provides a structured way (with components and virtual DOM). Understanding
how to do it manually is enlightening:

 Use DOM API to select elements and manipulate them (like filling the table with data).
 Use Fetch API or XMLHttpRequest to make HTTP requests to our backend.

For example, using Fetch (which returns promises):


// Let's fetch and display employees on page load
async function loadEmployees() {
try {
let response = await fetch('http://localhost:8080/api/employees');
if(!response.ok) throw new Error("Failed to load");
let employees = await response.json();
const table = document.querySelector('#employee-list table');
// clear any existing rows (except header)
table.querySelectorAll('tr:not(:first-child)').forEach(tr => tr.remove());
employees.forEach(emp => {
const row = document.createElement('tr');
row.innerHTML = `<td>${emp.id}</td><td>${emp.name}</td><td>${emp.position}</td>`;
table.appendChild(row);
});
} catch(err) {
console.error("Error loading employees", err);
}
}

document.getElementById('addEmpForm').addEventListener('submit', async function(e) {


e.preventDefault(); // prevent form from refreshing page
const form = e.target;
const empData = {
name: form.name.value,
email: form.email.value,
position: form.position.value,
salary: parseFloat(form.salary.value)
};
try {
let res = await fetch('http://localhost:8080/api/employees', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(empData)
});
if(res.ok) {
form.reset();
loadEmployees(); // refresh list
} else {
alert("Failed to add employee");
}
} catch(err) {
console.error("Error adding employee", err);
}
});

// Initial load
loadEmployees();

This script:
 Defines loadEmployees() which fetches JSON from our API and populates the table by creating rows
and inserting into DOM.
 Attaches a submit event to the form, which on submission collects the input values into an object
empData, sends a POST request with JSON body to the API, then on success, resets the form and
reloads the list.
 Uses async/await for readability (ES2017 feature).
 Relies on CORS being allowed – since our API is on localhost:8080 and if our static page is served from
say file:// or another port, the browser would block cross-origin. We would need to enable CORS on
the backend (@CrossOrigin or config) to allow this. In development, we might serve the front-end
from an HTTP server on a different port (React dev server uses 3000) – thus we'll configure CORS
or use a proxy.

This is essentially what a simplistic single-page app looks like without frameworks: manual DOM updates
and fetch calls. It's manageable for very small apps, but can become messy as the app grows (lots of DOM
manipulation, state management issues). This is why frameworks like React exist – they provide a structure
and automate the DOM updating (via re-rendering components when state changes).

Yet, understanding this under-the-hood mechanism is key to understanding what React abstracts.

10.4 Tooling and Build (briefly)

Modern web development often uses tools:

 npm (Node Package Manager) to manage front-end libraries.


 Build tools/bundlers like webpack, or frameworks' CLIs (Create React App uses webpack under the
hood) to compile and bundle code (especially since React uses JSX which is not directly browser-
executable, and also to transpile advanced JS for older browsers, etc.)

In this course context, by Week 11 we’ll likely use Create React App to scaffold the React project, which
sets up all this tooling. It's good to mention that behind the scenes, CRA uses Babel (for transforming
JSX/ES6) and webpack (for bundling modules and assets).

Also mention VS Code as a popular editor for front-end (the curriculum listed VS Code as a tool,
presumably for front-end dev).

10.5 Mini-Project Task – Week 10

 Create a basic static HTML/CSS/JS page as outlined, and try integrating it with the running backend
using pure JavaScript (this was somewhat done in the script above).
 Ensure CORS is enabled on the Spring Boot app (@CrossOrigin(origins="*", allowedHeaders="*") on
controller or global config) so that the static page (if opened from file or another server) can call the
API. (In production, you'd serve the built React app from the same domain or properly configure
CORS for specific domains).
 This exercise is partly for learning; once React app is built, we’ll replace this manual page with a
React-based one. But attempting this helps appreciate what React will simplify.

Summary – Week 10: We revisited the fundamentals of front-end web development:

 HTML5: The foundation that defines content structure. We saw how HTML is used to mark up
headings, tables, forms, etc., forming the skeleton of our pages. Semantic elements help convey
meaning, and we used them in structuring EMS page.
 CSS3: The styling layer that makes the app visually appealing and responsive. We applied CSS rules
to style our EMS page (colors, spacing, layout) and touched on modern layout techniques like
flexbox for responsiveness. We also discussed using frameworks like Bootstrap to accelerate styling.
 JavaScript: The engine of interactivity. We wrote a simple script to turn our static page into a
dynamic one that communicates with the back-end via AJAX (Fetch API) calls. This demonstrates
how to manipulate the DOM and handle user events (form submission) in vanilla JS.
 We prepared ourselves for ReactJS by understanding how a basic single-page behavior can be
achieved with JS. React will use these same fundamentals (JS to manipulate DOM, fetch to get data)
but in a more structured and powerful way, allowing us to build a larger application with ease.
 Having mastered these basics, we are ready to dive into ReactJS, using our knowledge of
components (like grouping HTML structure), state management, and API calls in the React
paradigm.
Week 11: ReactJS – Building the EMS Frontend
Topics: Introduction to ReactJS and modern front-end development. We will create a React application
for the EMS. Key concepts:

 JSX syntax and React Components.


 State and Props for managing data in components.
 Hooks (especially useState and useEffect for state and lifecycle respectively).
 Calling REST APIs from React (using fetch or axios in useEffect).
 React Router for navigation (if multiple pages, e.g., a page for list and a page for edit form).
 We will use functional components and hooks since class components are older approach.
 Possibly use a UI library or Bootstrap for styling to save time.

By end of week, we should have a working React front-end that interacts with our Spring Boot API to list,
add, update, delete employees.

11.1 Setting Up React Project

We use Create React App (CRA) for scaffolding:


npx create-react-app ems-frontend

This sets up a React project with everything (Webpack, Babel) configured.

Project structure key points:

 src/index.js– entry point, renders <App /> component into the root DOM.
 src/App.js – main component we can start editing, or we create our own.

We ensure to run the dev server:


cd ems-frontend
npm start

This starts on http://localhost:3000/.

We likely need to enable CORS or use a proxy for API calls. In package.json, we can add:
"proxy": "http://localhost:8080"

This way, when our React app calls /api/employees, the dev server will proxy to localhost:8080, avoiding CORS
issues in development.

Alternatively, use full URLs and configure backend CORS to allow localhost:3000. For development, CRA
proxy is easiest.

11.2 React Components, JSX, and State

JSX: React's syntax extension that looks like HTML in JS. Eg:
function App() {
return (
<div>
<Header title="Employee Management System" />
<EmployeeList />
</div>
);
}

JSX is not a string or HTML, it's syntax that Babel transforms to React.createElement calls. But thinking of it as
writing HTML inside JavaScript is fine. We can embed variables with curly braces in JSX (e.g.,
<h2>{employee.name}</h2>).

Functional Components and Hooks: We will primarily use these:

 Each component is a function that returns JSX.


 useState hook to manage component state (e.g., list of employees).
 useEffect hook to perform side effects like data fetching on component mount or when dependencies
change (like componentDidMount and componentDidUpdate unified).
 Possibly useRef if needed for form ref, but not necessary here.
Let's outline components we might have:

 App – main component (could hold state, but we might delegate).


 EmployeeList – displays the list of employees (table).
 EmployeeForm – form to add a new employee.
 We could also have an EmployeeRow component for each row, but not mandatory.
 If we do edit functionality in a separate view, maybe an EmployeeEdit component that shows a form
for editing (which might reuse EmployeeForm).

For simplicity, perhaps we incorporate add and list in one page (like earlier static version). But let's think:
Maybe we want to demonstrate React Router:

 Page for listing and adding (like a dashboard).


 Page for editing an employee (navigated to when clicking an employee row or an edit button).
However, given time, we could also do a modal for edit or inline editing.

But the curriculum specifically listed React Router in breakdown:


(Under Week 11: "ReactJS JSX, Components, Hooks, API Calls (React UI with REST API)")

Yes, it expects multi-component architecture and API integration, but maybe not necessarily separate
routes. But often they include Router as a key point to cover.

We'll include a simple Router usage:


Using react-router-dom (which CRA likely included v17 or if using v18 we need to do npm install react-router-
dom@6 perhaps).
Set up:
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>{" | "}
<Link to="/add">Add Employee</Link>
</nav>
<Routes>
<Route path="/" element={<EmployeeList />} />
<Route path="/add" element={<EmployeeForm />} />
<Route path="/edit/:id" element={<EmployeeForm />} />
</Routes>
</Router>
);
}

We include navigation links (just for example).


Routes:

 "/" shows EmployeeList component (which might also include a button/link to Add).
 "/add" shows EmployeeForm for new employee.
 "/edit/:id" shows EmployeeForm but for editing existing (we can detect if id param exists to fetch
that employee and populate form).

EmployeeList component with Hooks:


import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

function EmployeeList() {
const [employees, setEmployees] = useState([]);
const navigate = useNavigate();

useEffect(() => {
fetch('/api/employees')
.then(res => res.json())
.then(data => setEmployees(data))
.catch(err => console.error("Error fetching employees", err));
}, []); // empty dependency -> runs once on mount

const deleteEmployee = id => {


fetch(`/api/employees/${id}`, { method: 'DELETE' })
.then(res => {
if(res.status === 204) {
setEmployees(employees.filter(emp => emp.id !== id));
} else {
console.error("Delete failed");
}
});
};

return (
<div>
<h2>Employees</h2>
<table border="1">
<thead>
<tr><th>Name</th><th>Position</th><th>Actions</th></tr>
</thead>
<tbody>
{employees.map(emp => (
<tr key={emp.id}>
<td>{emp.name}</td>
<td>{emp.position}</td>
<td>
<button onClick={() => navigate(`/edit/${emp.id}`)}>Edit</button>
<button onClick={() => deleteEmployee(emp.id)} style={{marginLeft:'5px'}}>Delete</button>
</td>
</tr>
))}
</tbody>
</table>
<button onClick={() => navigate('/add')}>Add Employee</button>
</div>
);
}

Here:

 fetches employee data on component load.


useEffect
 We store employees in state with setEmployees. When state updates, React re-renders to reflect new
state (so removing an employee updates the list automatically after filtering it out).
 Provided Delete function calls backend, then updates state by removing from list if successful.
 Provided an Edit button to navigate to edit page, and an Add button to navigate to add page. We
use useNavigate hook from router for programmatic navigation.

EmployeeForm component:
import { useState, useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';

function EmployeeForm() {
const [employee, setEmployee] = useState({ name:'', email:'', position:'', salary:'' });
const navigate = useNavigate();
const { id } = useParams(); // will be undefined for add, or an id string for edit

useEffect(() => {
if(id) {
// fetch existing employee to edit
fetch(`/api/employees/${id}`)
.then(res => res.ok ? res.json() : Promise.reject("Failed to load"))
.then(data => setEmployee(data))
.catch(err => console.error(err));
}
}, [id]);

const handleChange = e => {


const { name, value } = e.target;
setEmployee(prev => ({ ...prev, [name]: value }));
};

const handleSubmit = e => {


e.preventDefault();
const method = id ? 'PUT' : 'POST';
const url = id ? `/api/employees/${id}` : '/api/employees';
fetch(url, {
method: method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(employee)
})
.then(res => {
if(res.ok) navigate('/');
else return Promise.reject("Save failed");
})
.catch(err => console.error(err));
};

return (
<div>
<h2>{id ? "Edit Employee" : "Add Employee"}</h2>
<form onSubmit={handleSubmit}>
<div>
<label>Name: </label>
<input name="name" value={employee.name} onChange={handleChange} required />
</div>
<div>
<label>Email: </label>
<input name="email" type="email" value={employee.email} onChange={handleChange} required />
</div>
<div>
<label>Position: </label>
<input name="position" value={employee.position} onChange={handleChange} />
</div>
<div>
<label>Salary: </label>
<input name="salary" type="number" value={employee.salary} onChange={handleChange} />
</div>
<button type="submit">{id ? "Update" : "Save"}</button>
<button type="button" onClick={() => navigate('/')}>Cancel</button>
</form>
</div>
);
}

Explanation:

 If id param exists, on mount (useEffect) we fetch that employee and populate form state.
 We use employee state object to bind input values (value={employee.name} etc.) and a single handleChange
to update state on any input change. This is a controlled component approach.
 On submit, we decide the method and URL based on whether we're editing or adding. We then
fetch with method and JSON body from state.
 On success, navigate back to home (list) page, where changes should reflect (if we added new or
updated, the list ideally should refresh. We didn't explicitly refresh in code, but since we navigated
home, our EmployeeList useEffect will run again and fetch fresh data. Alternatively, we could have
passed state or updated a context, but fetching again is fine for simplicity).
 Cancel button navigates back without saving.

One might wonder why not keep list in a global state or context so that when we add we can push to it
directly without re-fetching. That is an optimization which could be done (using React Context or a state
management library). For our scale, re-fetching isn't bad and keeps it simple.

Using Axios: Instead of fetch, many use axios for simpler syntax. It's not necessary but could mention:
axios.get('/api/employees').then(res => setEmployees(res.data));

and likewise for post, which returns promise etc. Our fetch usage is straightforward enough.

Styling in React: We can reuse our CSS from static version by importing in React. Or use Bootstrap by
adding it:
npm install bootstrap

Then in index.js or App.js:


import 'bootstrap/dist/css/bootstrap.min.css';

and apply classes accordingly as per Bootstrap docs (like className in JSX).

We may keep styling minimal here due to focus on functionality.

11.3 Running and Testing the React App

Start the dev server (if not already). Ensure Spring Boot backend is running on 8080. The React app will
proxy API calls to 8080 because of our package.json proxy.

Test flows:
 Load the app (http://localhost:3000). You should see "Employees" heading and maybe table (if DB
had employees).
 Try Add Employee: click Add or go to /add (the link or button will do that). Fill the form, submit. It
should navigate to home, and the new employee appears in list.
 Try Edit: if list shows entries with Edit button, click one. It should route to /edit/:id, form populates
(after fetch). Modify something, submit. Back to list, see changes.
 Try Delete: clicking delete should remove entry from state immediately after successful response (we
did filter and set state).

Watch console for any errors. The usual issues: CORS (if proxy not set or if hitting wrong URL), maybe a
small bug in code. But overall, this is the typical pattern for CRUD.

11.4 Mini-Project Task – Week 11

Build the React frontend:

 Use CRA to set up project.


 Implement components for listing and adding/editing employees, using hooks and functional
components.
 Integrate with the REST API: use fetch/axios to GET list and to POST/PUT new or updated data, etc.
 Use React Router for navigation between list and form pages (optional but good practice).
 Ensure the UI is user-friendly: add basic validations (HTML required attributes we did, and perhaps
some simple checks or messages).
 Style using either plain CSS or a library. (At least ensure it looks neat with some margins/padding,
maybe a bit of Bootstrap or similar.)
 Test thoroughly: create, update, delete, and verify changes reflect without manual page reload, and
also confirm via backend (database or swagger or Postman) that operations indeed happened.

Summary – Week 11: We successfully built a ReactJS frontend for our application:

 Created multiple components to encapsulate our UI sections (list, form, etc.), demonstrating
component-based architecture. Each component manages its own state and UI rendering, making
the app modular and easier to maintain.
 Used JSX to write components – which allows us to mix HTML-like syntax with dynamic
expressions, making UI code intuitive yet powerful.
 Leveraged React Hooks: useState to handle component state (like the list of employees or form
inputs) and useEffect to perform data fetching on component load. This allowed us to hook into the
component lifecycle without class components.
 Our React app communicates with the Spring Boot REST API using fetch/axios, demonstrating how
a modern SPA (Single Page Application) operates by asynchronously loading and modifying data in
the background. The UI updates smoothly based on state changes (e.g., after adding an employee,
we update state or re-fetch, and React re-renders the list).
 Implemented React Router to handle client-side routing, enabling a multi-page feel without a full
page reload. We can navigate between the list view and the add/edit form within our React app,
which improves user experience (no need to manually find pages or use the browser’s back, it’s all a
seamless app).
 The frontend is styled sufficiently with CSS/Bootstrap, making it presentable and responsive. We
practiced using CSS classes and possibly Bootstrap components to speed up UI development,
focusing more on functionality and React concepts.
 At this stage, we have a fully functional full-stack application: a Spring Boot RESTful backend and a
ReactJS frontend, working together to provide a rich user experience for managing employee data.

Finally, we will integrate everything and discuss deployment considerations and wrap up the project in
Week 12.

Week 12: Capstone Project Integration and Deployment


Topics: Bringing it all together – we have built each piece, now ensure the entire stack (React frontend +
Spring Boot backend + MySQL database) works as a cohesive application. We will discuss
packaging/deployment options (running React build and Spring Boot together, or separately), doing a
final code review, and perhaps mention further enhancements (like Docker, CI/CD if optional).

12.1 Integration Testing the Full Stack


Now that both front and back are ready, run them concurrently:

 Spring Boot app on 8080 (verify API endpoints via Swagger or Postman).
 React dev server on 3000 (verify UI actions against real backend).
We already did that in dev mode. For production, one can build the React app:
npm run build

This outputs static files in build/ directory.

To serve those with Spring Boot, a simple way:

 Copy the build files into src/main/resources/public or static in Spring Boot project. Spring Boot will serve
static files from there. If our API also serves under same domain, we avoid CORS issues.
 Another approach: use a dedicated web server or a CDN to serve the static files and have API on
separate domain (then need CORS config). But many simpler deployments just bundle UI with
backend for simplicity.

If we copy build to static folder and rebuild Spring Boot jar, then running that jar will serve both API and
UI on port 8080. Accessing http://server:8080/ will load index.html from static resources, which then hits API
endpoints on same host.

Final demonstration scenario: user can navigate to the deployed app (maybe http://localhost:8080), see the
React UI, interact with it, and everything works (the React calls the Boot API which hits the DB).

12.2 Deploying the Application

Possible deployment strategies:

 Jar Deployment: Package Spring Boot as executable jar (with UI included as above). Then run it on
a server (Java 11 runtime or container).
 WAR Deployment: If needed (less common with Boot, but possible if deploying to a servlet
container).
 Docker: Containerize the app – e.g., a Dockerfile that uses a Java image to run the jar. Possibly
another container for MySQL. Docker Compose to link them. (This was optional in curriculum but a
nice to mention).
 Cloud: deploying to AWS EC2 or Heroku (for instance) – basically similar to jar on a VM or using
cloud platform’s support for container images.

Given optional tools included Docker, Jenkins, AWS – we mention:

 Could create a Jenkins pipeline to build the jar and run tests, then deploy to an AWS EC2 instance
or container service.
 Or use GitHub Actions for CI.

But since it's a bit beyond creating the manual, we just note these possibilities.

12.3 Summarize Achievements and Further Enhancements

At the end of 12 weeks, we built:

 A full stack employee management web application, with a ReactJS frontend and a Spring Boot +
MySQL backend.
 We applied core Java and OOP principles in the design of our classes.
 Used JDBC and later JPA/Hibernate to handle database interactions.
 Created a web UI first with JSP/Servlets, then upgraded to Spring MVC and finally to a separate
React SPA, showing evolution of web architecture.
 Learned to build and consume RESTful APIs, which is a cornerstone of modern full stack
development.
 Integrated everything with Spring Boot serving as the glue (serving both APIs and static content in
production).

Capstone Project Completed: The Employee Management System now supports:

 Listing all employees.


 Adding new employees.
 Editing existing employees.
 Deleting employees.
All through a user-friendly interface and with data persisted in a reliable database.

Possible improvements/future work:

 Add search or filter functionality (e.g., search employees by name).


 Add authentication and authorization (perhaps an admin login, using Spring Security, so only
authorized can modify data).
 Enhance the UI with more pages (maybe a page per employee detail, etc.) and styling (using more
advanced Bootstrap components or custom CSS for a polished look).
 Use Redux or Context for state management if the app grows more complex.
 Write more comprehensive tests: unit tests for service layer (using JUnit), integration tests for
repository (perhaps using an in-memory DB for testing), and end-to-end tests for the UI (using tools
like Selenium or React Testing Library + Jest for components).
 Deploy on a cloud platform (containerize the app and run on AWS, Azure, or use Heroku for
simplicity).
 Containerize MySQL and app together using Docker Compose for an easy setup of the whole stack
on any machine.

Completing this project has given hands-on experience in:

 Full Stack development covering front-end, back-end, and database.


 Using professional tools and frameworks: Eclipse/VSCode, Spring Boot, React, etc.
 Following software engineering practices like layered architecture, use of version control (Git), and
documentation of APIs.

12.4 Mini-Project Task – Week 12

Finalize the project:

 Merge the React build into the Spring Boot app (if deploying together).
 Test the packaged application on a fresh environment (does it run by simply running jar and
connecting to a MySQL instance with proper config?).
 Prepare a short presentation or demo of the project, highlighting features. In a corporate training
context, perhaps do a final demo where you run through adding/editing employees as an end user.
 Clean up code: remove any console logs, ensure all TODOs are resolved, etc.
 Write documentation (maybe a README) for how to run the app, how the architecture is, etc.

Summary – Week 12: We completed integration and delivered the final Full Stack Java Developer
Capstone Project:

 The Employee Management System is fully implemented across all layers and is working as a
cohesive unit. We demonstrated how a user can perform operations from the React UI, which
triggers API calls to the Spring Boot server, which in turn uses JPA to interact with the MySQL
database, fulfilling the request and sending results back to the UI.
 We discussed how to deploy the application in a production-like scenario. For instance, bundling
the React app with Spring Boot so that a single deployment unit can serve the frontend and
backend, or deploying them separately as needed. We also covered optional tooling like Docker for
containerization to simplify deployment and environment setup.
 This final week was about ensuring everything works together (integration testing) and that the
project is production-ready (with documentation, proper configuration management, etc.). We also
identified potential improvements and extensions, reflecting on how the project can evolve beyond
the training.
 The project showcases all the competencies targeted by the 12-week curriculum:
o OOP and Java fundamentals (seen in our entity and service designs).
o Data handling with JDBC/SQL and later JPA/Hibernate for ORM.
o Web development skills with Servlets/JSP initially and then with Spring MVC and ultimately a
modern React SPA.
o Use of Spring Framework for building scalable and maintainable applications (IoC, DI, Spring
MVC, Spring Boot auto-config).
o Building and consuming RESTful services, using JSON and HTTP effectively.
o Frontend development with React, managing state and making asynchronous calls to backend
APIs to provide a dynamic user experience.
 By completing this capstone, we have traversed through all layers of a full stack application. This
comprehensive exercise has solidified the learner’s capability to develop end-to-end applications.
The result is a professional-grade training manual and project that can be used as a reference or
even a starting point for real-world projects.

Finally, congratulations on building the Employee Management System! Through this project, you have
gained practical experience and confidence in full stack Java development, positioning you strongly for
tackling real-world software development challenges.

References (Documentation & Resources):

(Throughout the material we provided inline citations to various sources for specific concepts and code
snippets. Key references include Java and Spring official docs, GeeksforGeeks articles for OOP and Spring
explanations, W3Schools for web basics, and more. Below we list some of them for further reading.)

 GeeksforGeeks – Java OOP Concepts.


 W3Resource – Inheritance example with Employee.
 GeeksforGeeks – JDBC with MySQL tutorial.
 Spring Boot Official Documentation – layered architecture and REST guides.
 Spring Framework Docs – Spring MVC and IoC container basics.
 MDN Web Docs / W3Schools – HTML5, CSS3, JS basics and examples.
 React Official Docs – Main concepts and Hooks (reactjs.org).

(The citations in the text, like, refer to these sources for verification of facts and for deeper exploration on
those topics.)

You might also like