0% found this document useful (0 votes)
11 views

Spring Boot Rest API

The document outlines best practices for developing REST APIs using Spring Boot, covering essential topics such as Spring Boot basics, REST API fundamentals, and creating REST APIs. It includes details on Spring Boot architecture, annotations, exception handling, validation, security, logging, caching, testing, API documentation, and deployment. Additionally, it provides interview-specific questions and offers to explain topics in further detail upon request.

Uploaded by

vksv08
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Spring Boot Rest API

The document outlines best practices for developing REST APIs using Spring Boot, covering essential topics such as Spring Boot basics, REST API fundamentals, and creating REST APIs. It includes details on Spring Boot architecture, annotations, exception handling, validation, security, logging, caching, testing, API documentation, and deployment. Additionally, it provides interview-specific questions and offers to explain topics in further detail upon request.

Uploaded by

vksv08
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 91

Core Java Best Practices

If you are working with Spring Boot REST API, here are the most important topics you
should focus on:

1. Spring Boot Basics


What is Spring Boot?

Difference between Spring and Spring Boot

Advantages of Spring Boot

Spring Boot Architecture

Spring Boot Annotations ( @SpringBootApplication , @Component , @Service ,


@Repository )

2. REST API Fundamentals


What is a REST API?

REST vs SOAP

HTTP Methods ( GET , POST , PUT , DELETE , PATCH )

Status Codes (200, 201, 400, 401, 403, 404, 500, etc.)

JSON vs XML

3. Creating a REST API in Spring Boot


Setting up a Spring Boot Project (Spring Initializr)

@RestController vs @Controller

@RequestMapping , @GetMapping , @PostMapping , @PutMapping , @DeleteMapping

1/4
Path Variables ( @PathVariable ) and Query Parameters ( @RequestParam )

Handling JSON Requests and Responses ( @RequestBody , @ResponseBody )

4. Spring Boot Data JPA & Database Connectivity


Spring Boot with MySQL / PostgreSQL

Using Spring Data JPA ( JpaRepository , CrudRepository )

Entity Relationships ( @OneToOne , @OneToMany , @ManyToOne , @ManyToMany )

Hibernate & Lazy Loading

Native Queries ( @Query and @NamedQuery )

5. Exception Handling in REST APIs


@ExceptionHandler Annotation

@ControllerAdvice for Global Exception Handling

Custom Exceptions ( ResponseStatusException )

6. Spring Boot Validation


Validating Request Body ( @Valid , @NotNull , @Size , etc.)

Custom Validators

Handling Validation Errors ( BindingResult )

7. Spring Boot Security (JWT & OAuth2)

2/4
Securing REST APIs with Spring Security

JWT (JSON Web Token) Authentication

OAuth2 Authorization

Role-Based Access Control (RBAC)

8. Logging & Monitoring


Logging with SLF4J and Logback

Using Spring Boot Actuator for Monitoring

Exposing Health & Metrics Endpoints

9. Spring Boot Caching


Enabling Caching ( @EnableCaching )

Using Redis Cache

Cache Eviction Strategies

10. Spring Boot Testing


Unit Testing with JUnit & Mockito

Integration Testing with MockMvc

Testing REST APIs with Postman

11. API Documentation with Swagger (OpenAPI)

3/4
Setting up Swagger ( springdoc-openapi )

Customizing API Documentation

12. Spring Boot Deployment


Deploying to Docker & Kubernetes

Deploying on AWS (EC2, S3, RDS)

Running Spring Boot with Apache Tomcat

Interview-Specific Questions
1. Difference between @RestController and @Controller

2. What is the difference between @Component , @Service , and @Repository ?

3. How do you handle exceptions in Spring Boot?

4. How do you secure a REST API using JWT?

5. How do you improve API performance in Spring Boot?

Next Steps?
Do you need code examples or in-depth explanations on any of these topics? 😊

4/4
Core Java Best Practices

I'll provide a detailed explanation of each topic related to Spring Boot Basics.

🔹 What is Spring Boot?


Spring Boot is a framework built on top of Spring Framework that simplifies Java application
development. It eliminates the need for extensive configuration and provides built-in
functionalities such as:

Embedded servers (Tomcat, Jetty, Undertow)

Auto-configuration (reduces boilerplate code)

Production-ready features (monitoring, health checks)

Microservices support (simplifies microservice architecture)

Key Features:

✅ Standalone applications (no external container required)


✅ Auto-configured Spring components
✅ Opinionated defaults (sensible pre-configurations)
✅ Production-ready with Actuator

🔹 Difference between Spring and Spring Boot


Feature Spring Framework Spring Boot

Configuration Requires manual XML or Java- Auto-configured, minimal setup


based configuration

Dependency Developers must define Comes with pre-configured


Management dependencies dependencies (Spring Boot Starters)

Embedded Server Requires an external server Has built-in embedded servers


(Tomcat, Jetty)

1/6
Feature Spring Framework Spring Boot

Microservices Used but requires extra setup Built specifically for microservices
development

Production Features Requires additional setup for Has built-in monitoring, logging, and
monitoring, logging Actuator

📌 Spring Boot simplifies Spring Framework by reducing manual configurations and


providing built-in production-ready features.

🔹 Advantages of Spring Boot


1. Faster Development:

Eliminates boilerplate code

Reduces configuration

Quick startup with embedded servers

2. Microservices Ready:

Easily build REST APIs

Supports distributed systems

3. Auto Configuration:

Automatically configures application components

4. Embedded Servers:

No need to deploy to an external server

5. Production-Ready:

Monitoring & Health Checks using Spring Boot Actuator

6. Simplified Dependency Management:

Uses Spring Boot Starters to bundle dependencies

🔹 Spring Boot Architecture


2/6
Spring Boot follows a layered architecture consisting of the following layers:

1️⃣ Presentation Layer (Controller Layer)


Handles user requests

Uses @RestController and @RequestMapping

2️⃣ Service Layer (Business Logic)


Contains business logic

Uses @Service

3️⃣ Repository Layer (Data Access Layer)


Communicates with the database

Uses @Repository

4️⃣ Persistence Layer (Database)


Stores and retrieves data

Uses JPA/Hibernate for ORM

🛠 Components in Spring Boot Architecture:

Spring Boot Starters → Pre-configured dependency packages

Spring Boot AutoConfiguration → Automatically configures Spring Beans

Spring Boot CLI → Allows running Spring Boot apps with minimal code

Spring Boot Actuator → Provides production monitoring & health checks

📌 Example of a Simple Layered Spring Boot Application:


java

@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;

@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {

3/6
return userService.getUserById(id);
}
}

java

@Service
public class UserService {
@Autowired
private UserRepository userRepository;

public User getUserById(Long id) {


return userRepository.findById(id).orElse(null);
}
}

java

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

🔹 Spring Boot Annotations


Annotations are used to simplify configuration in Spring Boot. Here are some of the most
important ones:

1️⃣ @SpringBootApplication

The entry point of a Spring Boot application.

Combines @Configuration , @EnableAutoConfiguration , and @ComponentScan .

Example:

java

@SpringBootApplication
public class MyApp {

4/6
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}

2️⃣ @Component

Marks a class as a Spring-managed bean.

Used for general components.

Example:

java

@Component
public class MyComponent {
public void doSomething() {
System.out.println("Component is working!");
}
}

3️⃣ @Service

Specialized version of @Component for business logic.

Example:

java

@Service
public class UserService {
public String getUser() {
return "John Doe";
}
}

