1. What is Spring Boot?

Spring Boot is a framework built on top of the Spring Framework that makes it extremely easy to build Java web applications and REST APIs. It follows the principle of "Convention over Configuration" — it auto-configures almost everything so you can focus on writing business logic instead of XML configuration files.

Spring Framework vs Spring Boot

FeatureSpring FrameworkSpring Boot
ConfigurationManual XML + Java configAuto-configured
ServerNeed external TomcatEmbedded Tomcat (built-in)
Setup timeHours of configMinutes with Spring Initializr
DependenciesManually add each JARStarter packs (one dependency = everything)
XML filesRequired (web.xml, beans.xml)No XML needed
Learning curveSteepBeginner-friendly
Convention over Configuration
Spring Boot makes smart default choices for you. You don't configure a database connection pool, a web server, or component scanning — Spring Boot does it automatically. You only override when you need something different.

Spring Initializr

Go to start.spring.io to generate a Spring Boot project. Select your dependencies (Spring Web, Spring Data JPA, MySQL Driver, etc.), click Generate, and you get a ready-to-run project ZIP.

Key Features of Spring Boot

Exam Tip
If the question asks "What makes Spring Boot different from Spring?" — the answer is auto-configuration, embedded server, and starter dependencies. These three are the most tested points.

2. Project Structure

A standard Spring Boot project looks like this:

my-project/
├── src/
│   ├── main/
│   │   ├── java/                    // All your Java code goes here
│   │   │   └── com/example/demo/
│   │   │       ├── DemoApplication.java      // Main class (entry point)
│   │   │       ├── controller/               // REST controllers
│   │   │       ├── service/                  // Business logic
│   │   │       ├── repository/               // Database access
│   │   │       └── model/                    // Entity classes
│   │   └── resources/
│   │       ├── application.properties        // Configuration file
│   │       ├── static/                       // CSS, JS, images
│   │       └── templates/                    // HTML templates (Thymeleaf)
│   └── test/                                 // Test files
└── pom.xml                                   // Maven dependencies

pom.xml — Maven Dependencies

The pom.xml file lists all libraries your project needs. Spring Boot uses "starter" dependencies — one starter pulls in multiple related JARs.

<!-- Key dependencies in pom.xml -->
<dependencies>

    <!-- Spring Web — for building REST APIs -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Data JPA — for database operations -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- MySQL Driver — connects Java to MySQL -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
    </dependency>

</dependencies>
Key starter dependencies to remember
  • spring-boot-starter-web — REST APIs, embedded Tomcat
  • spring-boot-starter-data-jpa — JPA + Hibernate for database
  • spring-boot-starter-test — testing support

The Main Class — Entry Point

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication   // This ONE annotation does 3 things (see below)
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);  // Starts the app
    }
}
Exam Tip
@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan. This is asked very frequently. Know what each sub-annotation does.

3. Key Annotations

Annotations are the backbone of Spring Boot. Instead of XML config, you put @ annotations on classes and methods to tell Spring what to do. This is the most important section for exams.

Complete Annotation Reference Table

AnnotationWhere UsedWhat It Does
@SpringBootApplicationMain classCombines @Configuration + @EnableAutoConfiguration + @ComponentScan. Entry point.
@RestControllerClassMakes the class a REST API controller. Every method returns data (JSON), not a view.
@ControllerClassMakes the class a web controller. Methods return view names (HTML pages).
@RequestMapping("/path")Class or MethodMaps a URL path to a class or method. Base path for all endpoints in the class.
@GetMapping("/path")MethodHandles HTTP GET requests (read/fetch data).
@PostMapping("/path")MethodHandles HTTP POST requests (create new data).
@PutMapping("/path")MethodHandles HTTP PUT requests (update existing data).
@DeleteMapping("/path")MethodHandles HTTP DELETE requests (remove data).
@PathVariableMethod paramExtracts value from URL path. /emp/{id} → id = 5
@RequestParamMethod paramExtracts query parameter. /emp?name=John → name = "John"
@RequestBodyMethod paramConverts incoming JSON body to a Java object automatically.
@AutowiredField or ConstructorInjects a dependency automatically (Dependency Injection).
@ServiceClassMarks class as a service layer component (business logic).
@RepositoryClassMarks class as a data access layer component (database operations).
@ComponentClassGeneric Spring-managed bean. @Service and @Repository are specialized versions.
@EntityClassMaps this Java class to a database table (JPA).
@Table(name="tbl")ClassSpecifies the exact database table name for the entity.
@IdFieldMarks a field as the primary key of the table.
@GeneratedValueFieldAuto-generates the primary key value (auto-increment).
@Column(name="col")FieldMaps a field to a specific column name in the table.

