JAVA TRAINING SERIES
Complete Study Notes
Covers: Core Java · OOP · Collections · Exception Handling
JSP · JDBC · SQL · Spring MVC · REST API · Spring Boot
MODULE 1: Core Java & OOP Concepts
1.1 JVM, JDK, and JRE — Architecture
Java follows the Write Once, Run Anywhere (WORA) philosophy. Your source code compiles into
platform-neutral bytecode which the JVM executes on any operating system.
Component Full Form Role
JDK Java Development Kit Complete toolkit — compiler (javac), debugger, JRE.
Used by developers.
JRE Java Runtime Runtime libraries + JVM. Needed to run Java programs
Environment (no compiler).
JVM Java Virtual Machine Executes bytecode; platform-specific. Includes JIT
compiler.
Compilation & Execution Flow
SOURCE CODE (.java)
└─ javac compiler
BYTECODE (.class)
└─ JVM ClassLoader → Interpreter / JIT Compiler
MACHINE CODE (platform-specific)
JVM Internal Memory Areas
• Method Area — stores class metadata, static variables, method bytecode
• Heap — where all objects live (Garbage Collected)
• Stack — each thread gets its own stack; holds local variables and method call frames
• PC Register — tracks the current instruction being executed
• Native Method Stack — used for native (non-Java) code
📌 NOTE: JDK = JRE + Dev Tools. JRE = JVM + Libraries. JVM alone just executes bytecode.
Class Loader sequence: Bootstrap → Extension → Application.
1.2 Data Types
Java is statically typed — every variable must have a declared type at compile time. There are 8
primitive types and reference types (objects, arrays).
Type Size Default Range / Notes
byte 1 byte 0 -128 to 127
short 2 bytes 0 -32,768 to 32,767
int 4 bytes 0 -2³¹ to 2³¹-1 (~2.1 billion)
long 8 bytes 0L Use L suffix: 100L. Very large integers.
float 4 bytes 0.0f ~6-7 decimal digits of precision
double 8 bytes 0.0 ~15-16 decimal digits of precision
char 2 bytes \u0000 Unicode characters (0 to 65535)
boolean 1 bit false true or false only
Type Casting
// Widening (Implicit) — smaller to larger, no data loss:
int x = 100;
long y = x; // auto-promoted
double d = x; // auto-promoted
// Narrowing (Explicit) — larger to smaller, may lose data:
double pi = 3.14159;
int i = (int) pi; // i = 3 (decimal part truncated!)
1.3 Object-Oriented Programming — Four Pillars
Pillar Definition Mechanism
Encapsulation Bundling data and methods together; hiding private fields + public getters/setters
internal state.
Inheritance Child class acquires properties and extends keyword; IS-A relationship
behaviour of parent class.
Polymorphism Same method name behaves differently Overloading (compile-time),
based on context. Overriding (runtime)
Abstraction Hiding implementation details; exposing only abstract class / interface
essential features.
Classes and Objects
A class is a blueprint. An object is a runtime instance created with new. Object memory is allocated on
the Heap; the reference variable lives on the Stack.
class Animal {
String name; // instance field
String sound;
Animal(String name, String sound) { // constructor
[Link] = name;
[Link] = sound;
}
void speak() {
[Link](name + " says " + sound);
}
}
Animal dog = new Animal("Dog", "Woof");
[Link](); // Output: Dog says Woof
Inheritance & super Keyword
Inheritance creates an IS-A relationship. The child calls the parent constructor via super(). The
@Override annotation verifies at compile time that you are truly overriding a parent method.
class Dog extends Animal {
String breed;
Dog(String name, String breed) {
super(name, "Woof"); // MUST call parent constructor first
[Link] = breed;
}
@Override
void speak() {
[Link](name + " barks: Woof Woof!");
}
}
// Runtime Polymorphism (Dynamic Dispatch):
Animal a = new Dog("Rex", "Lab"); // upcasting
[Link](); // calls [Link]() — decided at RUNTIME
⚠ KEY RULE: Constructors are NOT inherited. Java auto-inserts super() as the first line of the
child constructor only if no explicit call exists. If the parent has no default constructor you MUST
call super(...) explicitly.
Abstract Class vs Interface
Feature Abstract Class Interface
Instantiation Cannot be instantiated Cannot be instantiated
Methods Abstract + concrete methods All abstract (Java 7); default/static
allowed (Java 8+)
Variables Any type (instance/static) public static final only (constants)
Inheritance Single (extends) Multiple (implements many interfaces)
Constructor Yes — can have constructors No constructor
Use When Partial shared implementation Full contract / multiple inheritance need
// Interface with default method (Java 8+):
interface Drawable {
void draw(); // abstract
default void display() { // concrete default
[Link]("Displaying...");
}
}
interface Colorable { void setColor(String color); }
// Implementing multiple interfaces:
class Circle implements Drawable, Colorable {
public void draw() { [Link]("Drawing circle"); }
public void setColor(String c) { /* set color */ }
}
Encapsulation — Getters & Setters
class BankAccount {
private double balance; // hidden from outside
public double getBalance() { return balance; }
public void deposit(double amount) {
if (amount > 0) balance += amount;
else throw new IllegalArgumentException("Amount must be positive");
}
public void withdraw(double amount) throws Exception {
if (amount > balance) throw new Exception("Insufficient funds");
balance -= amount;
}
}
Static & Final Keywords
• static — belongs to the class, not to any object instance; shared across all instances
• final variable — constant; value cannot change after assignment
• final method — cannot be overridden in subclasses
• final class — cannot be extended (e.g., String, Integer)
class MathHelper {
static final double PI = 3.14159; // class constant
static double areaOfCircle(double r) {
return PI * r * r; // called as [Link](5)
}
}
1.4 Practice Problems — Core Java & OOP
P1: Hello Java — print "Hello, World!" and your name [Easy]
P2: Declare all 8 primitive types, assign and print [Easy]
P3: Calculator — calculate(int a, int b, char op) for +,-,*,/,% [Easy]
P4: Print first N Fibonacci numbers (iterative + recursive) [Easy]
P5: Factorial — iterative and recursive versions [Easy]
P6: isPrime(int n), print all primes between 1–100 [Easy]
P7: Shape hierarchy — Shape > Circle, Rectangle, Triangle with area() [Medium]
P8: BankAccount with encapsulation — deposit, withdraw, getBalance [Medium]
P9: Animal > Dog, Cat, Bird — each overrides speak(); show polymorphism [Medium]
P10: Interface Drawable with draw(); implement in Circle and Square [Medium]
P11: Abstract class Vehicle with abstract fuelType(); subclasses: Car, Bike [Medium]
P12: Constructor chaining — default chains to parameterized [Easy]
P13: Static counter field — count objects created of a class [Easy]
P14: Reverse a string, check palindrome, count vowels [Easy]
P15: Matrix multiplication (3x3) [Hard]
MODULE 2: Collections Framework & Exception
Handling
2.1 Collection Hierarchy Overview
The Java Collections Framework provides a unified architecture for storing and manipulating groups of
objects. All collection classes live in the [Link] package.
[Link]
└─ [Link]
├─ List (ordered, duplicates allowed)
│ ├─ ArrayList — dynamic array; fast random access O(1)
│ ├─ LinkedList — doubly linked; fast insert/delete at ends O(1)
│ └─ Vector — synchronized ArrayList (legacy)
├─ Set (no duplicates)
│ ├─ HashSet — unordered; O(1) add/remove/contains
│ ├─ LinkedHashSet — insertion order maintained
│ └─ TreeSet — sorted natural/custom order; O(log n)
└─ Queue (FIFO)
├─ LinkedList — also implements Queue
├─ PriorityQueue — heap-based; smallest element first
└─ ArrayDeque — double-ended queue (Deque)
[Link] (key-value pairs — does NOT extend Collection)
├─ HashMap — unordered; O(1) avg; allows one null key
├─ LinkedHashMap — insertion/access order maintained
├─ TreeMap — sorted by key; O(log n)
└─ Hashtable — synchronized (legacy)
2.2 ArrayList — Deep Dive
Backed by a dynamic array. Default capacity = 10; grows by 50% when full. Provides fast random
access O(1) but slow insert/delete at middle O(n) due to element shifting.
Operation Time Complexity Why
get(index) O(1) Direct array index access
add(element) O(1) amortized Appends at end; occasional resize
add(index, elem) O(n) Must shift all elements after index
remove(index) O(n) Must shift elements left
contains(elem) O(n) Linear scan through array
[Link]() O(n log n) TimSort algorithm
List<String> list = new ArrayList<>();
[Link]("Alice"); // O(1)
[Link](0, "Zara"); // O(n) — shifts elements right
[Link](1); // O(1)
[Link]("Alice"); // O(n) — finds then shifts
// Safe removal during iteration — use Iterator:
Iterator<String> it = [Link]();
while ([Link]()) {
if ([Link]().equals("Zara")) [Link](); // safe!
}
2.3 LinkedList — Deep Dive
A doubly linked list where each node stores data plus references to the previous and next node. No
contiguous memory required. Fast at head/tail operations but slow random access.
Operation ArrayList LinkedList
Random Access get(i) O(1) O(n) — traversal needed
Add at End O(1) amortized O(1)
Add at Middle O(n) O(n) find + O(1) insert
Remove from Middle O(n) O(n) find + O(1) remove
Memory Usage Less (array) More (prev + next pointers per
node)
Best Use Case Read-heavy, random access Insert/delete heavy at head/tail
LinkedList<Integer> ll = new LinkedList<>();
[Link](10); // O(1)
[Link](20); // O(1)
[Link](1); // O(n) — traversal
// Use as Stack (LIFO):
[Link](5); [Link]();
// Use as Queue (FIFO):
[Link](5); [Link]();
2.4 HashMap — Internal Working
HashMap uses a hash table backed by an array of buckets. Each bucket is a linked list (or a red-black
tree after 8 entries). Default initial capacity = 16; default load factor = 0.75.
put(key, value) — Step by Step
• Step 1: Compute hash = [Link]()
• Step 2: Determine bucket index = hash & (capacity - 1)
• Step 3: If bucket is empty → insert new Node
• Step 4: If key already exists (via equals()) → UPDATE value
• Step 5: Else → add to chain at that bucket (collision handled by chaining)
• Step 6: If size > capacity × loadFactor → RESIZE (double capacity + rehash)
Map<String, Integer> marks = new HashMap<>();
[Link]("Alice", 95);
[Link]("Bob", 88);
[Link]("Charlie", 0); // safe get (returns 0 if missing)
[Link]("Alice", 70); // won't overwrite existing key
// Iterate entries:
for ([Link]<String, Integer> e : [Link]()) {
[Link]([Link]() + " -> " + [Link]());
}
// Sort by value (Java 8 streams):
[Link]().stream()
.sorted([Link]([Link]()))
.forEach(e -> [Link]([Link]() + ": " + [Link]()));
2.5 TreeMap & HashSet
TreeMap stores keys in a Red-Black Tree (always sorted). All operations are O(log n). HashSet is
backed by a HashMap where the element is the key and a dummy Object is the value — so all Set
semantics are preserved.
// TreeMap — sorted by key:
TreeMap<String, Integer> tm = new TreeMap<>();
[Link]("Banana", 2); [Link]("Apple", 5); [Link]("Cherry", 1);
// Iterates in alphabetical order: Apple, Banana, Cherry
[Link](); // "Apple"
[Link](); // "Cherry"
[Link]("Cherry"); // all keys strictly before "Cherry"
// HashSet — no duplicates:
Set<String> hs = new HashSet<>();
[Link]("Java"); [Link]("Java"); // second add ignored
[Link]("Java"); // O(1)
2.6 Generics
Generics enable type-safe, reusable code. The type parameter is erased at runtime (type erasure), so
generics only exist at compile time for safety checking.
// Generic class:
class Box<T> {
private T value;
Box(T v) { [Link] = v; }
T get() { return value; }
}
Box<Integer> intBox = new Box<>(42);
Box<String> strBox = new Box<>("Hello");
// Generic method:
public static <T extends Comparable<T>> T max(T a, T b) {
return [Link](b) >= 0 ? a : b;
}
// Wildcard — accept any type:
void printList(List<?> list) { [Link]([Link]::println); }
// Upper bounded wildcard:
void addNumbers(List<? extends Number> list) { /* read only */ }
2.7 Comparable vs Comparator
Aspect Comparable Comparator
Package [Link] [Link]
Method compareTo(T other) compare(T o1, T o2)
Location Inside the class External (separate class or lambda)
Purpose Natural/default ordering Custom/multiple orderings
[Link]() Works directly Pass as second argument
// Comparable — natural order by name:
class Student implements Comparable<Student> {
String name; int marks;
public int compareTo(Student o) {
return [Link]([Link]);
}
}
[Link](students); // uses compareTo()
// Comparator — external, flexible, multiple orderings:
Comparator<Student> byMarks = (a, b) -> [Link] - [Link]; // desc
[Link](byMarks);
// Multi-field comparator (Java 8):
[Link]([Link](Student::getMarks)
.reversed()
.thenComparing(Student::getName));
2.8 Exception Handling
Exception Hierarchy
[Link]
├─ Error (JVM-level — do NOT catch normally)
│ ├─ OutOfMemoryError
│ └─ StackOverflowError
└─ Exception
├─ CHECKED (compiler forces you to handle)
│ ├─ IOException
│ ├─ SQLException
│ └─ FileNotFoundException
└─ UNCHECKED — RuntimeException (optional to handle)
├─ NullPointerException
├─ ArrayIndexOutOfBoundsException
├─ ClassCastException
├─ ArithmeticException
└─ NumberFormatException
try-catch-finally
The finally block ALWAYS executes — even if there is a return statement in try or catch. Used for
resource cleanup (closing files, DB connections).
try {
// risky code
} catch (FileNotFoundException e) { // specific first!
[Link]("File missing: " + [Link]());
} catch (IOException | SQLException e) { // multi-catch (Java 7)
[Link]();
} finally {
// ALWAYS runs — cleanup here
}
// try-with-resources (Java 7+) — auto-closes:
try (BufferedReader br = new BufferedReader(new FileReader("[Link]"))) {
String line;
while ((line = [Link]()) != null) [Link](line);
} catch (IOException e) { [Link](); }
// [Link]() called automatically
throws vs throw
Keyword Used On Purpose Example
throw Statement Throw an exception object right throw new IOException("File
now missing")
throws Method signature Declare that method may throw void read() throws IOException
a checked exception {}
Custom Exception Classes
// Checked custom exception:
class InsufficientFundsException extends Exception {
double shortfall;
InsufficientFundsException(double shortfall) {
super("Insufficient funds. Short by: " + shortfall);
[Link] = shortfall;
}
}
// Unchecked custom exception:
class InvalidAgeException extends RuntimeException {
InvalidAgeException(String msg) { super(msg); }
}
// Usage:
void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance)
throw new InsufficientFundsException(amount - balance);
balance -= amount;
}
Exception Best Practices
• Never catch Exception or Throwable unless re-throwing or top-level logging
• Always log: [Link]() + [Link]()
• Most specific exception type first in catch blocks
• Use finally or try-with-resources to release resources
• Do NOT use exceptions for flow control — they are expensive
• Use Checked exceptions for recoverable conditions; Unchecked for programming errors
2.9 Practice Problems — Collections & Exception Handling
P1: ArrayList Basics — add 10 names, sort, search, remove duplicates [Easy]
P2: LinkedList as Stack — push, pop, peek, isEmpty [Easy]
P3: LinkedList as Queue — enqueue, dequeue, peek [Easy]
P4: HashSet — store words from a sentence; find unique words and count [Easy]
P5: TreeSet — store 10 integers; print ascending and descending [Easy]
P6: HashMap — word frequency counter for a sentence [Medium]
P7: LinkedHashMap LRU Cache — fixed-size cache with access order [Hard]
P8: TreeMap Range — print students with marks between 60–80 [Medium]
P9: Comparator Sort — Employee list by salary desc, then name asc [Medium]
P10: Comparable — Student sorted by rollNumber; sort a list [Easy]
P11: Generic Stack class — push, pop, peek, isEmpty [Medium]
P12: Try-Catch-Finally — file reading with proper IOException handling [Medium]
P13: Multi-Catch — handle ArithmeticException + NumberFormatException [Easy]
P14: Custom AgeValidationException — throw if age < 0 or > 150 [Medium]
P15: BankAccount with InsufficientFundsException + NegativeAmountException [Hard]
MODULE 3: JSP · JDBC · SQL
3.1 SQL Command Categories
Categor Full Form Commands Purpose
y
DDL Data Definition Language CREATE, ALTER, DROP, Define and modify schema
TRUNCATE structure
DML Data Manipulation INSERT, UPDATE, DELETE Modify data within tables
Language
DQL Data Query Language SELECT Retrieve data from tables
DCL Data Control Language GRANT, REVOKE Manage user permissions
TCL Transaction Control COMMIT, ROLLBACK, Control transaction boundaries
Language SAVEPOINT
3.2 DDL — CREATE TABLE & Constraints
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) UNIQUE,
age INT CHECK (age >= 18),
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES department(id)
);
3.3 DQL — SELECT with Clauses
-- Basic SELECT with filter and sort:
SELECT name, age FROM students WHERE age > 20 ORDER BY name ASC;
-- GROUP BY with HAVING:
SELECT dept_id, COUNT(*) AS total, AVG(marks) AS avg_marks
FROM students
GROUP BY dept_id
HAVING COUNT(*) > 5
ORDER BY avg_marks DESC;
3.4 SQL JOINS
JOIN Type Returns Use Case
INNER JOIN Only rows with matching values in BOTH Students with departments assigned
tables
LEFT JOIN All left rows + matching right rows (NULL if All students, even those without a dept
no match)
RIGHT JOIN All right rows + matching left rows (NULL if All departments even with no students
no match)
SELF JOIN Table joined with itself Employee-Manager hierarchy
CROSS JOIN Cartesian product of both tables All combinations (rare)
-- INNER JOIN:
SELECT [Link], d.dept_name
FROM students s INNER JOIN department d ON s.dept_id = [Link];
-- LEFT JOIN:
SELECT [Link], d.dept_name
FROM students s LEFT JOIN department d ON s.dept_id = [Link];
-- SELF JOIN (Employee-Manager):
SELECT [Link] AS employee, [Link] AS manager
FROM employee e JOIN employee m ON e.mgr_id = [Link];
3.5 Subqueries
-- WHERE subquery:
SELECT name FROM students
WHERE marks > (SELECT AVG(marks) FROM students);
-- FROM subquery (inline view):
SELECT dept_id, avg_m FROM
(SELECT dept_id, AVG(marks) AS avg_m FROM students GROUP BY dept_id) sub
WHERE avg_m > 75;
-- EXISTS:
SELECT name FROM students s
WHERE EXISTS (SELECT 1 FROM results r WHERE r.student_id = [Link] AND [Link] = 'A');
3.6 JDBC — 7-Step Process
JDBC (Java Database Connectivity) provides a standard API for connecting Java applications to
relational databases. It acts as a bridge between Java code and the database driver.
Step 1: Load Driver
[Link]("[Link]");
Step 2: Get Connection
Connection con = [Link](
"jdbc:mysql://localhost:3306/mydb", "root", "password");
Step 3: Create Statement
PreparedStatement ps = [Link](
"SELECT * FROM students WHERE dept_id = ?");
Step 4: Set Parameters & Execute
[Link](1, deptId);
ResultSet rs = [Link]();
Step 5: Process ResultSet
while ([Link]()) {
[Link]([Link]("name") + " " + [Link]("age"));
}
Step 6: Close Resources (in finally or try-with-resources)
[Link](); [Link](); [Link]();
Step 7: Handle Exceptions — wrap in try-catch-finally
PreparedStatement — SQL Injection Prevention
Always use PreparedStatement for any query that includes user input. Parameters are sent separately
from the SQL text, making SQL injection impossible.
// SAFE — PreparedStatement:
String sql = "INSERT INTO students(name, age) VALUES (?, ?)";
PreparedStatement ps = [Link](sql);
[Link](1, studentName); // 1-indexed
[Link](2, studentAge);
int rows = [Link](); // returns rows affected
// UNSAFE — Statement (vulnerable to SQL injection!):
// Statement st = [Link]();
// [Link]("SELECT * FROM users WHERE name='" + input + "'");
Transaction Management
try {
[Link](false); // start transaction
[Link](); // debit from A
[Link](); // credit to B
[Link](); // both succeed
} catch (SQLException e) {
[Link](); // undo everything
} finally {
[Link](true);
}
3.7 JSP — JavaServer Pages
JSP Lifecycle
• Step 1 — Translation: .jsp → .java (Servlet class generated by the container)
• Step 2 — Compilation: .java → .class (compiled by javac)
• Step 3 — Loading: .class loaded into the JVM
• Step 4 — Instantiation: Servlet object created
• Step 5 — Init: jspInit() called once
• Step 6 — Request: _jspService() called for each HTTP request; generates HTML
• Step 7 — Destroy: jspDestroy() called on shutdown
JSP Elements Reference
Element Syntax Purpose / Example
Directive <%@ %> <%@ page language="java" contentType="text/html" %>
Scriptlet <% %> Java code block: <% int x = 10; [Link](x); %>
Expression <%= %> Outputs value: <%= new [Link]() %>
Declaration <%! %> Declare methods/vars: <%! int count = 0; %>
Comment <%-- --%> JSP comment (not sent to client)
EL ${ } Expression Language: ${[Link]}, ${[Link]}
JSTL forEach <c:forEach> <c:forEach items="${list}" var="item">${item}</c:forEach>
MVC Pattern — Servlet + JSP
The MVC pattern separates concerns: the Model holds data, the View presents it, and the Controller
handles requests and wires the two together.
MODEL: [Link] (POJO/Bean) — holds data
VIEW: [Link] — displays data using EL: ${students}
CONTROLLER: [Link] — processes request
FLOW:
Browser → HTTP Request → StudentServlet (Controller)
↓
StudentDAO (Model) → fetches from DB
↓
[Link]("students", list)
↓
[Link]("[Link]")
↓
JSP renders HTML using ${students} → Browser
3.8 Practice Problems — SQL, JDBC & JSP
P1: Schema Design — Library system: books, members, borrow_records [Medium]
P2: CRUD Operations — INSERT, UPDATE, DELETE, SELECT for Student table [Easy]
P3: Aggregate Queries — total students per dept; dept with highest avg marks [Medium]
P4: Join Mastery — students with dept name via INNER, LEFT, RIGHT JOIN [Medium]
P5: Subquery — students above average; top 3 scorers per dept [Hard]
P6: Bank Transfer Transaction — COMMIT / ROLLBACK [Medium]
P7: JDBC CRUD — add, update, delete, list all students [Medium]
P8: PreparedStatement — safely search students by name (user input) [Easy]
P9: Batch Processing — insert 100 students using JDBC batch [Medium]
P10: Login App — JSP form → Servlet validates against DB → redirect [Hard]
P11: Session — store username after login; display on every page; logout clears it [Medium]
P12: Student CRUD App — Full MVC: Servlet + JSP + JDBC [Hard]
P13: Pagination — 10 records per page using SQL LIMIT/OFFSET [Hard]
MODULE 4: Spring MVC · Spring Boot · REST API
4.1 Spring Core — IoC & Dependency Injection
Concept Definition
IoC (Inversion of Control) The Spring container manages object creation and lifecycle. You never use
new; Spring creates and injects them.
DI (Dependency Injection) Spring injects dependencies into a class via Constructor, Setter, or Field
injection.
ApplicationContext The IoC container. Reads bean configuration (annotations or XML) and
manages the full lifecycle.
Bean Any object managed by the Spring container. Defined with @Component,
@Service, @Repository, @Controller, or XML.
Dependency Injection Types
// 1. Constructor Injection (RECOMMENDED — immutable, testable):
@Service
public class OrderService {
private final PaymentService paymentService;
@Autowired // optional in Spring 4.3+ for single constructor
public OrderService(PaymentService paymentService) {
[Link] = paymentService;
}
}
// 2. Field Injection (convenient but harder to unit test):
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
// 3. Setter Injection (optional dependencies):
@Service
public class ReportService {
private NotificationService ns;
@Autowired
public void setNotificationService(NotificationService ns) {
[Link] = ns;
}
}
Bean Lifecycle
• 1. Instantiation — Spring creates bean instance (constructor called)
• 2. Populate — Dependencies injected (@Autowired, @Value)
• 3. BeanNameAware / BeanFactoryAware — optional callbacks called
• 4. @PostConstruct — custom init logic runs
• 5. Bean READY — available for use in the application
• 6. @PreDestroy — cleanup method called on container shutdown
• 7. Destruction — bean removed from container
Bean Scopes
Scope Description
singleton Default. ONE instance per Spring container. Shared everywhere.
prototype NEW instance every time bean is requested.
request New instance per HTTP request (Web apps only).
session New instance per HTTP session (Web apps only).
application One instance per ServletContext.
4.2 Spring MVC — Request-Response Flow
Spring MVC uses a Front Controller pattern. The DispatcherServlet is the single entry point for all HTTP
requests.
1. Browser sends HTTP Request to the web server
2. DispatcherServlet (Front Controller) intercepts it
3. HandlerMapping finds the matching @Controller method
4. Controller processes request → calls Service → calls Repository
5. Controller returns ModelAndView (model data + view name)
6. ViewResolver maps view name → JSP / Thymeleaf file
7. View renders HTML using model data
8. HTTP Response sent back to Browser
Spring MVC Annotations
Annotation Purpose
@Controller Marks class as web controller; methods return view names
@RequestMapping Maps URL pattern to method/class; supports method, path, params
@GetMapping Shorthand for @RequestMapping(method = GET)
@PostMapping Shorthand for @RequestMapping(method = POST)
@RequestParam Binds query param: ?name=Alice → @RequestParam String name
@PathVariable Binds URI segment: /user/{id} → @PathVariable Long id
@ModelAttribute Binds HTML form data to a Java object automatically
@ResponseBody Write return value directly to HTTP response body (not a view)
@RequestBody Deserialize JSON request body into a Java object
@ResponseStatus Set HTTP response status code on a method
Controller Example
@Controller
@RequestMapping("/students")
public class StudentController {
@Autowired private StudentService service;
@GetMapping("/list")
public String listAll(Model model) {
[Link]("students", [Link]());
return "student-list"; // → /WEB-INF/views/[Link]
}
@PostMapping("/add")
public String addStudent(@ModelAttribute Student s, RedirectAttributes ra) {
[Link](s);
[Link]("msg", "Saved!");
return "redirect:/students/list";
}
@GetMapping("/{id}")
public String getById(@PathVariable Long id, Model model) {
[Link]("student", [Link](id));
return "student-detail";
}
}
4.3 Spring Boot
Spring Boot eliminates boilerplate Spring configuration. It auto-configures beans based on classpath
dependencies and provides an embedded server so no external Tomcat installation is needed.
• @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
• Starter POMs: spring-boot-starter-web, spring-boot-starter-data-jpa, spring-boot-starter-security
• Embedded Server: Tomcat / Jetty / Undertow — no external setup needed
• [Link]: centralized configuration (DB, port, logging, JPA)
• Actuator: /actuator/health, /actuator/metrics, /actuator/info
Project Structure
src/main/java/com/example/
[Link] → main class with @SpringBootApplication
controller/
[Link] → @RestController or @Controller
service/
[Link] → @Service — business logic
repository/
[Link] → extends JpaRepository
model/
[Link] → @Entity — JPA entity
exception/
[Link]
src/main/resources/
[Link] → DB config, server port, etc.
[Link] → Maven dependencies
[Link]
[Link]=8080
[Link]=jdbc:mysql://localhost:3306/mydb
[Link]=root
[Link]=secret
[Link]-auto=update
[Link]-sql=true
[Link].format_sql=true
[Link]=INFO
4.4 REST API Design Principles
REST (Representational State Transfer) is an architectural style for building web services. Everything is
a resource identified by a URI, and standard HTTP methods express what operation to perform.
• Stateless — each request contains all info needed; server stores no client state
• Client-Server — UI and backend are separated; communicate via HTTP only
• Uniform Interface — resources identified by URI; standard HTTP verbs for operations
• Resource-Based — model your API as nouns: /students, /orders, /products
HTTP Methods & Status Codes
Method CRUD URI Example Success Code Description
GET Read GET /students 200 OK Retrieve all resources
GET Read GET /students/5 200 OK Retrieve resource by ID
POST Create POST /students 201 Created Create a new resource
PUT Update PUT /students/5 200 OK Full replacement update
PATCH Update PATCH /students/5 200 OK Partial update
DELETE Delete DELETE /students/5 204 No Content Delete a resource
Full REST CRUD Controller
@RestController
@RequestMapping("/api/students")
public class StudentRestController {
@Autowired private StudentService service;
@GetMapping
public ResponseEntity<List<Student>> getAll() {
return [Link]([Link]());
}
@GetMapping("/{id}")
public ResponseEntity<Student> getById(@PathVariable Long id) {
return [Link](id)
.map(ResponseEntity::ok)
.orElseThrow(() -> new ResourceNotFoundException("Student", id));
}
@PostMapping
public ResponseEntity<Student> create(@Valid @RequestBody Student s) {
Student saved = [Link](s);
URI loc = [Link]("/api/students/" + [Link]());
return [Link](loc).body(saved);
}
@PutMapping("/{id}")
public ResponseEntity<Student> update(@PathVariable Long id, @RequestBody Student
s) {
[Link](id);
return [Link]([Link](s));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
[Link](id);
return [Link]().build();
}
}
Global Exception Handling (@ControllerAdvice)
@RestControllerAdvice provides a centralized location to handle exceptions thrown by any
@RestController. This keeps controller code clean.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
ErrorResponse err = new ErrorResponse(404, [Link](),
[Link]());
return [Link](HttpStatus.NOT_FOUND).body(err);
}
@ExceptionHandler([Link])
public ResponseEntity<Map<String, String>> handleValidation(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
[Link]().getFieldErrors()
.forEach(e -> [Link]([Link](), [Link]()));
return [Link]().body(errors);
}
@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse> handleGeneric(Exception ex) {
ErrorResponse err = new ErrorResponse(500, "Internal error",
[Link]());
return [Link]().body(err);
}
}
4.5 Spring Data JPA
Spring Data JPA eliminates boilerplate DAO code. Extend JpaRepository to get save, findById, findAll,
delete, count, and more for free. Spring generates the SQL at runtime.
// JPA Entity:
@Entity
@Table(name = "students")
public class Student {
@Id @GeneratedValue(strategy = [Link])
private Long id;
@Column(nullable = false)
private String name;
private int age;
@ManyToOne
@JoinColumn(name = "dept_id")
private Department department;
}
// Repository — zero implementation needed:
public interface StudentRepository extends JpaRepository<Student, Long> {
List<Student> findByName(String name);
List<Student> findByAgeGreaterThan(int age);
List<Student> findByDepartment_Name(String deptName);
// JPQL:
@Query("SELECT s FROM Student s WHERE [Link] BETWEEN :min AND :max")
List<Student> findByAgeRange(@Param("min") int min, @Param("max") int max);
// Pagination:
Page<Student> findAll(Pageable pageable);
}
Layered Architecture — Request Flow
POST /api/students { name:"Alice", age:21 }
↓
@RestController (StudentRestController)
— validates @Valid @RequestBody
— calls [Link](student)
↓
@Service (StudentService)
— business logic (check duplicates, set defaults)
— calls [Link](student)
↓
@Repository (StudentRepository extends JpaRepository)
— Hibernate generates: INSERT INTO students VALUES (...)
↓
DATABASE (MySQL)
— stores record, returns generated ID
↑
Response: 201 Created { id:1, name:"Alice", age:21 }
4.6 Practice Problems — Spring MVC, Boot & REST
P1: Hello Spring Boot — GET /hello returns "Hello, World!" [Easy]
P2: IoC Demo — inject EmailService into UserService via constructor [Easy]
P3: Bean Scopes — demonstrate singleton is shared, prototype is not [Easy]
P4: MVC Form — Spring MVC form to add a Student; list page [Medium]
P5: Validation — @NotNull, @Size, @Email on Student; show error messages [Medium]
P6: REST GET — GET /api/products returns list of products as JSON [Easy]
P7: REST CRUD — Full CRUD for Employee with proper HTTP status codes [Hard]
P8: Path Variables — GET /api/students/{id} or 404 if not found [Easy]
P9: Request Params — GET /api/students?dept=CSE&minAge=20 [Medium]
P10: Spring Data JPA — Student entity + JpaRepository CRUD [Medium]
P11: Custom Query — findByDepartmentAndAgeGreaterThan + @Query JPQL [Medium]
P12: Pagination — GET /api/students?page=0&size=10&sort=name,asc [Hard]
P13: Global Exception Handler — 404 for not found, 500 for generic [Medium]
P14: One-to-Many — Department has many Students; GET /api/departments/{id}/students
[Hard]
P15: AOP Logging — @Around to log execution time of all service methods [Hard]
P16: Full App — Student Management REST API: Spring Boot + JPA + MySQL, full CRUD,
pagination, global error handling [Hard]
End of Java Training Notes