5/6
4️⃣ @Repository

Specialized version of @Component for data access.

Used for DAO (Data Access Object) layer.

Example:

java

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

🎯 Summary
Annotation Purpose

@SpringBootApplication Main entry point of Spring Boot application

@Component Marks a general Spring bean

@Service Defines a service class (business logic)

@Repository Defines a repository class (data access)

✅ What's Next?
Would you like me to explain Spring Boot REST APIs in detail? 🚀

6/6
Core Java Best Practices

I'll provide an in-depth explanation of REST API Fundamentals in Spring Boot.

🔹 What is a REST API?


A REST API (Representational State Transfer Application Programming Interface) is a web
service that follows REST architecture principles to enable communication between client
and server over HTTP.

Key Characteristics of REST API:


1. Stateless: Each request from the client contains all the necessary information, and the
server does not store client state.

2. Client-Server Architecture: The client and server are independent; the frontend and
backend can evolve separately.

3. Cacheable: Responses can be cached to improve performance.

4. Layered System: The API can have multiple layers (e.g., security, load balancing) without
the client being aware of them.

5. Uniform Interface: Uses standard HTTP methods (GET, POST, PUT, DELETE, PATCH).

📌 Example:
A REST API for a User Management System:

GET /users → Fetch all users

GET /users/{id} → Fetch a user by ID

POST /users → Create a new user

PUT /users/{id} → Update user details

DELETE /users/{id} → Delete a user

🔹 1/5
🔹 REST vs SOAP
REST (Representational State
Feature Transfer) SOAP (Simple Object Access Protocol)

Protocol Uses HTTP Uses XML-based messaging

Data Format JSON, XML Only XML

Performance Lightweight and fast Heavier due to XML and WS-Security

Complexity Simple, uses standard HTTP More complex, requires more setup
methods

Usage Ideal for web services, Used in enterprise applications requiring


microservices, APIs high security

📌 REST is commonly used for modern web and mobile applications due to its simplicity
and performance advantages.

🔹 HTTP Methods
HTTP methods define actions performed on resources in a REST API.

HTTP
Method Description Example

GET Fetches data from the server GET /users (Get all users)

POST Creates a new resource POST /users (Create a new user)

PUT Updates an existing resource (full update) PUT /users/1 (Update entire user)

PATCH Updates part of an existing resource (partial PATCH /users/1 (Update only a few
update) fields)

DELETE Deletes a resource DELETE /users/1 (Delete a user)

📌 Example: A Spring Boot Controller using HTTP methods


java

@RestController
@RequestMapping("/users")
public class UserController {

2/5
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return "Fetching user with ID " + id;
}

@PostMapping
public String createUser(@RequestBody String user) {
return "User created: " + user;
}

@PutMapping("/{id}")
public String updateUser(@PathVariable Long id, @RequestBody String user) {
return "User with ID " + id + " updated";
}

@DeleteMapping("/{id}")
public String deleteUser(@PathVariable Long id) {
return "User with ID " + id + " deleted";
}
}

🔹 Status Codes
HTTP status codes indicate the result of an API request.

Status Code Meaning

200 OK Request successful

201 Created Resource created successfully

400 Bad Request Client sent an invalid request

401 Unauthorized Authentication required

403 Forbidden User does not have permission

404 Not Found Resource not found

500 Internal Server Error Server encountered an error

📌 Example: Handling Status Codes in Spring Boot


3/5
java

@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
Optional<User> user = userRepository.findById(id);
return user.map(ResponseEntity::ok)
.orElseGet(() ->
ResponseEntity.status(HttpStatus.NOT_FOUND).build());
}

🔹 JSON vs XML
REST APIs typically use JSON (JavaScript Object Notation) as the data format, but they can
also support XML.

Feature JSON XML

Format Lightweight, human-readable Verbose, uses tags

Parsing Faster parsing Slower due to complex structure

Data Types Supports numbers, strings, arrays, objects Treats everything as a string

Usage Preferred in modern web APIs Used in legacy systems

📌 Example of JSON Response:


json

{
"id": 1,
"name": "John Doe",
"email": "[email protected]"
}

📌 Example of XML Response:


xml

<User>
<id>1</id>

4/5
<name>John Doe</name>
<email>[email protected]</email>
</User>

Spring Boot supports both JSON and XML using Jackson (default for JSON) and JAXB (for
XML).

✅ Summary
Concept Explanation

REST API A stateless, client-server architecture for web services

REST vs SOAP REST is lightweight and JSON-based; SOAP is XML-heavy and enterprise-focused

HTTP Methods GET , POST , PUT , PATCH , DELETE used to interact with APIs

Status Codes HTTP response codes indicate success, failure, or errors

JSON vs XML JSON is lightweight and widely used, while XML is used in older systems

🚀 What's Next?
Would you like me to explain Building REST APIs in Spring Boot with practical examples? 🎯

5/5
Core Java Best Practices

I'll provide an in-depth explanation of Creating a REST API in Spring Boot step by step.

🔹 Setting up a Spring Boot Project


(Spring Initializr)
To create a Spring Boot project, follow these steps:

Step 1: Use Spring Initializr


1. Go to Spring Initializr

2. Select:

Project: Maven or Gradle

Language: Java

Spring Boot Version: Latest stable version

Dependencies: Spring Web (to create REST APIs)

3. Click Generate to download the project.

Step 2: Import into IDE


Extract the downloaded project and open it in IntelliJ IDEA, Eclipse, or VS Code.

Step 3: Main Class (Spring Boot Starter)


Spring Boot's entry point is a main class annotated with @SpringBootApplication :

java

@SpringBootApplication
public class RestApiApplication {
public static void main(String[] args) {
SpringApplication.run(RestApiApplication.class, args);

1/7
}
}

🔹 @RestController vs @Controller
Spring provides two annotations for handling web requests:

Annotation Purpose

@Controller Used for MVC (Model-View-Controller) applications, returns views (JSP,


Thymeleaf).

@RestController A combination of @Controller and @ResponseBody , used for REST APIs,


returning JSON responses.

📌 Example:
java

@Controller
public class ViewController {
@GetMapping("/home")
public String home() {
return "home"; // Returns a view (JSP/Thymeleaf)
}
}

@RestController
public class ApiController {
@GetMapping("/api/greet")
public String greet() {
return "Hello, REST API!"; // Returns JSON response
}
}

🔹 2/7
🔹 @RequestMapping, @GetMapping,
@PostMapping, @PutMapping,
@DeleteMapping
Spring Boot provides HTTP method-specific annotations:

Annotation HTTP Method Purpose

@GetMapping GET Fetch data from the server

@PostMapping POST Create new resources

@PutMapping PUT Update existing resources

@DeleteMapping DELETE Remove resources

@RequestMapping Any General mapping for any HTTP method

📌 Example: Implementing a Simple REST API


java

@RestController
@RequestMapping("/users")
public class UserController {

@GetMapping
public String getAllUsers() {
return "Fetching all users";
}

@PostMapping
public String createUser() {
return "Creating a new user";
}

@PutMapping("/{id}")
public String updateUser(@PathVariable int id) {
return "Updating user with ID " + id;
}

@DeleteMapping("/{id}")
public String deleteUser(@PathVariable int id) {
return "Deleting user with ID " + id;

3/7
}
}

🔹 Path Variables (@PathVariable) and


Query Parameters (@RequestParam)
1️⃣ Path Variables (@PathVariable)
Used to pass values as part of the URL.