@RestController vs @Controller

@RestController    // Returns DATA (JSON) — used for REST APIs
public class ApiController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello World";   // Returns this string as response body
    }
}

@Controller        // Returns VIEW NAME (HTML page) — used for web pages
public class WebController {
    @GetMapping("/home")
    public String home() {
        return "index";         // Looks for index.html template
    }
}
Key Difference
@RestController = @Controller + @ResponseBody. The @ResponseBody part tells Spring to write the return value directly into the HTTP response body (as JSON or text) instead of looking for an HTML template.

@PathVariable vs @RequestParam vs @RequestBody

// @PathVariable — value is PART of the URL path
// URL: GET /employees/5
@GetMapping("/employees/{id}")
public Employee getById(@PathVariable Long id) {  // id = 5
    return service.findById(id);
}

// @RequestParam — value comes AFTER ? in URL
// URL: GET /employees?department=IT
@GetMapping("/employees")
public List<Employee> getByDept(@RequestParam String department) {  // department = "IT"
    return service.findByDept(department);
}

// @RequestBody — value comes from JSON body of the request
// POST /employees with body: {"name":"John","department":"IT"}
@PostMapping("/employees")
public Employee create(@RequestBody Employee emp) {  // JSON → Java object
    return service.save(emp);
}
Exam Tip
@PathVariable = value in URL path (/emp/5). @RequestParam = value after ? (/emp?id=5). @RequestBody = JSON data in request body. They ask "which annotation to use when..." — know the difference.

4. REST Controller — Building APIs

A REST controller handles HTTP requests and returns data (usually JSON). Each method maps to an HTTP method (GET, POST, PUT, DELETE).

Simple GET Endpoint

@RestController                           // This class handles REST API requests
@RequestMapping("/api")                   // Base URL: all endpoints start with /api
public class HelloController {

    @GetMapping("/hello")                  // Handles GET /api/hello
    public String sayHello() {
        return "Hello from Spring Boot!";  // Response sent as plain text
    }
}

GET with Path Variable

@GetMapping("/employees/{id}")              // {id} is a placeholder in URL
public Employee getEmployee(@PathVariable Long id) {
    return service.getEmployeeById(id);    // Fetch employee by ID
}
// URL: GET /api/employees/5 → id = 5

POST — Create New Resource

@PostMapping("/employees")                 // Handles POST /api/employees
public Employee createEmployee(@RequestBody Employee emp) {
    // @RequestBody converts JSON from request body → Employee object
    return service.saveEmployee(emp);      // Save and return the new employee
}
// Send JSON: {"name": "John", "department": "IT", "salary": 50000}

PUT — Update Existing Resource

@PutMapping("/employees/{id}")              // Handles PUT /api/employees/5
public Employee updateEmployee(@PathVariable Long id,
                               @RequestBody Employee emp) {
    emp.setId(id);                         // Set the ID from URL path
    return service.saveEmployee(emp);      // save() updates if ID exists
}

DELETE — Remove Resource

@DeleteMapping("/employees/{id}")           // Handles DELETE /api/employees/5
public String deleteEmployee(@PathVariable Long id) {
    service.deleteEmployee(id);              // Delete employee with this ID
    return "Employee deleted successfully";
}
HTTP Method → Annotation Mapping
HTTP MethodAnnotationPurposeExample URL
GET@GetMappingRead / FetchGET /api/employees
POST@PostMappingCreatePOST /api/employees
PUT@PutMappingUpdatePUT /api/employees/5
DELETE@DeleteMappingDeleteDELETE /api/employees/5

5. Layered Architecture

