0% found this document useful (0 votes)
7 views25 pages

Unit-IV-Backend Engineering With Java Spring Boot

This document provides an overview of Backend Engineering using Java Spring Boot, covering key concepts such as the Spring Boot ecosystem, Dependency Injection, Spring Data JPA, RESTful controllers, API versioning, and Spring Security. It includes hands-on examples for creating a Spring Boot project, implementing CRUD operations, and securing APIs with JWT. The document serves as a comprehensive guide for developers looking to build secure and efficient backend applications with Spring Boot.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views25 pages

Unit-IV-Backend Engineering With Java Spring Boot

This document provides an overview of Backend Engineering using Java Spring Boot, covering key concepts such as the Spring Boot ecosystem, Dependency Injection, Spring Data JPA, RESTful controllers, API versioning, and Spring Security. It includes hands-on examples for creating a Spring Boot project, implementing CRUD operations, and securing APIs with JWT. The document serves as a comprehensive guide for developers looking to build secure and efficient backend applications with Spring Boot.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Unit-IV: Backend Engineering with

Java Spring Boot


1. Spring Boot Ecosystem and IoC / Dependency Injection
2. Spring Data JPA: Repositories and Entity Mapping
3. RESTful Controllers: Handling HTTP Methods
4. API Versioning Strategies
5. Spring Security: Authentication and Authorization
6. Securing APIs with JSON Web Token (JWT)
7. Role-Based Access Control (RBAC) using JWT Claims
8. Input Validation and Global Exception Handling
9. API Documentation with Swagger / OpenAPI
Spring Boot Ecosystem and IoC / Dependency Injection
What is Spring Boot?
Spring Boot is an open-source Java-based framework built on top of the Spring Framework. It
simplifies the development of production-ready applications by providing auto-configuration,
embedded servers, and starter dependencies. It eliminates boilerplate configuration so
developers can focus on business logic.

Spring Boot Ecosystem Components


Component Purpose
Spring Core Foundation: IoC container and Dependency Injection
Spring MVC Build web applications and REST APIs
Spring Data JPA Simplify database operations using ORM
Spring Security Authentication, Authorization, and API security
Spring Boot Auto-configuration and embedded server wrapper
Spring Cloud Microservices, service discovery, config servers

Key Features of Spring Boot


• Auto-Configuration: Automatically configures beans based on classpath dependencies.
• Starter Dependencies: Pre-packaged dependency sets (e.g., spring-boot-starter-web).
• Embedded Server: Ships with Tomcat/Jetty; no external server deployment needed.
• Spring Initializr: Web tool to bootstrap a Spring Boot project quickly ([Link]).
• Actuator: Built-in production monitoring endpoints such as /health and /metrics.

Inversion of Control (IoC)


IoC is a design principle where the control of object creation and lifecycle is handed over from
the application code to the Spring IoC container. In a traditional approach, a class creates its
own dependencies. With IoC, the container creates and manages them on behalf of the class.
Traditional: UserService creates a DatabaseHelper object inside its own constructor.
IoC: Spring container creates DatabaseHelper and supplies it to UserService automatically.

Dependency Injection (DI)


Dependency Injection is the mechanism that implements IoC. Instead of a class instantiating its
dependencies, they are injected by the Spring container.
DI Type Description
Constructor Injection Dependencies passed via constructor – recommended best
practice
Setter Injection Dependencies supplied via setter methods after object
creation
Field Injection Dependencies injected directly on fields using @Autowired –
not recommended for testing

Important Spring Annotations


Annotation Meaning
@SpringBootApplication Entry point; combines @Configuration,
@EnableAutoConfiguration, @ComponentScan
@Component Marks a class as a Spring-managed bean
@Service Specialization of @Component for the service layer
@Repository Specialization of @Component for the DAO / data access
layer
@RestController Marks a class as a REST web controller; combines
@Controller and @ResponseBody
@Autowired Injects a matching bean automatically
@Bean Declares a method that returns a Spring-managed bean
@Configuration Marks a class as a source of bean definitions