📌 Example: Fetching a user by ID


java

@GetMapping("/{id}")
public String getUserById(@PathVariable int id) {
return "Fetching user with ID: " + id;
}

📌 Request: GET /users/5


📌 Response: "Fetching user with ID: 5"

2️⃣ Query Parameters (@RequestParam)


Used to send optional parameters in the URL.

📌 Example: Filtering users by name


java

@GetMapping("/search")
public String searchUser(@RequestParam String name) {
return "Searching for user: " + name;
}

4/7
📌 Request: GET /users/search?name=John
📌 Response: "Searching for user: John"

🔹 Handling JSON Requests and


Responses (@RequestBody,
@ResponseBody)
1️⃣ Sending JSON Request with @RequestBody
Used to convert incoming JSON into a Java object.

📌 Example: Creating a user


java

@RestController
@RequestMapping("/users")
public class UserController {

@PostMapping
public String createUser(@RequestBody User user) {
return "User created: " + user.getName();
}
}

📌 JSON Request Body:


json

{
"id": 1,
"name": "Alice",
"email": "[email protected]"
}

📌 Response: "User created: Alice"

5/7
2️⃣ Returning JSON Response with @ResponseBody
By default, @RestController returns JSON, but in @Controller , use @ResponseBody .

📌 Example: Returning a User as JSON


java

@RestController
@RequestMapping("/users")
public class UserController {

@GetMapping("/{id}")
public User getUser(@PathVariable int id) {
return new User(id, "Alice", "[email protected]");
}
}

📌 Response (JSON):
json

{
"id": 1,
"name": "Alice",
"email": "[email protected]"
}

✅ Summary
Concept Explanation

Spring Boot Setup Use Spring Initializr to create a project with Spring Web dependency.

@RestController vs @RestController is for APIs returning JSON, while @Controller


@Controller returns views.

HTTP Methods Use @GetMapping , @PostMapping , @PutMapping , @DeleteMapping


for API endpoints.

6/7
Concept Explanation

@PathVariable Extracts values from the URL path.

@RequestParam Extracts query parameters from the URL.

@RequestBody Converts JSON request into a Java object.

@ResponseBody Converts a Java object into a JSON response.

🚀 What's Next?
Would you like me to explain Exception Handling in Spring Boot REST APIs next? 🎯

7/7
Core Java Best Practices

I'll provide an in-depth explanation of Spring Boot Data JPA & Database Connectivity step
by step.

🔹 Spring Boot with MySQL /


PostgreSQL
Spring Boot supports multiple databases, including MySQL and PostgreSQL.

1️⃣ Add Dependencies


In pom.xml , add:

xml

<dependencies>
<!-- Spring Boot Starter Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- MySQL Driver -->


<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- PostgreSQL Driver (If using PostgreSQL) -->


<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>

1/9
2️⃣ Configure application.properties

For MySQL:

properties

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect

For PostgreSQL:

properties

spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

🔹 Using Spring Data JPA


(JpaRepository, CrudRepository)
Spring Data JPA provides interfaces for interacting with the database:

Interface Description

CrudRepository<T, Provides basic CRUD operations ( save , findById , findAll ,


ID> deleteById ).

2/9
Interface Description

JpaRepository<T, ID> Extends CrudRepository , provides additional JPA features like pagination
and sorting.

1️⃣ Create an Entity


java

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;

// Constructors, Getters, Setters


}

2️⃣ Create a Repository


java

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

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}

3/9
3️⃣ Create a Service Layer
java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserService {
@Autowired
private UserRepository userRepository;

public List<User> getAllUsers() {


return userRepository.findAll();
}

public User getUserByEmail(String email) {


return userRepository.findByEmail(email);
}

public User saveUser(User user) {


return userRepository.save(user);
}
}

4️⃣ Create a Controller


java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController

4/9
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;

@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}

@GetMapping("/{email}")
public User getUserByEmail(@PathVariable String email) {
return userService.getUserByEmail(email);
}

@PostMapping
public User createUser(@RequestBody User user) {
return userService.saveUser(user);
}
}

🔹 Entity Relationships (@OneToOne,


@OneToMany, @ManyToOne,
@ManyToMany)
1️⃣ @OneToOne (One-to-One Relationship)
Example: A User has one Profile

java

@Entity
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String bio;

5/9
@OneToOne
@JoinColumn(name = "user_id")
private User user;
}

2️⃣ @OneToMany (One-to-Many Relationship)


Example: A User has multiple Orders

java

@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String product;

@ManyToOne
@JoinColumn(name = "user_id")
private User user;
}

java

@Entity
public class User {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Order> orders;
}

3️⃣ @ManyToOne (Many-to-One Relationship)


Example: Many Employees belong to one Department

6/9
java

@Entity
public class Employee {
@ManyToOne
@JoinColumn(name = "department_id")
private Department department;
}

4️⃣ @ManyToMany (Many-to-Many Relationship)


Example: A Student can enroll in multiple Courses

java

@Entity
public class Student {
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Course> courses;
}

🔹 Hibernate & Lazy Loading


Lazy Loading ( FetchType.LAZY ): Data is loaded only when required.

Eager Loading ( FetchType.EAGER ): Data is loaded immediately.

📌 Example: Lazy Loading


java

7/9
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;

📌 Example: Eager Loading


java

@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)


private List<Order> orders;

🔹 Native Queries (@Query and


@NamedQuery)
1️⃣ Using @Query
java

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

public interface UserRepository extends JpaRepository<User, Long> {


@Query("SELECT u FROM User u WHERE u.email = ?1")
User findUserByEmail(String email);
}

2️⃣ Using @NamedQuery


Define in User.java :

java

@NamedQuery(
name = "User.findByEmail",
query = "SELECT u FROM User u WHERE u.email = :email"

8/9
)
@Entity
public class User { ... }

Use in UserRepository :

java

User findByEmail(@Param("email") String email);

✅ Summary
Concept Explanation

Spring Boot with Configuring database connection using


MySQL/PostgreSQL application.properties .

Spring Data JPA Using JpaRepository and CrudRepository for database


operations.

Entity Relationships @OneToOne , @OneToMany , @ManyToOne , @ManyToMany .

Hibernate & Lazy Loading Controls when related data is fetched.

Native Queries Custom queries using @Query and @NamedQuery .

🚀 What's Next?
Would you like me to explain Spring Boot Exception Handling in REST APIs next? 🎯

9/9
Core Java Best Practices
🚀 Exception Handling in REST APIs (Spring Boot)
Exception handling in a Spring Boot REST API ensures that errors are properly handled and
informative responses are returned to clients.

🔹 Types of Exception Handling in


Spring Boot
1️⃣ Using in Controller (Not recommended)
try-catch
2️⃣ Using (Method-Level Exception Handling)
@ExceptionHandler
3️⃣ Using (Global Exception Handling)
@ControllerAdvice
4️⃣ Custom Exceptions using ResponseStatusException

1️⃣ Basic Exception Handling (try-catch)


📌 This is the simplest way, but not recommended because it clutters controllers.
java

@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
try {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
} catch (UserNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
}

✅ Better Approach: Use @ExceptionHandler or @ControllerAdvice .

1/6
2️⃣ Handling Exceptions with
@ExceptionHandler
The @ExceptionHandler annotation catches specific exceptions inside a single controller.

📌 Example: Handling a UserNotFoundException

java

@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;