Spring Boot follows a layered architecture pattern. Each layer has a specific responsibility and talks only to the layer directly below it.

  Client (Browser / Postman)
        ↓ HTTP Request
  ┌─────────────────────┐
  │    Controller        │  ← Handles HTTP requests, calls Service
  │   (@RestController)  │
  └─────────┬───────────┘
            ↓
  ┌─────────────────────┐
  │     Service          │  ← Business logic, validation, rules
  │    (@Service)        │
  └─────────┬───────────┘
            ↓
  ┌─────────────────────┐
  │    Repository       │  ← Database queries (CRUD operations)
  │   (@Repository)      │
  └─────────┬───────────┘
            ↓
  ┌─────────────────────┐
  │    Database         │  ← MySQL, PostgreSQL, H2, etc.
  └─────────────────────┘

Why Layers?

Each Layer's Responsibility

LayerAnnotationResponsibility
Controller@RestControllerReceive HTTP requests, validate input, call service, return response
Service@ServiceBusiness logic, calculations, validation rules, orchestration
Repository@RepositoryDatabase operations — save, find, update, delete
Model/Entity@EntityRepresents a database table as a Java class
Exam Tip
If they ask "Which layer contains business logic?" — answer is Service layer. Controller NEVER contains business logic. Repository NEVER contains business logic. They each have one job.

6. JPA and Hibernate (ORM)

What is ORM?

ORM = Object-Relational Mapping. It maps Java objects to database tables automatically. Instead of writing SQL queries, you work with Java objects and JPA/Hibernate translates them to SQL behind the scenes.

Java ConceptDatabase Concept
ClassTable
ObjectRow
Field/VariableColumn

Entity Class Example

An entity class is a regular Java class with JPA annotations that maps to a database table.

import jakarta.persistence.*;  // JPA annotations

@Entity                        // Tells JPA: this class = a database table
@Table(name = "employees")     // Table name in database (optional if class name = table name)
public class Employee {

    @Id                        // This field is the PRIMARY KEY
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // Auto-increment
    private Long id;

    @Column(name = "emp_name")  // Maps to column "emp_name" in table
    private String name;

    private String department;   // No @Column? Column name = field name "department"

    private double salary;

    // Default constructor (REQUIRED by JPA)
    public Employee() {}

    // Parameterized constructor
    public Employee(String name, String department, double salary) {
        this.name = name;
        this.department = department;
        this.salary = salary;
    }

    // Getters and Setters (required for JPA and JSON conversion)
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getDepartment() { return department; }
    public void setDepartment(String dept) { this.department = dept; }
    public double getSalary() { return salary; }
    public void setSalary(double salary) { this.salary = salary; }
}
Common Mistake
JPA entities MUST have a default (no-arg) constructor. If you only define a parameterized constructor, JPA will throw an error. Always include public Employee() {}.

JpaRepository — Built-in Database Methods

By extending JpaRepository, you get a full set of database operations for FREE. No SQL needed.

import org.springframework.data.jpa.repository.JpaRepository;

// JpaRepository<EntityClass, PrimaryKeyType>
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    // That's it! You get all CRUD methods automatically:
    // findAll()       → SELECT * FROM employees
    // findById(id)    → SELECT * FROM employees WHERE id = ?
    // save(entity)    → INSERT or UPDATE
    // deleteById(id)  → DELETE FROM employees WHERE id = ?
    // count()         → SELECT COUNT(*) FROM employees
    // existsById(id)  → checks if row exists
}

Built-in JpaRepository Methods

MethodSQL EquivalentReturns
findAll()SELECT * FROM tableList<Entity>
findById(id)SELECT * WHERE id = ?Optional<Entity>
save(entity)INSERT or UPDATESaved Entity
deleteById(id)DELETE WHERE id = ?void
count()SELECT COUNT(*)long
existsById(id)SELECT EXISTS(...)boolean

Custom Queries with @Query

public interface EmployeeRepository extends JpaRepository<Employee, Long> {

    // Custom query method — Spring generates SQL from method name!
    List<Employee> findByDepartment(String department);
    // → SELECT * FROM employees WHERE department = ?

    List<Employee> findByNameContaining(String keyword);
    // → SELECT * FROM employees WHERE name LIKE '%keyword%'

    // Custom JPQL query (Java Persistence Query Language)
    @Query("SELECT e FROM Employee e WHERE e.salary > :minSalary")
    List<Employee> findHighEarners(@Param("minSalary") double minSalary);
}
Query Method Naming Convention
Spring Data JPA generates queries from method names automatically:
  • findByName → WHERE name = ?
  • findByDepartmentAndSalaryGreaterThan → WHERE department = ? AND salary > ?
  • findByNameContaining → WHERE name LIKE '%?%'
  • findBySalaryBetween → WHERE salary BETWEEN ? AND ?