Hands-on:
Step 1: Create a Spring Boot Project
Go to [Link] and configure: Project = Maven, Language = Java, Dependencies =
Spring Web, Spring Data JPA, H2 Database. Download, extract, and open in IntelliJ IDEA or VS
Code.

Step 2: Main Application Class


@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
This single annotation bootstraps the entire Spring context automatically.

Step 3: Constructor Injection Example


@Service
public class UserService {
private final UserRepository userRepository;

// Constructor Injection (recommended)


public UserService(UserRepository userRepository) {
[Link] = userRepository;
}
}

Step 4: React Integration Concept


Spring Boot runs as the backend API server on port 8080. React runs as a separate frontend on
port 3000. React calls the Spring Boot API using fetch() or Axios. Enable CORS on the Spring
Boot side to allow cross-origin requests from React.
@CrossOrigin(origins = "[Link]
@RestController
public class UserController { ... }

// React fetching Spring Boot API


fetch('[Link]
.then(res => [Link]())
.then(data => setUsers(data));
Spring Data JPA – Repositories and Entity Mapping
What is JPA?
Java Persistence API (JPA) is a specification for managing relational data in Java. It uses
Object-Relational Mapping (ORM) to map Java objects called entities to database tables. This
eliminates the need for writing raw SQL in most cases.

What is Spring Data JPA?


Spring Data JPA is a layer built on top of JPA (using Hibernate as the default implementation). It
reduces boilerplate code by providing ready-made repository interfaces with built-in CRUD
operations. Developers only define an interface; Spring generates the implementation at
runtime.

Entity Mapping Annotations


Annotation Purpose
@Entity Marks the class as a JPA entity mapped to a database table
@Table(name=...) Specifies the database table name (optional if class name
matches)
@Id Marks the primary key field
@GeneratedValue Automatically generates the primary key value
@Column(name=...) Maps a field to a specific column name with constraints
@OneToMany Defines a one-to-many relationship between two entities
@ManyToOne Defines a many-to-one relationship
@JoinColumn Specifies the foreign key column used in a relationship

Repository Interface Hierarchy


Interface Provides
Repository<T, ID> Marker interface with no methods
CrudRepository<T, ID> save(), findById(), findAll(), delete()
PagingAndSortingRepository<T, Pagination and sorting support
ID>
JpaRepository<T, ID> All the above plus flush() and batch operations
JpaRepository is the most commonly used. Extend it in your repository interface.

Derived Query Methods


Spring Data JPA generates SQL from method names automatically. No implementation code is
needed.
findByEmail(String email) --> SELECT * FROM users WHERE email = ?
findByAgeGreaterThan(int age) --> SELECT * FROM users WHERE age > ?
findByNameAndCity(String n, String c) --> AND condition

Hands-on:
Step 1: Add Dependency ([Link])
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

Step 2: Define an Entity


@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = [Link])
private Long id;

@Column(nullable = false)
private String name;

@Column(unique = true, nullable = false)


private String email;

// Getters and Setters


}

Step 3: Create Repository Interface


public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
List<User> findByName(String name);
}
Spring auto-generates the implementation. No SQL queries needed.

Step 4: [Link]
[Link]=jdbc:h2:mem:testdb
[Link]-class-name=[Link]
[Link]-auto=update
[Link]-sql=true
[Link]=true
Step 5: Service Layer
@Service
public class UserService {
private final UserRepository repo;
public UserService(UserRepository repo) { [Link] = repo; }

public List<User> getAllUsers() { return [Link](); }


public User saveUser(User user) { return [Link](user); }
public Optional<User> findByEmail(String email) {
return [Link](email);
}
}