@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id); // Throws UserNotFoundException
}

@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException
e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
}
}

✅ Pros: Keeps exception handling separate from business logic.


❌ Cons: Works only inside this controller.

3️⃣ Global Exception Handling with


@ControllerAdvice
If we want one place to handle exceptions for all controllers, we use @ControllerAdvice .

2/6
📌 Steps to Create Global Exception Handling
1️⃣ Create a Custom Exception ( UserNotFoundException )

java

public class UserNotFoundException extends RuntimeException {


public UserNotFoundException(String message) {
super(message);
}
}

2️⃣ Create a Global Exception Handler


java

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestControllerAdvice // Global Exception Handler


public class GlobalExceptionHandler {

@ExceptionHandler(UserNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handleUserNotFoundException(UserNotFoundException e) {
return e.getMessage();
}

@ExceptionHandler(Exception.class) // Catch-all Exception Handler


@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleGenericException(Exception e) {
return "An error occurred: " + e.getMessage();
}
}

✅ Pros: Centralized exception handling for all controllers.


✅ Handles multiple exceptions in one place.

4️⃣ 3/6
4️⃣ Custom Exceptions using
ResponseStatusException
Spring Boot provides ResponseStatusException to return HTTP errors directly inside the
service layer.

📌 Example: Throwing ResponseStatusException

java

import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

public User getUserById(Long id) {


return userRepository.findById(id).orElseThrow(() ->
new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found"));
}

✅ Pros: Directly throws exceptions from the service layer.


❌ Cons: Doesn't allow custom response structure.

🔹 Exception Response with JSON


Structure
Instead of returning plain text, we can return a JSON response.

📌 Example: Custom Error Response


1️⃣ Create an ErrorResponse DTO

java

public class ErrorResponse {


private String message;
private int status;

4/6
public ErrorResponse(String message, int status) {
this.message = message;
this.status = status;
}

// Getters and Setters


}

2️⃣ Modify GlobalExceptionHandler to return JSON

java

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse>
handleUserNotFoundException(UserNotFoundException e) {
ErrorResponse errorResponse = new ErrorResponse(e.getMessage(),
HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(Exception e) {
ErrorResponse errorResponse = new ErrorResponse("Something went wrong",
HttpStatus.INTERNAL_SERVER_ERROR.value());
return new ResponseEntity<>(errorResponse,
HttpStatus.INTERNAL_SERVER_ERROR);
}
}

📌 Now, if an exception occurs, API response will be JSON, like:


json

{
"message": "User not found",
"status": 404
}

🔹 5/6
🔹 Summary
Approach Description Scope

try-catch in Controller Simple, but makes code messy Single Method

@ExceptionHandler Handles exceptions inside a specific controller Single Controller

@ControllerAdvice Centralized exception handling for all controllers Global

ResponseStatusException Throws HTTP errors directly from service layer Service Layer

🚀 Next Steps
Would you like me to explain Spring Boot Logging & Monitoring (with SLF4J, Logback, and
Actuator)? 📊

6/6
Core Java Best Practices

🚀 Spring Boot Validation


Validation in Spring Boot ensures that incoming data in API requests meets the required
format and constraints before processing it.

🔹 Topics Covered
✅ Validating Request Body ( @Valid , @NotNull , @Size , etc.)
✅ Custom Validators
✅ Handling Validation Errors ( BindingResult )

1️⃣ Adding Validation to Spring Boot


Spring Boot uses the Jakarta Validation API (JSR-380), which provides annotations like
@NotNull , @Size , @Min , etc.

📌 Step 1: Add Dependencies


If you're using Spring Boot Starter Web, it already includes validation dependencies.
But if not, add this to pom.xml :

xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2️⃣ 1/7
2️⃣ Validating Request Body Using
@Valid
We use @Valid along with Jakarta Validation annotations in DTOs.

📌 Example: Creating a UserDTO with Validation Rules

java

import jakarta.validation.constraints.*;

public class UserDTO {

@NotNull(message = "Name cannot be null")


@Size(min = 3, message = "Name must be at least 3 characters")
private String name;

@Email(message = "Invalid email format")


private String email;

@Min(value = 18, message = "Age must be at least 18")


private int age;

// Getters and Setters


}

✅ Validation Rules Used:


@NotNull → Ensures the field is not null.

@Size(min = 3) → Ensures minimum length of 3.

@Email → Ensures the field follows email format.

@Min(18) → Ensures the age is at least 18.

3️⃣ Validating Request Body in


Controller

2/7
Now, let's create a REST API to validate UserDTO .

📌 Controller Using @Valid

java

import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

@PostMapping("/create")
public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO user) {
return ResponseEntity.ok("User created successfully!");
}
}

✅ What Happens?
If the request body is valid, the API returns "User created successfully!"

If the request body fails validation, Spring Boot automatically returns an error
response.

4️⃣
(
Handling Validation Errors
BindingResult)
By default, Spring Boot returns a generic error message if validation fails.
We can customize this using BindingResult .

📌 Controller Using BindingResult

java

@PostMapping("/create")
public ResponseEntity<?> createUser(@Valid @RequestBody UserDTO user, BindingResult

3/7
result) {
if (result.hasErrors()) {
String errors = result.getAllErrors().stream()
.map(error -> error.getDefaultMessage())
.reduce("", (a, b) -> a + ", " + b);
return ResponseEntity.badRequest().body(errors);
}
return ResponseEntity.ok("User created successfully!");
}

✅ Customizes Validation Errors instead of returning a generic Spring Boot error.


📌 Example API Request:
json

{
"name": "Jo",
"email": "invalid-email",
"age": 16
}

📌 Response:
json

{
"errors": "Name must be at least 3 characters, Invalid email format, Age must be
at least 18"
}

5️⃣ Global Exception Handling for


Validation Errors
Instead of handling errors inside each controller, we can create a global handler.

📌 Global Exception Handler Using @ControllerAdvice

4/7
java

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>>
handleValidationErrors(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));

return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);


}
}

✅ Now, all validation errors return JSON output:


json

{
"name": "Name must be at least 3 characters",
"email": "Invalid email format",
"age": "Age must be at least 18"
}

6️⃣ Custom Validators in Spring Boot


If built-in validation doesn’t meet your needs, create a custom validator.