7. Complete CRUD Application

Here's a complete working CRUD app with all 4 layers. This is what you need to know for PRA and Sprint 3.

Exam Tip
PRA and Sprint 3 often ask you to build or trace through a complete CRUD application. Understand how each layer connects. Data flows: Controller → Service → Repository → Database.

Layer 1: Entity — Employee.java

package com.example.demo.model;

import jakarta.persistence.*;

@Entity                                     // This class maps to a database table
@Table(name = "employees")                  // Table name: "employees"
public class Employee {

    @Id                                     // Primary key
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // Auto-increment
    private Long id;

    @Column(nullable = false)               // Cannot be null in database
    private String name;

    private String department;

    private double salary;

    // Default constructor — REQUIRED by JPA
    public Employee() {}

    // Constructor with fields (no id — database generates it)
    public Employee(String name, String department, double salary) {
        this.name = name;
        this.department = department;
        this.salary = salary;
    }

    // --- Getters and Setters ---
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getDepartment() { return department; }
    public void setDepartment(String department) { this.department = department; }

    public double getSalary() { return salary; }
    public void setSalary(double salary) { this.salary = salary; }
}

Layer 2: Repository — EmployeeRepository.java

package com.example.demo.repository;

import com.example.demo.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository                                        // Marks as data access layer
public interface EmployeeRepository
        extends JpaRepository<Employee, Long> {
    // Employee = Entity class
    // Long = type of the primary key (id)

    // All CRUD methods are inherited automatically!
    // findAll(), findById(), save(), deleteById(), etc.
}

Layer 3: Service — EmployeeService.java

package com.example.demo.service;

import com.example.demo.model.Employee;
import com.example.demo.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;

@Service                                            // Marks as service layer (business logic)
public class EmployeeService {

    @Autowired                                      // Inject repository automatically
    private EmployeeRepository repository;

    // GET ALL employees
    public List<Employee> getAllEmployees() {
        return repository.findAll();                  // Returns all rows from table
    }

    // GET ONE employee by ID
    public Employee getEmployeeById(Long id) {
        Optional<Employee> emp = repository.findById(id);  // May or may not exist
        if (emp.isPresent()) {
            return emp.get();                        // Found — return employee
        } else {
            throw new RuntimeException("Employee not found with id: " + id);
        }
    }

    // CREATE a new employee (or UPDATE if id exists)
    public Employee saveEmployee(Employee emp) {
        return repository.save(emp);                  // save() handles both INSERT and UPDATE
    }

    // UPDATE an existing employee
    public Employee updateEmployee(Long id, Employee updatedEmp) {
        Employee existing = getEmployeeById(id);     // Find existing record
        existing.setName(updatedEmp.getName());       // Update name
        existing.setDepartment(updatedEmp.getDepartment()); // Update department
        existing.setSalary(updatedEmp.getSalary());   // Update salary
        return repository.save(existing);             // Save updated record
    }

    // DELETE an employee
    public void deleteEmployee(Long id) {
        repository.deleteById(id);                   // Delete row with this ID
    }
}

Layer 4: Controller — EmployeeController.java

package com.example.demo.controller;

import com.example.demo.model.Employee;
import com.example.demo.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController                                     // This handles REST API requests
@RequestMapping("/api/employees")                   // Base URL for all endpoints
public class EmployeeController {

    @Autowired                                      // Inject service automatically
    private EmployeeService service;

    // GET /api/employees — Get all employees
    @GetMapping
    public List<Employee> getAll() {
        return service.getAllEmployees();              // Returns JSON array
    }

    // GET /api/employees/5 — Get one employee by ID
    @GetMapping("/{id}")
    public Employee getById(@PathVariable Long id) {
        return service.getEmployeeById(id);           // Returns JSON object
    }

    // POST /api/employees — Create new employee
    @PostMapping
    public Employee create(@RequestBody Employee emp) {
        return service.saveEmployee(emp);              // JSON body → Employee object
    }

    // PUT /api/employees/5 — Update employee
    @PutMapping("/{id}")
    public Employee update(@PathVariable Long id,
                           @RequestBody Employee emp) {
        return service.updateEmployee(id, emp);       // Update and return
    }