React Integration
// Fetch users from Spring Boot API
useEffect(() => {
fetch('[Link]
.then(r => [Link]())
.then(data => setUsers(data));
}, []);
RESTful Controllers – Handling HTTP Methods

What is REST?
REST (Representational State Transfer) is an architectural style for designing networked APIs.
A RESTful API uses standard HTTP methods to perform operations on resources identified by
URLs. It is stateless, meaning each request contains all the information needed to process it.

HTTP Methods and Their Meaning


HTTP Method Operation Example URL
GET Read or retrieve data /api/users or /api/users/{id}
POST Create a new resource /api/users
PUT Replace existing resource (full /api/users/{id}
update)
PATCH Partially update a resource /api/users/{id}
DELETE Remove a resource /api/users/{id}

Key REST Controller Annotations


Annotation Usage
@RestController Combines @Controller and @ResponseBody; returns JSON
by default
@RequestMapping Maps a base URL to a class or method
@GetMapping Handles HTTP GET requests
@PostMapping Handles HTTP POST requests
@PutMapping Handles HTTP PUT requests
@DeleteMapping Handles HTTP DELETE requests
@PathVariable Extracts a value from the URL path e.g., /users/{id}
@RequestBody Reads and deserializes JSON from the request body
@RequestParam Reads query parameters from the URL e.g., ?name=Alice
ResponseEntity<T> Allows control over HTTP status code and response body

HTTP Response Status Codes


Code Meaning
200 OK Request was successful
201 Created Resource created successfully
204 No Content Successful, no body to return
400 Bad Request Invalid input from client
401 Unauthorized Authentication required
403 Forbidden Authenticated but not authorized
404 Not Found Resource does not exist
500 Internal Server Error Unexpected server-side error

Hands-on: Full CRUD REST Controller


@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "[Link]
public class UserController {

private final UserService userService;


public UserController(UserService userService) {
[Link] = userService;
}

@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
return [Link]([Link]());
}

@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
return [Link](id)
.map(ResponseEntity::ok)
.orElse([Link]().build());
}

@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
return [Link](201).body([Link](user));
}

@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@RequestBody User user) {
[Link](id);
return [Link]([Link](user));
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
[Link](id);
return [Link]().build();
}
}

React: POST Request to Create a User


const createUser = async (userData) => {
const response = await fetch('[Link] {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link](userData)
});
return [Link]();
};
API Versioning Strategies
Why API Versioning?
As an API evolves, breaking changes may be introduced – for example, renaming fields or
changing response structure. Versioning allows old clients (such as a React frontend using v1)
to continue working without disruption while new clients adopt v2. Without versioning, any API
update risks breaking existing consumers.

Types of API Versioning


Strategy Description and Example
URI Versioning Version embedded in URL path: /api/v1/users, /api/v2/users
Request Parameter Version as a query parameter: /api/users?version=1
Header Versioning Custom request header: X-API-Version: 1
Content Negotiation Version in Accept header: Accept: application/[Link].v1+json

Comparison of Versioning Strategies


Strategy Advantage Disadvantage
URI Versioning Easy to test in browser; clear URL pollution; not purely
and visible RESTful
Request Param Simple to implement Easy to miss; less visible to
developers
Header Versioning Clean URLs; best REST practice Cannot test directly in a browser
URL
Content Negotiation RESTfully correct approach Complex to implement and
consume

Hands-on
URI Versioning in Spring Boot
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 {
@GetMapping
public List<String> getUsers() {
return [Link]("Alice", "Bob");
}
}

@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 {
@GetMapping
public List<UserDTO> getUsers() {
return [Link]();
}
}

Header Versioning Example


@GetMapping(value = "/users", headers = "X-API-Version=1")
public ResponseEntity<?> getUsersV1() { ... }

@GetMapping(value = "/users", headers = "X-API-Version=2")


public ResponseEntity<?> getUsersV2() { ... }

React: Calling a Versioned API