5/7
📌 Example: Creating a Custom Age Validator
1️⃣ Create a Custom Annotation
java

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = AgeValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidAge {
String message() default "Age must be between 18 and 60";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

2️⃣ Create the Validator Class


java

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

public class AgeValidator implements ConstraintValidator<ValidAge, Integer> {


@Override
public boolean isValid(Integer age, ConstraintValidatorContext context) {
return age != null && age >= 18 && age <= 60;
}
}

3️⃣ Use It in the DTO


java

public class UserDTO {

@ValidAge
private int age;

6/7
// Other fields, getters, and setters
}

📌 Now, if age is not between 18 and 60, the API will return:
json

{
"age": "Age must be between 18 and 60"
}

🔹 Summary
Feature Description

Basic Validation Use @Valid in DTOs to enforce validation rules

Handling Validation Errors Use BindingResult to return custom error messages

Global Exception Handling Use @ControllerAdvice to handle all validation exceptions

Custom Validators Create custom annotations for complex validation logic

🚀 Next Steps
Would you like me to explain Spring Boot Logging & Monitoring (SLF4J, Logback,
Actuator)? 📊

7/7
Core Java Best Practices

🚀 Spring Boot Security (JWT &


OAuth2)
Spring Boot Security is crucial for securing REST APIs against unauthorized access. We use
Spring Security, JWT (JSON Web Token) for authentication, and OAuth2 for authorization.

🔹 Topics Covered
✅ Securing REST APIs with Spring Security
✅ JWT (JSON Web Token) Authentication
✅ OAuth2 Authorization
✅ Role-Based Access Control (RBAC)

1️⃣ Securing REST APIs with Spring


Security
📌 What is Spring Security?
Spring Security is a powerful framework that provides authentication, authorization, and
protection against attacks (CSRF, CORS, etc.).

📌 Adding Dependencies (Spring Security & JWT)


Add these to pom.xml :

xml

<dependency>
<groupId>org.springframework.boot</groupId>

1/9
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.11.5</version>
</dependency>

2️⃣ JWT (JSON Web Token)


Authentication
📌 What is JWT?
JWT is a compact, secure token used for authentication. It contains:

Header (Algorithm & Type)

Payload (User Data)

Signature (Verifies authenticity)

📌 How JWT Authentication Works?


1. User sends username & password.

2. If valid, the server generates a JWT token and sends it back.

3. The client stores the token (e.g., in localStorage) and includes it in every API request.

4. The server validates the token and processes the request.

📌 Implementing JWT Authentication


1️⃣ Create for User Authentication
UserDetailsService

java

2/9
import org.springframework.security.core.userdetails.*;

public class CustomUserDetailsService implements UserDetailsService {


@Override
public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
if ("admin".equals(username)) {
return User.withUsername("admin")
.password("{noop}password") // NoOpPasswordEncoder for
simplicity
.roles("ADMIN")
.build();
}
throw new UsernameNotFoundException("User not found");
}
}

✅ Returns a User object with roles.

2️⃣ Generate JWT Token


java

import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import java.util.Date;

@Component
public class JwtUtil {
private String secretKey = "mySecret";

public String generateToken(String username) {


return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 *
60)) // 1 hour
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();

3/9
}

public String extractUsername(String token) {


return
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
}

public boolean validateToken(String token, String username) {


return username.equals(extractUsername(token)) && !isTokenExpired(token);
}

private boolean isTokenExpired(String token) {


return
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getExpiration().
Date());
}
}

✅ Generates, extracts, and validates JWT tokens.

3️⃣ Create an Authentication Controller


java

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {

private final JwtUtil jwtUtil;

public AuthController(JwtUtil jwtUtil) {


this.jwtUtil = jwtUtil;
}

@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String
password) {

4/9
if ("admin".equals(username) && "password".equals(password)) {
return jwtUtil.generateToken(username);
}
return "Invalid Credentials";
}
}

✅ When a user logs in, a JWT token is generated.


📌 Example Request:
json

POST /auth/login
{
"username": "admin",
"password": "password"
}

📌 Response:
json

{
"token": "eyJhbGciOiJIUzI1NiIs..."
}

4️⃣ Protecting Endpoints with JWT Filter


java

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*;
import javax.servlet.http.*;

public class JwtFilter extends OncePerRequestFilter {


private final JwtUtil jwtUtil;
private final CustomUserDetailsService userDetailsService;

5/9
public JwtFilter(JwtUtil jwtUtil, CustomUserDetailsService userDetailsService) {
this.jwtUtil = jwtUtil;
this.userDetailsService = userDetailsService;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");

if (token != null && token.startsWith("Bearer ")) {


token = token.substring(7);
String username = jwtUtil.extractUsername(token);
UserDetails userDetails =
userDetailsService.loadUserByUsername(username);

if (jwtUtil.validateToken(token, username)) {
SecurityContextHolder.getContext().setAuthentication(new
UsernamePasswordAuthenticationToken(userDetails, null,
userDetails.getAuthorities()));
}
}
chain.doFilter(request, response);
}
}

✅ Validates JWT on each request and sets security context.

5️⃣ Configure Spring Security


java

import org.springframework.context.annotation.*;
import
org.springframework.security.config.annotation.authentication.configuration.Authenticat
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

6/9
@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws
Exception {
http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/auth/login").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
return http.build();
}
}

✅ Only allows login API without authentication. Other APIs require a JWT token.

3️⃣ OAuth2 Authorization (Google,


GitHub, Facebook Login)
📌 What is OAuth2?
OAuth2 is an authorization framework that allows users to log in via Google, GitHub,
Facebook, etc.

📌 Adding OAuth2 Dependencies


xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

📌 Configuring OAuth2 Login (Google Example)


7/9
Add this to application.yml :

yaml

spring:
security:
oauth2:
client:
registration:
google:
client-id: your-client-id
client-secret: your-client-secret
scope: profile, email

📌 Enable OAuth2 Login


java

import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class OAuth2SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws
Exception {
http.oauth2Login();
return http.build();
}
}

✅ Users can now log in using Google OAuth2!

4️⃣ Role-Based Access Control (RBAC)


We can restrict API access based on user roles.

8/9
📌 Secure APIs Based on Roles
java

.authorizeHttpRequests()
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()