    // DELETE /api/employees/5 — Delete employee
    @DeleteMapping("/{id}")
    public String delete(@PathVariable Long id) {
        service.deleteEmployee(id);
        return "Employee with id " + id + " deleted";
    }
}
How It All Connects — Request Flow
  1. Client sends GET /api/employees/5
  2. Controller receives request → calls service.getEmployeeById(5)
  3. Service runs business logic → calls repository.findById(5)
  4. Repository runs SQL → SELECT * FROM employees WHERE id = 5
  5. Database returns row → Repository converts to Employee object
  6. Response travels back up: Repository → Service → Controller → Client (as JSON)

8. application.properties

The application.properties file (in src/main/resources/) configures your Spring Boot app — database connection, server settings, JPA behavior, etc.

Complete Configuration Example

# ─── Server Configuration ───
server.port=8080                              # Port the app runs on (default: 8080)

# ─── Database Connection ───
spring.datasource.url=jdbc:mysql://localhost:3306/employeedb
spring.datasource.username=root               # Database username
spring.datasource.password=password           # Database password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# ─── JPA / Hibernate Settings ───
spring.jpa.hibernate.ddl-auto=update          # Auto-create/update tables
spring.jpa.show-sql=true                      # Print SQL queries in console
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

ddl-auto Values — Important for Exams

ValueWhat It DoesWhen to Use
createDrops all tables, creates fresh every time app startsTesting only (DESTROYS data)
updateUpdates tables if entity changes, keeps existing dataDevelopment (most common)
validateOnly validates schema — doesn't change anythingProduction
noneDoes nothing — you manage schema manuallyProduction
create-dropCreates on startup, drops on shutdownUnit testing only
Exam Tip
Most exam questions about ddl-auto ask: "Which value preserves existing data while updating schema?" — Answer: update. "Which drops and recreates tables?" — Answer: create.
Never use create or create-drop in production
create deletes ALL your data every time the application restarts. Use update during development and validate or none in production.

9. Dependency Injection (DI)

What is Dependency Injection?

Dependency Injection means objects receive their dependencies from the outside instead of creating them internally. Spring creates and manages all objects (called "beans") and injects them where needed.

Without DI (Bad — Tight Coupling)

public class EmployeeService {
    // Creating dependency manually — TIGHT COUPLING
    private EmployeeRepository repo = new EmployeeRepository();  // BAD!
}

With DI (Good — Loose Coupling)

@Service
public class EmployeeService {
    // Spring injects the dependency — LOOSE COUPLING
    @Autowired                                       // Spring creates and injects this
    private EmployeeRepository repo;                  // GOOD!
}

Constructor Injection (Preferred)

@Service
public class EmployeeService {

    private final EmployeeRepository repo;           // Declared as final

    // Constructor injection — BEST PRACTICE
    public EmployeeService(EmployeeRepository repo) {
        this.repo = repo;                             // Spring passes repo here
    }
    // When there's only ONE constructor, @Autowired is optional
}

Field Injection vs Constructor Injection

AspectField Injection (@Autowired on field)Constructor Injection (Preferred)
Syntax@Autowired private Repo repo;public Service(Repo repo) { this.repo = repo; }
TestabilityHard to test (need reflection)Easy to test (pass mock in constructor)
ImmutabilityField can changeField is final — cannot change
Best practice?No (but commonly used in tutorials)Yes — recommended by Spring team
Why DI Matters
  • Loose coupling — classes don't depend on specific implementations
  • Testability — you can inject mock objects during testing
  • Flexibility — swap implementations without changing code
  • Spring manages lifecycle — you don't worry about creating/destroying objects

10. Exception Handling

When something goes wrong (e.g., employee not found), you want to return a clean error response instead of a stack trace. Spring Boot provides annotations for this.

Custom Exception Class

public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);   // Pass message to parent RuntimeException
    }
}

Using @ExceptionHandler (Local — Single Controller)

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {

    @GetMapping("/{id}")
    public Employee getById(@PathVariable Long id) {
        return service.getEmployeeById(id);  // Throws exception if not found
    }

    // Handles ResourceNotFoundException in THIS controller only
    @ExceptionHandler(ResourceNotFoundException.class)
    public String handleNotFound(ResourceNotFoundException ex) {
        return ex.getMessage();               // Return error message as response
    }
}