const API_VERSION = 'v1';
fetch(`[Link]
.then(r => [Link]())
.then(data => setUsers(data));
Spring Security – Authentication and Authorization
What is Spring Security?
Spring Security is a powerful and highly customizable framework that provides authentication
and authorization to Java applications. It protects APIs from unauthorized access and supports
various security mechanisms including HTTP Basic, Form Login, OAuth2, and JWT.

Authentication vs Authorization
Concept Definition
Authentication Verifying WHO the user is – e.g., checking username and
password
Authorization Verifying WHAT the user is allowed to do – e.g., checking
roles
Authentication always happens before Authorization.

Spring Security Core Components


Component Role
SecurityFilterChain A chain of filters that every HTTP request passes through
AuthenticationManager Coordinates the authentication process
UserDetailsService Loads user-specific data from the database or any data source
UserDetails Holds user information: username, password, roles
PasswordEncoder Encodes and verifies passwords; BCryptPasswordEncoder is
recommended
GrantedAuthority Represents a role or permission granted to a user

Security Filter Chain


Every HTTP request passes through a chain of filters before reaching the controller. Common
filters include UsernamePasswordAuthenticationFilter for form login, BasicAuthenticationFilter
for HTTP Basic auth, and custom JwtAuthenticationFilter for JWT-based authentication.

Hands-on
Step 1: Add Dependency
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Step 2: Custom UserDetailsService


@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String email) {
User user = [Link](email)
.orElseThrow(() ->
new UsernameNotFoundException("User not found"));
return [Link]
.withUsername([Link]())
.password([Link]())
.roles([Link]())
.build();
}
}

Step 3: Security Configuration


@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
[Link]().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
);
return [Link]();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Securing APIs with JSON Web Token (JWT)
What is JWT?
JSON Web Token (JWT) is a compact, self-contained token used to securely transmit
information between parties as a JSON object. It is digitally signed so the receiver can verify its
authenticity. JWTs are used in stateless authentication – the server does not need to store
session data because all information is inside the token.

JWT Structure
A JWT has three parts separated by dots: [Link]
Part Contains
Header Algorithm (e.g., HS256) and token type (JWT)
Payload Claims: user data such as sub (subject), roles, exp (expiry
time)
Signature HMAC of header + payload using a secret key; ensures the
token has not been tampered with

JWT Authentication Flow


• Step 1: User sends credentials (email and password) to /api/auth/login.
• Step 2: Server verifies credentials against the database.
• Step 3: Server generates a JWT token signed with a secret key and returns it.
• Step 4: React stores the token in localStorage.
• Step 5: Every subsequent API request includes the token in the Authorization header.
• Step 6: Server validates the token on each request. Valid token proceeds; invalid returns
401.

Advantages of JWT
• Stateless: No server-side session storage needed – scales easily.
• Self-contained: All user information is embedded inside the token.
• Cross-domain: Works seamlessly between React (port 3000) and Spring Boot (port
8080).
• Secure: Signature verification prevents tampering.

Hands-on
Step 1: Add JWT Dependency
<dependency>
<groupId>[Link]</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>

Step 2: JWT Utility Class


@Component
public class JwtUtil {
private final String SECRET = "mySecretKey12345678901234567890";

public String generateToken(String username) {


return [Link]()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(
new Date([Link]() + 86400000)) // 1 day
.signWith([Link]([Link]()))
.compact();
}

public String extractUsername(String token) {


return [Link]()
.setSigningKey([Link]([Link]()))
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}

Step 3: Authentication Controller


@RestController
@RequestMapping("/api/auth")
public class AuthController {
private final AuthenticationManager authManager;
private final JwtUtil jwtUtil;

@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
[Link](new UsernamePasswordAuthenticationToken(
[Link](), [Link]()));
String token = [Link]([Link]());
return [Link]([Link]("token", token));
}
}
React: Login and Store JWT
const login = async (email, password) => {
const res = await fetch('[Link] {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link]({ email, password })
});
const data = await [Link]();
[Link]('token', [Link]);
};

// Attach token to protected requests


const getUsers = async () => {
const token = [Link]('token');
const res = await fetch('[Link] {
headers: { 'Authorization': `Bearer ${token}` }
});
return [Link]();
};
Role-Based Access Control (RBAC) using JWT Claims
What is RBAC?
Role-Based Access Control (RBAC) restricts access to system resources based on the roles
assigned to users. Instead of assigning permissions to individual users, roles such as ADMIN,
USER, and MANAGER are created with specific permissions, and users are assigned those
roles.

Embedding Roles in JWT Claims


When generating a JWT token, the user's role is embedded as a claim inside the payload. The
Spring Security filter extracts this role from the token and stores it in the SecurityContext so
authorization decisions can be made.
// JWT Payload (decoded) Example
{
"sub": "alice@[Link]",
"role": "ADMIN",
"exp": 1700000000
}

Access Control Annotations


Annotation / Expression Usage
@PreAuthorize("hasRole('ADMIN')") Only ADMIN users can access this method
@PreAuthorize("hasAnyRole('ADMIN','USER')") Either ADMIN or USER role can access
@Secured("ROLE_ADMIN") Method-level security using older
@Secured annotation
.hasRole("ADMIN") URL-pattern-based access control in
SecurityFilterChain

Hands-on
Step 1: Include Role in JWT Token
public String generateToken(String username, String role) {
return [Link]()
.setSubject(username)
.claim("role", role)
.setExpiration(new Date([Link]() + 86400000))
.signWith([Link]([Link]()))
.compact();
}

Step 2: Extract Role in JWT Filter and Set in SecurityContext


Claims claims = [Link]()
.setSigningKey(key).build()
.parseClaimsJws(token).getBody();

String role = [Link]("role", [Link]);


List<GrantedAuthority> authorities = [Link](
new SimpleGrantedAuthority("ROLE_" + role));

UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(
username, null, authorities);
[Link]().setAuthentication(auth);

Step 3: Protect Endpoints by Role in Security Config


[Link]().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/users/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
);

Step 4: Method-Level Security with @PreAuthorize


@EnableMethodSecurity // Add to the main config class

@GetMapping("/admin/dashboard")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> adminDashboard() {
return [Link]("Welcome Admin");
}

React: Role-Based Conditional Rendering


import { jwtDecode } from 'jwt-decode';

const token = [Link]('token');


const decoded = jwtDecode(token);
const role = [Link];

{role === 'ADMIN' && <AdminPanel />}


{role === 'USER' && <UserDashboard />}
Input Validation and Global Exception Handling
Why Input Validation?
Validating input at the server side ensures data integrity, prevents invalid data from entering the
database, and protects against malicious input. Spring Boot integrates the Bean Validation API
(Jakarta Validation) through the spring-boot-starter-validation dependency.

Common Validation Annotations


Annotation Validates That...
@NotNull Field value is not null
@NotBlank String is not null, not empty, and not whitespace only
@NotEmpty String or collection is not null and not empty
@Size(min, max) String or collection size is within the given range
@Min(value) Number is greater than or equal to the given value
@Max(value) Number is less than or equal to the given value
@Email String is a valid email address format
@Pattern(regexp) String matches the specified regular expression
@Positive Number is strictly greater than zero

Global Exception Handling


Instead of handling exceptions in every controller method, Spring Boot provides
@RestControllerAdvice to centralize exception handling across all controllers. This produces
uniform, structured error responses for every API consumer.

Common Exceptions
Exception Scenario
MethodArgumentNotValidException Triggered when @Valid fails on a @RequestBody
ConstraintViolationException Triggered when @Validated fails on @PathVariable or
@RequestParam
ResourceNotFoundException Thrown when a requested record is not found in the
(custom) database
Exception (global fallback) Catches any unhandled exception as a last resort

Hands-on
Step 1: Add Dependency
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Step 2: Add Validation Constraints to DTO


public class UserDTO {
@NotBlank(message = "Name is required")
@Size(min = 2, max = 50, message = "Name must be 2-50 characters")
private String name;

@NotBlank(message = "Email is required")


@Email(message = "Invalid email format")
private String email;

@NotNull(message = "Age is required")


@Min(value = 18, message = "Age must be at least 18")
private Integer age;
}

Step 3: Enable Validation in Controller


@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO dto) {
// @Valid triggers validation automatically
// If any constraint fails, MethodArgumentNotValidException is thrown
User saved = [Link](dto);
return [Link](201).body(saved);
}

Step 4: Custom Exception Class


public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}

Step 5: Global Exception Handler


@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler([Link])
public ResponseEntity<Map<String, String>> handleValidation(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
[Link]().getFieldErrors().forEach(err ->
[Link]([Link](), [Link]()));
return [Link]().body(errors);
}

@ExceptionHandler([Link])
public ResponseEntity<String> handleNotFound(
ResourceNotFoundException ex) {
return [Link](404).body([Link]());
}

@ExceptionHandler([Link])
public ResponseEntity<String> handleGeneral(Exception ex) {
return [Link](500).body("Internal Server Error");
}
}

React: Displaying Validation Errors


const createUser = async (data) => {
const res = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link](data)
});
if (![Link]) {
const errors = await [Link]();
setErrors(errors); // e.g. { name: 'Name is required', email: '...' }
}
};
API Documentation with Swagger / OpenAPI
What is Swagger / OpenAPI?
OpenAPI (formerly Swagger) is a specification for describing RESTful APIs in a machine-
readable JSON or YAML format. Swagger UI reads this specification and generates interactive
API documentation automatically. It allows developers and testers to explore and invoke API
endpoints directly from a browser without writing any client code.

Why Use Swagger?


• Automatically generates documentation from Spring Boot code and annotations.
• Provides an interactive browser-based UI to test endpoints without Postman.
• Helps React developers understand what endpoints exist and what they return.
• Acts as a living contract between backend and frontend development teams.

springdoc-openapi Library
The springdoc-openapi library integrates OpenAPI 3 with Spring Boot. Once added as a
dependency, it auto-generates the API spec at /v3/api-docs and serves Swagger UI at
/[Link] with zero additional configuration.

Key Swagger Annotations


Annotation Purpose
@Tag(name, description) Groups related endpoints under a named label in Swagger
UI
@Operation(summary, Documents a single API endpoint method
description)
@ApiResponse(responseCode, Documents a specific HTTP response for an endpoint
description)
@Parameter(description) Documents an individual method parameter
@Schema(description) Documents a model field in a DTO or Entity class
@SecurityRequirement(name) Marks an endpoint as requiring authentication in Swagger
UI

Hands-on

Step 1: Add Dependency


<dependency>
<groupId>[Link]</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>

Step 2: Access Swagger UI


After adding the dependency and starting the application, open:
[Link]
The OpenAPI JSON specification is available at:
[Link]

Step 3: Configure OpenAPI Metadata


@Configuration
public class OpenAPIConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("User Management API")
.version("1.0")
.description("Spring Boot REST API with JWT Security"));
}
}

Step 4: Annotate Controller for Documentation


@Tag(name = "User API", description = "Operations for managing users")
@RestController
@RequestMapping("/api/users")
public class UserController {

@Operation(summary = "Get all users",


description = "Returns a list of all registered users")
@ApiResponse(responseCode = "200", description = "Users retrieved")
@GetMapping
public ResponseEntity<List<User>> getAllUsers() { ... }

@Operation(summary = "Create a new user")


@ApiResponse(responseCode = "201", description = "User created")
@ApiResponse(responseCode = "400", description = "Validation error")
@PostMapping
public ResponseEntity<User> createUser(@RequestBody UserDTO dto) { ... }
}

Step 5: Add JWT Authorization to Swagger UI


@Bean
public OpenAPI openAPIWithJWT() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList("Bearer"))
.components(new Components().addSecuritySchemes("Bearer",
new SecurityScheme()
.type([Link])
.scheme("bearer")
.bearerFormat("JWT")));
}
After this configuration, Swagger UI will display an Authorize button. Paste your JWT token
there to test secured endpoints directly from the browser without Postman.

Step 6: Permit Swagger URLs in Security Config


.requestMatchers("/swagger-ui/**",
"/v3/api-docs/**",
"/[Link]").permitAll()

You might also like