✅ Users with ROLE_ADMIN can access /admin/** APIs, while ROLE_USER and ROLE_ADMIN
can access /user/** APIs.

🔹 Summary
Feature Description

Spring Security Basic security framework for authentication

JWT Token-based authentication for securing REST APIs

OAuth2 Allows login via Google, GitHub, etc.

RBAC Restricts API access based on user roles

🚀 Next Steps
Would you like me to explain Logging & Monitoring in Spring Boot (SLF4J, Logback,
Actuator)? 📊

9/9
Core Java Best Practices

🚀 Logging & Monitoring in Spring


Boot
Proper logging & monitoring in Spring Boot ensures application health, performance, and
debugging capabilities.

🔹 Topics Covered
✅ Logging with SLF4J and Logback
✅ Using Spring Boot Actuator for Monitoring
✅ Exposing Health & Metrics Endpoints

1️⃣ Logging with SLF4J and Logback


📌 What is SLF4J?
SLF4J (Simple Logging Facade for Java) is a logging abstraction that allows developers to
switch between different logging frameworks (Logback, Log4j, JUL) without modifying code.

📌 Spring Boot uses Logback as the default logging framework.


📌 Adding SLF4J & Logback Dependencies
Spring Boot includes SLF4J & Logback by default, but if missing, add:

xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

1/6
📌 Using SLF4J in Java Classes
java

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/logging")
public class LoggingController {

private static final Logger logger =


LoggerFactory.getLogger(LoggingController.class);

@GetMapping("/test")
public String logTest() {
logger.info("INFO: This is an info message");
logger.debug("DEBUG: Debugging details");
logger.warn("WARN: Warning message");
logger.error("ERROR: Something went wrong!");
return "Logging Example in Spring Boot";
}
}

✅ SLF4J supports different log levels: DEBUG, INFO, WARN, ERROR.

📌 Configuring Logback ( logback.xml )

Located in src/main/resources/

xml

<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} -
%msg%n</pattern>

2/6
</encoder>
</appender>

<appender name="FILE" class="ch.qos.logback.core.FileAppender">


<file>logs/app.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} -
%msg%n</pattern>
</encoder>
</appender>

<logger name="com.example" level="DEBUG"/>


<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>

✅ Sends logs to console and stores them in logs/app.log .

📌 Log Levels Configuration in application.properties

properties

logging.level.root=INFO
logging.level.com.example=DEBUG
logging.file.name=logs/app.log
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} -
%msg%n

✅ Defines logging levels & custom patterns.

2️⃣ Using Spring Boot Actuator for Monitoring


📌 What is Spring Boot Actuator?
3/6
Spring Boot Actuator monitors and manages applications with built-in endpoints for:

Health Checks ( /actuator/health )

Metrics ( /actuator/metrics )

Application Info ( /actuator/info )

Log Levels ( /actuator/loggers )

📌 Adding Actuator Dependency


xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

📌 Enabling Actuator Endpoints in application.properties

properties

# Enable all Actuator endpoints


management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
management.endpoint.info.enabled=true

✅ Enables health, metrics, and logging endpoints.

3️⃣ Exposing Health & Metrics Endpoints


📌 Checking Application Health

4/6
Run the app and visit:
📌 http://localhost:8080/actuator/health

json

{
"status": "UP"
}

✅ Indicates application is running smoothly.

📌 Viewing System Metrics


📌 http://localhost:8080/actuator/metrics
Lists available metrics (JVM, CPU, memory usage, requests, etc.).

📌 Example:
📌 http://localhost:8080/actuator/metrics/jvm.memory.used

json

{
"name": "jvm.memory.used",
"measurements": [{"statistic": "VALUE", "value": 50914560}]
}

✅ Shows JVM memory usage.

📌 Monitoring Log Levels Dynamically


📌 http://localhost:8080/actuator/loggers/com.example
Returns current logging level:

json

{
"configuredLevel": "DEBUG",

5/6
"effectiveLevel": "DEBUG"
}

✅ Dynamically change log levels via API.


📌 Example: Change Log Level to ERROR
sh

curl -X POST http://localhost:8080/actuator/loggers/com.example -H "Content-Type:


application/json" -d '{"configuredLevel":"ERROR"}'

✅ No need to restart the application!

🔹 Summary
Feature Description

SLF4J & Logback Logs events with different log levels (INFO, DEBUG, ERROR)

Logback Configuration Stores logs in a file and formats log output

Spring Boot Actuator Provides system monitoring endpoints

Health & Metrics API /actuator/health , /actuator/metrics for system monitoring

Dynamic Log Level Changes Modify log levels at runtime via Actuator

🚀 Next Steps
Would you like to explore Spring Boot Caching (EhCache, Redis) for performance
optimization? 🚀

6/6
Core Java Best Practices

🚀 Spring Boot Caching


Spring Boot Caching improves application performance by reducing database queries and
reusing previously fetched data.

🔹 Topics Covered
✅ Enabling Caching ( @EnableCaching )
✅ Using Redis Cache
✅ Cache Eviction Strategies

1️⃣ Enabling Caching ( @EnableCaching )

📌 What is Caching?
Caching stores frequently used data in memory (RAM) to improve performance by avoiding
repeated database queries.

📌 Adding Caching Dependency


Spring Boot provides caching support with Spring Cache. Add this dependency:

xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

1/6
✅ Spring Boot supports multiple caching providers like EhCache, Redis, Caffeine, etc.

📌 Enabling Caching in Spring Boot ( @EnableCaching )

Add @EnableCaching in your main class:

java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}

✅ This enables caching in the application.

📌 Caching with @Cacheable

java

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

@Cacheable(value = "products", key = "#id")


public String getProductById(Long id) {
System.out.println("Fetching product from DB...");
return "Product-" + id;

2/6
}
}

✅ First-time execution fetches data from the database. Next time, it retrieves from the
cache.

2️⃣ Using Redis Cache


📌 Why Redis?
🔹 In-Memory Cache → Super Fast
🔹 Supports Expiration → Auto removes old cache
🔹 Scalable → Handles large loads efficiently

📌 Adding Redis Dependencies


xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

✅ This integrates Redis with Spring Boot.

📌 Configuring Redis in application.properties

properties

spring.redis.host=localhost
spring.redis.port=6379

✅ Ensure Redis is running ( redis-server command).

3/6
📌 Creating Redis Cache Configuration
java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

@Bean
public LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}

✅ This sets up Redis as the caching provider.

📌 Using Redis Cache with @Cacheable

java

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

4/6
@Service
public class ProductService {

@Cacheable(value = "productCache", key = "#id")


public String getProductById(Long id) {
System.out.println("Fetching product from DB...");
return "Product-" + id;
}
}

✅ Now, data is stored in Redis instead of memory.

3️⃣ Cache Eviction Strategies


Sometimes, cached data must be cleared when data updates.

📌 Using @CacheEvict

java

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

@CacheEvict(value = "productCache", key = "#id")


public void removeProductFromCache(Long id) {
System.out.println("Product removed from cache.");
}
}

✅ Deletes specific cache entry when a product is updated or deleted.

📌 Using @CachePut

5/6
If you want to update cache when updating data, use @CachePut .

java

import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

@CachePut(value = "productCache", key = "#id")


public String updateProduct(Long id, String name) {
System.out.println("Updating product in DB...");
return name;
}
}

✅ Updates cache instead of just removing it.

🔹 Summary
Feature Description

@EnableCaching Enables caching in Spring Boot

@Cacheable Stores method results in cache

Redis Integration Uses Redis for faster caching

@CacheEvict Removes data from cache

@CachePut Updates data in cache

🚀 Next Steps
Would you like to explore Spring Boot Email Sending (SMTP, JavaMailSender)? 📧

6/6
Core Java Best Practices

🚀 Spring Boot Testing


Testing is essential in Spring Boot applications to ensure reliability, maintainability, and
bug-free code. Spring Boot provides various testing frameworks like JUnit, Mockito, and
MockMvc to perform unit and integration testing.

🔹 Topics Covered
✅ Unit Testing with JUnit & Mockito
✅ Integration Testing with MockMvc
✅ Testing REST APIs with Postman

1️⃣ Unit Testing with JUnit & Mockito


📌 What is Unit Testing?
Unit Testing tests individual components (methods/classes) in isolation without external
dependencies.

📌 Tools Used:
✅ JUnit 5 - Java Testing Framework
✅ Mockito - Mock Objects for Unit Testing

📌 Adding JUnit & Mockito Dependencies


Add these dependencies in pom.xml :

xml

1/7
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

✅ This includes JUnit and Mockito for testing.

📌 Example: Unit Testing a Service Layer


Let's create a ProductService and test it using JUnit & Mockito.

✅ Product Entity
java

public class Product {


private Long id;
private String name;
private double price;

// Constructor, Getters, and Setters


}

✅ Product Repository (Mocked in Test)


java

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

public interface ProductRepository extends JpaRepository<Product, Long> {


}

2/7
✅ Product Service
java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;

@Service
public class ProductService {

@Autowired
private ProductRepository productRepository;

public Product getProductById(Long id) {


return productRepository.findById(id).orElseThrow(() -> new
RuntimeException("Product not found"));
}
}

✅ ProductService interacts with ProductRepository .

📌 Writing JUnit Test for ProductService

✅ Creating a Test Class


java

import static org.junit.jupiter.api.Assertions.*;


import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Optional;

@ExtendWith(MockitoExtension.class)

3/7
public class ProductServiceTest {

@Mock
private ProductRepository productRepository;

@InjectMocks
private ProductService productService;

@Test
public void testGetProductById() {
Product product = new Product(1L, "Laptop", 75000);
when(productRepository.findById(1L)).thenReturn(Optional.of(product));

Product result = productService.getProductById(1L);

assertEquals("Laptop", result.getName());
assertEquals(75000, result.getPrice());
}
}

✅ @Mock → Mocks ProductRepository .


✅ @InjectMocks → Injects the mock into ProductService .
✅ when(...).thenReturn(...) → Defines mock behavior.

2️⃣ Integration Testing with MockMvc


📌 What is Integration Testing?
Integration Testing tests the interaction between components (e.g., Controller & Service).

📌 Tools Used:
✅ MockMvc - Mocks HTTP requests
✅ Spring Boot Test - Test Spring Boot components

📌 Adding MockMvc Dependency

4/7
(Spring Boot already includes this in spring-boot-starter-test ).

📌 Example: Integration Testing a REST Controller


✅ Product Controller
java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/products")
public class ProductController {

@Autowired
private ProductService productService;

@GetMapping("/{id}")
public Product getProductById(@PathVariable Long id) {
return productService.getProductById(id);
}
}

✅ The API returns a product by ID.

📌 Writing MockMvc Test for ProductController

✅ Creating a Test Class


java

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;


import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

5/7
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(ProductController.class)
public class ProductControllerTest {

@Autowired
private MockMvc mockMvc;

@Test
public void testGetProductById() throws Exception {
mockMvc.perform(get("/products/1"))
.andExpect(status().isOk());
}
}

✅ Mocks an HTTP GET request to /products/1


✅ Checks if the status is .
200 OK

3️⃣ Testing REST APIs with Postman


📌 What is Postman?
Postman is a tool for testing REST APIs by sending HTTP requests and analyzing responses.

📌 Steps to Test in Postman:


1. Open Postman

2. Send a GET request to http://localhost:8080/products/1

3. Check the Response

json

{
"id": 1,
"name": "Laptop",
"price": 75000
}

6/7
✅ If the response matches expected output, the API works correctly.

🔹 Summary
Testing Type Tools Used Purpose

Unit Testing JUnit, Mockito Tests individual methods in isolation

Integration Testing MockMvc Tests interaction between components

API Testing Postman Manually tests REST APIs

🚀 Next Steps
Would you like a detailed guide on Spring Boot Email Sending (SMTP, JavaMailSender)? 📧

7/7
Core Java Best Practices

🚀 API Documentation with Swagger


(OpenAPI) in Spring Boot
Swagger (OpenAPI) is a powerful tool for generating and documenting REST APIs. It helps
developers and consumers understand and interact with APIs without needing direct
backend access.

🔹 Topics Covered
✅ What is Swagger (OpenAPI)?
✅ Setting up Swagger with springdoc-openapi
✅ Customizing API Documentation

1️⃣ What is Swagger (OpenAPI)?


Swagger is an API specification framework used for documenting RESTful web services.

OpenAPI is the standard for defining APIs, and Swagger is one of its implementations.

With Swagger, you can:


✅ Auto-generate API documentation
✅ Test APIs using a built-in UI
✅ Share API documentation easily

2️⃣ Setting up Swagger ( springdoc-openapi )

📌 Add Maven Dependency


1/5
Add the following dependency in pom.xml :

xml

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>

✅ This automatically integrates Swagger into your Spring Boot application.

📌 Access Swagger UI
Once the application is running, open Swagger UI in your browser:
📌 URL: http://localhost:8080/swagger-ui.html

You will see an interactive API documentation UI where you can test API endpoints directly.

3️⃣ Creating a Sample REST API


📌 Create a ProductController API

java

import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Arrays;

@RestController
@RequestMapping("/products")
public class ProductController {

@GetMapping
public List<String> getAllProducts() {
return Arrays.asList("Laptop", "Smartphone", "Tablet");

2/5
}

@GetMapping("/{id}")
public String getProductById(@PathVariable int id) {
List<String> products = Arrays.asList("Laptop", "Smartphone", "Tablet");
return products.get(id);
}
}

✅ Run the application and visit: http://localhost:8080/swagger-ui.html


✅ You will see the APIs listed with a "Try it out" button!

4️⃣ Customizing API Documentation


📌 Add @Operation and @ApiResponses Annotations

To enhance API documentation, use OpenAPI annotations.

java

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Arrays;

@RestController
@RequestMapping("/products")
public class ProductController {

@Operation(summary = "Get all products", description = "Retrieves a list of


available products")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Products retrieved
successfully"),
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@GetMapping

3/5
public List<String> getAllProducts() {
return Arrays.asList("Laptop", "Smartphone", "Tablet");
}

@Operation(summary = "Get a product by ID", description = "Fetches a single


product based on its ID")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Product found"),
@ApiResponse(responseCode = "404", description = "Product not found")
})
@GetMapping("/{id}")
public String getProductById(@PathVariable int id) {
List<String> products = Arrays.asList("Laptop", "Smartphone", "Tablet");
return products.get(id);
}
}

✅ Visit http://localhost:8080/swagger-ui.html again and see the enhanced API


documentation!

5️⃣ Customizing Swagger UI


By default, Swagger UI has a standard look, but we can customize it.

📌 Change API Title & Description


Create a configuration file:

java

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()

4/5
.info(new Info()
.title("Product API")
.version("1.0")
.description("API documentation for managing products"));
}
}

✅ Now the Swagger UI will show a custom title and description!

🔹 Summary
Feature Swagger Integration

Set up Swagger springdoc-openapi

API UI URL http://localhost:8080/swagger-ui.html

Custom API Descriptions @Operation , @ApiResponses

Custom API Title & Info SwaggerConfig class

🚀 Next Steps
Would you like a detailed guide on Spring Boot Deployment (Docker, Kubernetes, AWS,
Heroku)? 🚀

5/5
Core Java Best Practices

🚀 Spring Boot Deployment Guide


Spring Boot applications can be deployed in multiple ways, including Docker, Kubernetes,
AWS (EC2, S3, RDS), and Apache Tomcat. Below is a topic-by-topic breakdown of how to
deploy a Spring Boot application.

🔹 Topics Covered
✅ Building a Spring Boot JAR/WAR
✅ Deploying to Docker & Kubernetes
✅ Deploying on AWS (EC2, S3, RDS)
✅ Running Spring Boot with Apache Tomcat

1️⃣ Building a Spring Boot JAR/WAR


Before deployment, we need to package the Spring Boot application into a JAR (Java
Archive) or WAR (Web Application Archive).

📌 Steps to Build a JAR File


1. Open pom.xml and ensure the packaging is set to JAR:

xml

<packaging>jar</packaging>

2. Run the following Maven command to build the JAR:

sh

mvn clean package

1/6
3. Find the JAR file in the target/ folder:

bash

target/myapp-0.0.1-SNAPSHOT.jar

4. Run the JAR locally for testing:

sh

java -jar target/myapp-0.0.1-SNAPSHOT.jar

2️⃣ Deploying Spring Boot to Docker & Kubernetes


📌 Create a Dockerfile
1. Inside the Spring Boot project directory, create a Dockerfile :

dockerfile

FROM openjdk:17
COPY target/myapp-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

2. Build the Docker image:

sh

docker build -t my-spring-boot-app .

3. Run the container:

sh

docker run -p 8080:8080 my-spring-boot-app

✅ Your Spring Boot app is now running inside a Docker container!

2/6
📌 Deploying to Kubernetes
1. Create a Kubernetes deployment YAML file ( deployment.yaml ):

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-spring-boot-app
spec:
replicas: 2
selector:
matchLabels:
app: my-spring-boot-app
template:
metadata:
labels:
app: my-spring-boot-app
spec:
containers:
- name: my-spring-boot-app
image: my-docker-hub-username/my-spring-boot-app:latest
ports:
- containerPort: 8080

2. Apply the deployment in Kubernetes:

sh

kubectl apply -f deployment.yaml

✅ Now, your Spring Boot app is running in a Kubernetes cluster!

3️⃣ Deploying Spring Boot on AWS (EC2, S3, RDS)


📌 Deploying on AWS EC2
1. Launch an EC2 instance (Ubuntu or Amazon Linux).

3/6
2. Connect to EC2 via SSH:

sh

ssh -i my-key.pem ec2-user@your-ec2-ip

3. Install Java on EC2:

sh

sudo yum install java-17-openjdk -y

4. Upload the JAR file to EC2 using SCP:

sh

scp -i my-key.pem target/myapp-0.0.1-SNAPSHOT.jar ec2-user@your-ec2-


ip:/home/ec2-user/

5. Run the Spring Boot app on EC2:

sh

java -jar myapp-0.0.1-SNAPSHOT.jar

✅ Your application is now running on AWS EC2!

📌 Connecting Spring Boot to AWS RDS


1. Create an RDS instance (MySQL or PostgreSQL).

2. Update application.properties in your Spring Boot project:

properties

spring.datasource.url=jdbc:mysql://your-rds-endpoint:3306/dbname
spring.datasource.username=your-db-username
spring.datasource.password=your-db-password

3. Rebuild and deploy the JAR to EC2.

4/6
✅ Now your Spring Boot app is connected to AWS RDS!

4️⃣ Running Spring Boot with Apache Tomcat


📌 Steps to Deploy Spring Boot as a WAR File
1. Modify pom.xml for WAR packaging:

xml

<packaging>war</packaging>

2. Add dependency for Spring Boot Web:

xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

3. Extend SpringBootServletInitializer in your main class:

java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class MyApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}

4. Build the WAR file:

sh

5/6
mvn clean package

5. Copy the WAR file to Tomcat’s webapps/ directory:

sh

cp target/myapp-0.0.1-SNAPSHOT.war /opt/tomcat/webapps/

6. Restart Tomcat and access the application:

bash

http://your-server-ip:8080/myapp

✅ Your Spring Boot app is now running on Apache Tomcat!

🔹 Summary
Deployment Method Steps

Docker Build a Docker image and run the container

Kubernetes Deploy the Docker image to Kubernetes

AWS EC2 Upload JAR and run it on an EC2 instance

AWS RDS Connect Spring Boot to a managed database

Apache Tomcat Deploy Spring Boot as a WAR file

🚀 Next Steps
Would you like a detailed guide on CI/CD (GitHub Actions, Jenkins, AWS CodeDeploy)? 🚀

6/6
Core Java Best Practices

1️⃣ Difference between


@RestController and @Controller
@Controller

Used for MVC (Model-View-Controller) applications.

Returns views (like JSP, Thymeleaf) instead of JSON data.

Works with ViewResolvers to render HTML pages.

Example:
java

@Controller
public class MyController {
@GetMapping("/home")
public String home() {
return "index"; // Returns "index.html"
}
}

@RestController

Used for REST APIs.

Returns JSON or XML instead of views.

Combines @Controller + @ResponseBody automatically.

Example:
java

@RestController
public class MyRestController {
@GetMapping("/hello")
public String sayHello() {
return "Hello, World!";
}
}

1/8
✅ Use @RestController for REST APIs and @Controller for web pages.

2️⃣ Difference between @Component,


@Service, and @Repository
Annotation Purpose Used for

@Component Generic Spring Bean Any Spring-managed component

@Service Business Logic Service layer (e.g., UserService)

@Repository Database Operations DAO layer (e.g., UserRepository)

Example of @Component (Generic Bean)

java

@Component
public class MyComponent {
public String getMessage() {
return "Hello from Component!";
}
}

Example of @Service (Business Logic)

java

@Service
public class UserService {
public String getUser() {
return "User fetched!";
}
}

Example of @Repository (Database Operations)

java

2/8
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

✅ @Component is a generic bean, while @Service and @Repository are specialized


versions used in Service and DAO layers.

3️⃣ How do you handle exceptions in


Spring Boot?
Method 1: Using @ExceptionHandler (Local Exception Handling)
Handles exceptions inside a specific controller.

Example:
java

@RestController
public class UserController {
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
if (id < 1) {
throw new IllegalArgumentException("Invalid ID");
}
return new User(id, "John Doe");
}

@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleException(IllegalArgumentException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}

Method 2: Using @ControllerAdvice (Global Exception Handling)


Handles exceptions globally across the application.

3/8
Example:
java

@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGlobalException(Exception ex) {
return new ResponseEntity<>("Error: " + ex.getMessage(),
HttpStatus.INTERNAL_SERVER_ERROR);
}
}

✅ Use @ExceptionHandler for controller-specific exceptions and @ControllerAdvice for


global exceptions.

4️⃣
JWT?
How do you secure a REST API using

Steps to Secure a REST API with JWT


1. User sends login credentials.

2. Server verifies credentials and generates a JWT token.

3. User includes the JWT token in the request header for every API call.

4. Server validates the token and processes the request.

Step 1: Add Dependencies

xml

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.11.5</version>
</dependency>

4/8
Step 2: Create JWT Utility Class

java

import io.jsonwebtoken.*;
import java.util.Date;

@Component
public class JwtUtil {
private String secretKey = "mySecret";

public String generateToken(String username) {


return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 *
60)) // 1 hour
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}

public String extractUsername(String token) {


return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}

Step 3: Implement JWT Filter

java

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.springframework.web.filter.OncePerRequestFilter;

@Component

5/8
public class JwtFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");

if (token != null && token.startsWith("Bearer ")) {


String username = jwtUtil.extractUsername(token.substring(7));
System.out.println("Authenticated user: " + username);
}
chain.doFilter(request, response);
}
}

✅ Now your REST API is secured with JWT authentication!

5️⃣ How do you improve API


performance in Spring Boot?
📌 Best Practices for API Performance Optimization
Strategy Description

Enable Caching Use @EnableCaching and Redis for repeated API calls

Use Asynchronous Processing Use @Async for non-blocking calls

Optimize Database Queries Use @Query and pagination to reduce load

Use Connection Pooling Configure HikariCP for better DB connection management

Enable GZIP Compression Enable compression in application.properties

Use a Load Balancer Distribute API traffic with Nginx or AWS ELB

Example: Enable Caching in Spring Boot


java

6/8
@EnableCaching
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}

Example: Asynchronous API Call


java

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class MyService {
@Async
public void processHeavyTask() {
System.out.println("Processing in background...");
}
}

✅ These strategies help improve API speed, scalability, and performance.

🔹 Summary of Answers
Question Key Answer

1. Difference between @RestController @RestController returns JSON, while @Controller


and @Controller ? returns views.

2. Difference between @Component , @Component is generic, @Service is for business logic,


@Service , and @Repository ? @Repository is for database operations.

3. How to handle exceptions? Use @ExceptionHandler for local handling and


@ControllerAdvice for global handling.

7/8
Question Key Answer

4. How to secure a REST API using JWT? Generate JWT token, validate it in a filter, and secure API
requests.

5. How to improve API performance? Use caching, async processing, database optimization,
and load balancing.

🚀 Would you like a hands-on project implementing these concepts? Let me know! 😊

8/8

You might also like