Using @RestControllerAdvice (Global — All Controllers)

@RestControllerAdvice          // Applies to ALL controllers in the application
public class GlobalExceptionHandler {

    // Handle specific exception
    @ExceptionHandler(ResourceNotFoundException.class)
    public Map<String, String> handleNotFound(ResourceNotFoundException ex) {
        Map<String, String> error = new HashMap<>();
        error.put("error", ex.getMessage());
        error.put("status", "404");
        return error;  // Returns JSON: {"error": "...", "status": "404"}
    }

    // Handle all other exceptions
    @ExceptionHandler(Exception.class)
    public Map<String, String> handleGeneral(Exception ex) {
        Map<String, String> error = new HashMap<>();
        error.put("error", "Something went wrong");
        error.put("status", "500");
        return error;
    }
}
@ExceptionHandler vs @RestControllerAdvice
  • @ExceptionHandler inside a controller — handles exceptions for that controller only
  • @RestControllerAdvice on a separate class — handles exceptions for all controllers (global)
  • @ControllerAdvice = same but returns views. @RestControllerAdvice = returns JSON/data.

11. Spring Boot vs Servlet Comparison

FeatureServletsSpring Boot
Configurationweb.xml (XML-based)Annotations + application.properties
ServerExternal Tomcat requiredEmbedded Tomcat (built-in)
HTTP handlingdoGet(), doPost() methods@GetMapping, @PostMapping annotations
Request datarequest.getParameter()@PathVariable, @RequestBody
Response formatManual response.getWriter().write()Automatic JSON conversion
DatabaseManual JDBC codeJPA Repository (automatic)
Code needed~100 lines for basic CRUD~30 lines for same CRUD
Dependency managementManually add each JARStarter dependencies in pom.xml
BoilerplateLots of repetitive codeMinimal — convention over config
Modern projects?Rarely used directlyIndustry standard
Same endpoint — Servlet vs Spring Boot
Servlet (verbose):
protected void doGet(HttpServletRequest request,
                     HttpServletResponse response) {
    String id = request.getParameter("id");
    // Manual JDBC connection, query, result parsing...
    response.setContentType("application/json");
    response.getWriter().write(jsonString);
}
  
Spring Boot (clean):
@GetMapping("/{id}")
public Employee getById(@PathVariable Long id) {
    return service.findById(id);  // Auto-converts to JSON
}
  
Exam Tip
Spring Boot uses Servlets internally — it runs on an embedded Tomcat servlet container. Spring Boot is NOT a replacement for servlets; it's built ON TOP of servlets. It just removes the boilerplate.

12. Practice Questions

Question 1
What does @SpringBootApplication combine?
  1. @Component + @Service + @Repository
  2. @Configuration + @EnableAutoConfiguration + @ComponentScan
  3. @RestController + @RequestMapping + @Autowired
  4. @Entity + @Table + @Id
B) @Configuration + @EnableAutoConfiguration + @ComponentScan. This is the most frequently asked Spring Boot annotation question.
Question 2
Which annotation is used to handle HTTP GET requests?
  1. @PostMapping
  2. @RequestMapping
  3. @GetMapping
  4. @ResponseBody
C) @GetMapping. It specifically handles GET requests. @RequestMapping can handle any method but needs the method attribute specified.
Question 3
What is the difference between @RestController and @Controller?
  1. @RestController is for REST APIs, @Controller is for Servlets
  2. @RestController = @Controller + @ResponseBody (returns data, not views)
  3. @RestController handles only GET, @Controller handles all methods
  4. There is no difference
B) @RestController = @Controller + @ResponseBody. @RestController returns data (JSON/text) directly. @Controller returns view names (HTML templates).
Question 4
Which annotation extracts a value from the URL path /employees/5?
  1. @RequestParam
  2. @RequestBody
  3. @PathVariable
  4. @RequestMapping
C) @PathVariable. It extracts values from the URL path. @RequestParam extracts from query parameters (?key=value). @RequestBody extracts from the request body (JSON).
Question 5
Which layer in Spring Boot architecture contains business logic?
  1. Controller layer
  2. Repository layer
  3. Service layer
  4. Entity layer
C) Service layer (@Service). Controller handles HTTP requests/responses. Repository handles database operations. Service contains all business logic and rules.
Question 6
What does spring.jpa.hibernate.ddl-auto=update do?
  1. Drops all tables and recreates them
  2. Only validates the schema without changes
  3. Updates tables when entity changes, preserves existing data
  4. Does nothing — schema is managed manually
C) update modifies the table structure when entity classes change but keeps existing data. create drops and recreates (data lost). validate only checks. none does nothing.
Question 7
Which JpaRepository method is used to insert OR update a record?
  1. insert()
  2. save()
  3. update()
  4. persist()
B) save(). If the entity has no ID (or ID doesn't exist in DB), it inserts. If the ID already exists, it updates. One method handles both operations.
Question 8
What does @Autowired do?
  1. Creates a new instance of a class
  2. Automatically injects a dependency managed by Spring
  3. Maps a URL to a method
  4. Makes a field the primary key
B) @Autowired tells Spring to automatically inject (provide) the required dependency. Spring creates the object and passes it to your class — you don't use new.
Question 9
Which annotation marks a Java class as a database table?
  1. @Table
  2. @Entity
  3. @Repository
  4. @Column
B) @Entity. It tells JPA that this Java class maps to a database table. @Table is optional — it specifies the exact table name. @Entity is mandatory for JPA to recognize the class.
Question 10
What HTTP method does @DeleteMapping handle?
  1. GET
  2. POST
  3. PUT
  4. DELETE
D) DELETE. Each annotation maps to its HTTP method: @GetMapping → GET, @PostMapping → POST, @PutMapping → PUT, @DeleteMapping → DELETE.
Question 11
Which is the correct order of layers when a request comes in?
  1. Service → Controller → Repository → Database
  2. Controller → Repository → Service → Database
  3. Controller → Service → Repository → Database
  4. Repository → Service → Controller → Database
C) Controller → Service → Repository → Database. The controller receives the HTTP request, passes to service for business logic, service calls repository for database operations.
Question 12
What does @GeneratedValue(strategy = GenerationType.IDENTITY) do?
  1. Generates a random UUID
  2. Uses auto-increment in the database for the primary key
  3. Creates a composite key
  4. Validates the primary key value
B) It tells JPA to let the database auto-increment the primary key value. The database assigns the next available number (1, 2, 3...) automatically when inserting a new row.
Question 13
What is the default port for a Spring Boot application?
  1. 3000
  2. 8080
  3. 80
  4. 443
B) 8080. You can change it in application.properties with server.port=9090. Port 80 is HTTP default, 443 is HTTPS default, 3000 is commonly used by Node.js.
Question 14
What does @RestControllerAdvice do?
  1. Creates a REST controller
  2. Handles exceptions globally across all controllers
  3. Adds authentication to controllers
  4. Logs all API requests
B) @RestControllerAdvice creates a global exception handler that catches exceptions from ANY controller in the application and returns a clean error response (JSON).
Question 15
Why is constructor injection preferred over field injection (@Autowired on field)?
  1. Constructor injection is faster
  2. Field injection doesn't work with Spring
  3. Constructor injection allows final fields and is easier to test
  4. Field injection requires XML configuration
C) Constructor injection allows fields to be final (immutable) and makes testing easier because you can pass mock objects directly through the constructor. Field injection requires reflection for testing.
Question 16
Which file lists all Maven dependencies in a Spring Boot project?
  1. application.properties
  2. web.xml
  3. pom.xml
  4. build.gradle
C) pom.xml (for Maven projects). It lists all dependencies like spring-boot-starter-web, spring-boot-starter-data-jpa, mysql-connector-j, etc. build.gradle is used for Gradle projects (alternative to Maven).
Question 17
What does findById() return in JpaRepository?
  1. The entity object directly
  2. A List of entities
  3. An Optional<Entity>
  4. null if not found
C) Optional<Entity>. It wraps the result — you use .isPresent() to check if found and .get() to retrieve the value. This avoids NullPointerException.
Question 18
What does @RequestBody do?
  1. Extracts query parameters from the URL
  2. Converts JSON in the request body to a Java object
  3. Returns the response body as HTML
  4. Extracts path variables from the URL
B) @RequestBody automatically converts (deserializes) JSON data from the HTTP request body into a Java object. Used with POST and PUT requests where the client sends data in the body.