Features
- Manage Users
- Create User
- Update User
- Delete User
- View All Users
- Manage Students
- Create Student
- Update Student
- Delete Student
- View All Students
- Manage Books
- Create Book
- Update Book
- Delete Book
- View All Books
- Issue book
- Return book
- View Issued books
- View Defaulters List
Technologies
- Spring Boot
- Spring Data JPA (Hibernate)
- Spring Security
- MySql Database
Advertisement
Watch on YouTube
Database Configurations
Using below commands create the tables in MySql
content_copy
copy
CREATE TABLE users (
user_id int auto_increment not null primary key,
user_name VARCHAR(50) NOT NULL,
email varchar(20) not null,
contact varchar(20) not null,
password VARCHAR(50) NOT NULL
);
create table roles(
role_id int auto_increment not null primary key,
role_name varchar(20) NOT NULL
);
create table user_roles(
user_roles_id int auto_increment not null primary key,
user_id int not null,
role_id int not null,
CONSTRAINT fk_users FOREIGN KEY (user_id) REFERENCES users(user_id),
CONSTRAINT fk_roles FOREIGN KEY (role_id) REFERENCES roles(role_id)
);
create table students(
student_id int auto_increment not null primary key,
student_name varchar(20) not null,
student_department varchar(20) not null,
student_contact_no varchar(20) not null
);
create table books(
book_id int auto_increment not null primary key,
book_title varchar(20) not null,
book_author varchar(20) not null,
initial_qty int not null,
issued_qty int not null
);
create table issued_books(
issued_book_id int auto_increment not null primary key,
book_id int not null,
student_id int not null,
issued_date date not null,
return_date date,
duration int not null,
CONSTRAINT fk_books FOREIGN KEY (book_id) REFERENCES books(book_id),
CONSTRAINT fk_students FOREIGN KEY (student_id) REFERENCES students(student_id)
);
Create a new Admin user and 2 default roles i.e 'Admin' and 'Librarian'
content_copy
copy
insert into users( user_name, email, contact, password) values( "admin", "admin@exp.com", "123456789", "adminPassword");
insert into roles(role_name) values("ADMIN");
insert into roles(role_name) values( "LIBRARIAN");
insert into user_roles(user_id, role_id) values( 1, 1);
Next, create a Java Maven project in IntelliJ and create a directory structure as shown in below figure.
Pom File
Include the following dependencies in pom file
content_copy
copy
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>LibraryMgmtSys</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.properties File
Define the datasource and hibernate configurations. Replace the datasource configurations mentioned below with your datasource configurations
content_copy
copy
#Datasource configuration
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root
#Hibernate Configuration
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
Entities
Create entity classes for all the tables that we created in MySql
Books
content_copy
copy
package org.example.entities;
import jakarta.persistence.*;
import java.util.List;
@Entity
@Table(name = "books")
public class Books {
@Id
@Column(name = "book_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long bookId;
@Column(name = "book_title")
private String title;
@Column(name = "book_author")
private String authorName;
@Column(name = "initial_qty")
private Long initialQty;
@Column(name = "issued_qty")
private Long issuedQty;
@OneToMany(mappedBy = "book")
private List issuedBooks;
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public Long getInitialQty() {
return initialQty;
}
public void setInitialQty(Long initialQty) {
this.initialQty = initialQty;
}
public Long getIssuedQty() {
return issuedQty;
}
public void setIssuedQty(Long issuedQty) {
this.issuedQty = issuedQty;
}
public List getIssuedBooks() {
return issuedBooks;
}
public void setIssuedBooks(List issuedBooks) {
this.issuedBooks = issuedBooks;
}
}
IssuedBooks
content_copy
copy
package org.example.entities;
import jakarta.persistence.*;
import java.util.Date;
@Entity
@Table(name = "issued_books")
public class IssuedBooks {
@Id
@Column(name = "issued_book_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long issuedBookId;
@ManyToOne()
@JoinColumn(name = "book_id")
private Books book;
@ManyToOne()
@JoinColumn(name = "student_id")
private Students student;
@Column(name = "duration")
private Long duration;
@Column(name = "issued_date")
private Date issuedDate;
@Column(name = "return_date")
private Date returnDate;
public Long getIssuedBookId() {
return issuedBookId;
}
public void setIssuedBookId(Long issuedBookId) {
this.issuedBookId = issuedBookId;
}
public Books getBook() {
return book;
}
public void setBook(Books book) {
this.book = book;
}
public Students getStudent() {
return student;
}
public void setStudent(Students student) {
this.student = student;
}
public Long getDuration() {
return duration;
}
public void setDuration(Long duration) {
this.duration = duration;
}
public Date getIssuedDate() {
return issuedDate;
}
public void setIssuedDate(Date issuedDate) {
this.issuedDate = issuedDate;
}
public Date getReturnDate() {
return returnDate;
}
public void setReturnDate(Date returnDate) {
this.returnDate = returnDate;
}
}
Roles
content_copy
copy
package org.example.entities;
import jakarta.persistence.*;
import java.util.List;
@Entity
@Table(name = "roles")
public class Roles {
@Id
@Column(name = "role_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long roleId;
@Column(name = "role_name")
private String roleName;
@OneToMany(mappedBy = "roles")
private List userRoles;
public Long getRoleId() {
return roleId;
}
public void setRoleId(Long roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public List getUserRoles() {
return userRoles;
}
public void setUserRoles(List userRoles) {
this.userRoles = userRoles;
}
}
Students
content_copy
copy
package org.example.entities;
import jakarta.persistence.*;
import java.util.List;
@Entity
@Table(name = "students")
public class Students {
@Id
@Column(name = "student_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long studentId;
@Column(name = "student_name")
private String name;
@Column(name = "student_department")
private String department;
@Column(name = "student_contact_no")
private String contact;
@OneToMany(mappedBy = "student")
private List issuedBooks;
public Long getStudentId() {
return studentId;
}
public void setStudentId(Long studentId) {
this.studentId = studentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public List getIssuedBooks() {
return issuedBooks;
}
public void setIssuedBooks(List issuedBooks) {
this.issuedBooks = issuedBooks;
}
}
UserRoles
content_copy
copy
package org.example.entities;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
@Entity
@Table(name = "user_roles")
public class UserRoles {
@Id
@Column(name = "user_roles_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userRolesId;
@ManyToOne()
@JsonIgnore
@JoinColumn(name = "user_id")
private Users users;
@ManyToOne
@JsonIgnore
@JoinColumn(name = "role_id")
private Roles roles;
public Long getUserRolesId() {
return userRolesId;
}
public void setUserRolesId(Long userRolesId) {
this.userRolesId = userRolesId;
}
public Users getUsers() {
return users;
}
public void setUsers(Users users) {
this.users = users;
}
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
}
Users
content_copy
copy
package org.example.entities;
import jakarta.persistence.*;
import java.util.List;
@Entity
@Table(name = "users")
public class Users {
@Id
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
@Column(name = "user_name")
private String userName;
@Column(name = "password")
private String password;
@Column(name = "email")
private String email;
@Column(name = "contact")
private String contact;
@OneToMany(mappedBy = "users", fetch = FetchType.EAGER)
private List userRoles;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public List getUserRoles() {
return userRoles;
}
public void setUserRoles(List userRoles) {
this.userRoles = userRoles;
}
}
Dto's
Create data transfer objects for API's
PaginationDto
This dto carries the required pagination information for spring Jpa
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class PaginationDto implements Serializable {
private Integer totalPages;
private Integer currentPage;
private Integer pageSize;
public Integer getTotalPages() {
return totalPages;
}
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
public Integer getCurrentPage() {
return currentPage;
}
public void setCurrentPage(Integer currentPage) {
this.currentPage = currentPage;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
}
RequestDto
This Dto encapsulates the pagination dto and generic api related dto. It will be used as input Dto for all Api's
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class RequestDto implements Serializable {
private T data;
private PaginationDto pagination;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public PaginationDto getPagination() {
return pagination;
}
public void setPagination(PaginationDto pagination) {
this.pagination = pagination;
}
}
ResponseDto
This Dto encapsulates the pagination dto and generic appi related dto. It will be used as output dot for all API's
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class ResponseDto implements Serializable {
private T data;
private String status;
private String errorMessage;
private PaginationDto pagination;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public PaginationDto getPagination() {
return pagination;
}
public void setPagination(PaginationDto pagination) {
this.pagination = pagination;
}
}
LoginReqDto
This dto carries the login request payload
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class LoginReqDto implements Serializable {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
LoginResDto
This Dto carries the login response payload
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class LoginResDto implements Serializable {
private String authToken;
public String getAuthToken() {
return authToken;
}
public void setAuthToken(String authToken) {
this.authToken = authToken;
}
}
BookDto
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class BookDto implements Serializable {
private Long bookId;
private String title;
private String authorName;
private Long initialQty;
private Long issuedQty;
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public Long getInitialQty() {
return initialQty;
}
public void setInitialQty(Long initialQty) {
this.initialQty = initialQty;
}
public Long getIssuedQty() {
return issuedQty;
}
public void setIssuedQty(Long issuedQty) {
this.issuedQty = issuedQty;
}
}
IssuedBookDto
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class IssuedBookDto implements Serializable {
private String bookTitle;
private Long studentId;
private String studentName;
private String issuedDate;
private String returnDate;
private Long duration;
public String getBookTitle() {
return bookTitle;
}
public void setBookTitle(String bookTitle) {
this.bookTitle = bookTitle;
}
public Long getStudentId() {
return studentId;
}
public void setStudentId(Long studentId) {
this.studentId = studentId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getIssuedDate() {
return issuedDate;
}
public void setIssuedDate(String issuedDate) {
this.issuedDate = issuedDate;
}
public String getReturnDate() {
return returnDate;
}
public void setReturnDate(String returnDate) {
this.returnDate = returnDate;
}
public Long getDuration() {
return duration;
}
public void setDuration(Long duration) {
this.duration = duration;
}
}
IssueReturnDto
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class IssueReturnDto implements Serializable {
private Long bookId;
private Long studentId;
private Long duration;
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public Long getStudentId() {
return studentId;
}
public void setStudentId(Long studentId) {
this.studentId = studentId;
}
public Long getDuration() {
return duration;
}
public void setDuration(Long duration) {
this.duration = duration;
}
}
StudentDto
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class StudentDto implements Serializable {
private Long studentId;
private String name;
private String department;
private String contact;
public Long getStudentId() {
return studentId;
}
public void setStudentId(Long studentId) {
this.studentId = studentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
}
UserDto
content_copy
copy
package org.example.dtos;
import java.io.Serializable;
public class UserDto implements Serializable {
private Long userId;
private String userName;
private String email;
private String contact;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
}
Mapper
We will use mapstruct to create mappings between the entities and Dto's. In the interface, specify the target and source data fields if data fields are not same. This interface will create the mapping class during compile time.
Mapper
content_copy
copy
package org.example.mappers;
import org.example.dtos.IssuedBookDto;
import org.example.dtos.UserDto;
import org.example.dtos.BookDto;
import org.example.dtos.StudentDto;
import org.example.entities.Books;
import org.example.entities.IssuedBooks;
import org.example.entities.Students;
import org.example.entities.Users;
import org.mapstruct.IterableMapping;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import java.util.List;
@org.mapstruct.Mapper(componentModel = "spring")
public interface Mapper {
@Named("userEntityToUserDto")
UserDto userEntityToUserDto(Users user);
@IterableMapping(qualifiedByName = "userEntityToUserDto")
List<UserDto> userEntitiesToUserDtos(List<Users> users);
@Named("userDtoToUserEntity")
Users userDtoToUserEntity(UserDto userDto);
@Named("studentEntityToStudentDto")
StudentDto studentEntityToStudentDto(Students student);
@IterableMapping(qualifiedByName = "studentEntityToStudentDto")
List<StudentDto> studentEntitiesToStudentDtos(List<Students> students);
Students studentDtoToStudentEntity(StudentDto studentDto);
@Named("bookEntityToBookDto")
BookDto bookEntityToBookDto(Books book);
@IterableMapping(qualifiedByName = "bookEntityToBookDto")
List<BookDto> bookEntitiesToBookDtos(List<Books> books);
Books bookDtoToBookEntity(BookDto bookDto);
@Named("issuedBookEntityToIssuedBooksDto")
@Mappings(value = {
@Mapping(target = "bookTitle", source = "book.title"),
@Mapping(target = "studentId", source = "student.studentId"),
@Mapping(target = "studentName", source = "student.name"),
@Mapping(target = "issuedDate", source = "issuedDate"),
@Mapping(target = "returnDate", source = "returnDate"),
@Mapping(target = "duration", source = "duration"),
})
IssuedBookDto issuedBookEntityToIssuedBooksDto(IssuedBooks issuedBook);
@IterableMapping(qualifiedByName = "issuedBookEntityToIssuedBooksDto")
List<IssuedBookDto> issuedBookEntitiesToIssuedBookDto(List<IssuedBooks> issuedBook);
}
Controller Advice(Global Exception Handler)
We'll create a global exception handler class using @controllerAdvice annotation. All runtime exceptions will be directed to this class and it will return the error response.
content_copy
copy
package org.example.exception;
import org.example.dtos.ResponseDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ControllerAdvice
public class ExceptionHandler {
@org.springframework.web.bind.annotation.ExceptionHandler(RuntimeException.class)
public ResponseEntity<ResponseDto<Object>> handleExceptions(RuntimeException e){
ResponseDto responseDto = new ResponseDto();
responseDto.setStatus("error");
responseDto.setErrorMessage(e.getMessage());
ResponseEntity responseEntity = new ResponseEntity(responseDto, HttpStatus.INTERNAL_SERVER_ERROR);
return responseEntity;
}
}
Repositories
Create respository interfaces for all entities
BooksRepository
content_copy
copy
package org.example.repositories;
import org.example.entities.Books;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BooksRepository extends JpaRepository<Books, Long> {
Books findByBookId(Long bookId);
}
IssuedBooksRepository
content_copy
copy
package org.example.repositories;
import org.example.entities.IssuedBooks;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface IssuedBooksRepository extends JpaRepository<IssuedBooks, Long> {
IssuedBooks findByBook_BookIdAndStudent_StudentId(Long bookId, Long studentId);
@Query(nativeQuery = true, value = "select * from issued_books where return_date is null and date_add(issued_date, interval duration day) < curdate()")
Page<List<IssuedBooks>> findDefaulters(Pageable pageable);
}
RolesRepository
content_copy
copy
package org.example.repositories;
import org.example.entities.Roles;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface RolesRepository extends JpaRepository<Roles, Long> {
Roles findByRoleName(String roleName);
}
StudentsRepository
content_copy
copy
package org.example.repositories;
import org.example.entities.Students;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentsRepository extends JpaRepository<Students, Long> {
Students findByStudentId(Long studentId);
}
UserRolesRepository
content_copy
copy
package org.example.repositories;
import org.example.entities.UserRoles;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRolesRepository extends JpaRepository<UserRoles, Long> {
UserRoles findByUsers_userId(Long userId);
}
UsersRepository
content_copy
copy
package org.example.repositories;
import org.example.entities.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UsersRepository extends JpaRepository<Users, Long> {
Users findByUserName(String userName);
Users findByUserId(Long userId);
}
Spring Security
To add login functionality we need to utilize the spring security. First create the custom user class to incorporate the user details that we created in our database.
CustomUser
content_copy
copy
package org.example.security;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
public class CustomUser extends User {
private String email;
private String contact;
public CustomUser(String userName, String password, Collection<? extends GrantedAuthority> grantedAuthorities) {
super(userName, password, grantedAuthorities);
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
}
UserDetailsServiceImpl
We'll implement the userDetailsService as we need to authenticate the user from database. We'll override the loadUserByUserName method to fetch the user from DB.
content_copy
copy
*ackage org.example.security;
import org.example.entities.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.example.repositories.UsersRepository;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.stream.Collectors;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users user = usersRepository.findByUserName(username);
if(user != null) {
Collection<? extends GrantedAuthority> grantedAuthorities = user.getUserRoles().stream().map(userRoles -> {
return new SimpleGrantedAuthority(userRoles.getRoles().getRoleName());
}).collect(Collectors.toList());
return new CustomUser(username, user.getPassword(), grantedAuthorities);
}else
throw new UsernameNotFoundException("UserName not found");
}
}
JwtUtils
We will be using Json Web token to authenticate the user once the user has logged in. This class contains the utility functions for creating, validating and extracting the user form jwt.
content_copy
copy
package org.example.security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;
import java.security.Key;
import java.util.Date;
@Component
public class JwtUtils {
private String jwtSecret = "asfdjvbfljknvkrljnjrvekbdvnrjkglfjknvjhfssfvnfjnvnsjkfnvjlhfknvfnvfjvnfjvnjfvfjfvnfjvsflsljkfvnv";
private int jwtExpTime = 36000000;
public Key generateKey() {
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret));
}
public String generateJwt(String userName) {
return Jwts.builder()
.setSubject(userName)
.setIssuedAt(new Date())
.setExpiration(new Date(new Date().getTime() + jwtExpTime))
.signWith(generateKey(), SignatureAlgorithm.HS256)
.compact();
}
public Boolean validateJwtToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(generateKey()).build().parse(token);
return true;
} catch (MalformedJwtException e) {
throw new RuntimeException("Invalid Jwt Token");
} catch (ExpiredJwtException e) {
throw new RuntimeException("JWT Token is expired");
} catch (UnsupportedJwtException e) {
throw new RuntimeException("Jwt is unsupported");
} catch (IllegalArgumentException e) {
throw new RuntimeException("Jwt string is empty");
} catch (Exception e) {
throw new RuntimeException("Error in Jwt");
}
}
public String getUserNameFromJwt(String token){
return Jwts.parserBuilder().setSigningKey(generateKey())
.build().parseClaimsJws(token).getBody().getSubject();
}
}
JwtFilter
This class extends the OncePerRequestFilter and will be used to autheticate the user by validating the jwt. If input jwt is valid then it will add the authentication token for the user in security context holder.
content_copy
copy
package org.example.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.dtos.ResponseDto;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
JwtUtils jwtUtils;
@Autowired
UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
if (request.getHeader("Authorization") != null) {
String token = request.getHeader("Authorization")
.substring(7);
if (jwtUtils.validateJwtToken(token)) {
String userName = jwtUtils.getUserNameFromJwt(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}catch (Exception e){
response.getWriter().flush();
ResponseDto<Object> responseDto = new ResponseDto<>();
responseDto.setStatus("error");
responseDto.setErrorMessage(e.getMessage());
ObjectMapper objectMapper = new ObjectMapper();
response.getWriter().write(objectMapper.writeValueAsString(responseDto));
}
}
}
SecurityConfiguration
This class creates the beans for authentication Manager and authentication provider. Here we will be using the daoAuthenticationProvider for authentication using DB. daoAuthenticationProvider uses the UserDetailsService implementation to load the user from DB. We'll also create a bean of SecurityFilterChain and configure the authorization rules for our Api's. Login Api will be accessible without authentication and user related api's will only be accessible to users having admin role. Lastly add the jwtFilter before the usernamePasswordAuthenticationFilter. So, to authenticate the user using jwt once user has logged in.
content_copy
copy
package org.example.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Autowired
UserDetailsService userDetailsService;
@Autowired
JwtFilter jwtFilter;
@Bean
AuthenticationManager getAuthenticationManagerBean(AuthenticationConfiguration authConf) throws Exception {
return authConf.getAuthenticationManager();
}
@Bean
DaoAuthenticationProvider getDaoAuthProviderBean() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(NoOpPasswordEncoder.getInstance());
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
return daoAuthenticationProvider;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception{
httpSecurity.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(
req ->
req.requestMatchers("/login").permitAll()
.requestMatchers("/getUsers", "/createUser", "/updateUser", "/deleteUser/{userId}")
.hasAuthority("ADMIN")
.anyRequest().authenticated());
httpSecurity.authenticationProvider(getDaoAuthProviderBean());
httpSecurity.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
}
Services
Now create the service classes.
CommonUtils
This is a utility class that creates different tyepes of responses.
content_copy
copy
package org.example.services;
import org.example.dtos.PaginationDto;
import org.example.dtos.ResponseDto;
import org.springframework.stereotype.Component;
@Component
public class CommonUtils {
public <T> ResponseDto<T> successResponseWithoutData() {
ResponseDto<T> responseDto = new ResponseDto<>();
responseDto.setStatus("success");
return responseDto;
}
public <T> ResponseDto<T> successResponseWithDataAndPagination(T data, PaginationDto paginationDto) {
ResponseDto<T> responseDto = new ResponseDto<>();
responseDto.setStatus("success");
responseDto.setData(data);
responseDto.setPagination(paginationDto);
return responseDto;
}
public <T> ResponseDto<T> successResponseWithData(T data){
ResponseDto<T> responseDto = new ResponseDto<>();
responseDto.setStatus("success");
responseDto.setData(data);
return responseDto;
}
}
BookService
content_copy
copy
package org.example.services;
import org.example.dtos.BookDto;
import org.example.dtos.PaginationDto;
import org.example.dtos.ResponseDto;
import org.example.entities.Books;
import jakarta.transaction.Transactional;
import org.example.mappers.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.example.repositories.BooksRepository;
import java.util.List;
@Service
public class BookService {
@Autowired
BooksRepository booksRepository;
@Autowired
Mapper mapper;
@Autowired
CommonUtils commonUtils;
public ResponseDto<List<BookDto>> getAllBooks(PaginationDto paginationDto) {
Pageable pageable = PageRequest.of(paginationDto.getCurrentPage(), paginationDto.getPageSize(), Sort.by("bookId"));
Page<Books> books = booksRepository.findAll(pageable);
List<BookDto> bookDtos = mapper.bookEntitiesToBookDtos(books.getContent());
paginationDto.setTotalPages(books.getTotalPages());
return commonUtils.successResponseWithDataAndPagination(bookDtos, paginationDto);
}
@Transactional
public ResponseDto<Object> createBook(BookDto bookDto) {
try {
Books book = new Books();
book = mapper.bookDtoToBookEntity(bookDto);
book.setIssuedQty(0L);
booksRepository.save(book);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
@Transactional
public ResponseDto<Object> updateBook(BookDto bookDto){
try{
Books book = booksRepository.findByBookId(bookDto.getBookId());
book.setTitle(bookDto.getTitle());
book.setAuthorName(bookDto.getAuthorName());
if(bookDto.getInitialQty() < book.getInitialQty()) {
if (book.getInitialQty() - book.getIssuedQty() < bookDto.getInitialQty())
throw new RuntimeException("Initial qty can't be set less than the available qty");
}
book.setInitialQty(bookDto.getInitialQty());
}catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
@Transactional
public ResponseDto<Object> deleteBook(Long bookId){
try {
Books book = booksRepository.findByBookId(bookId);
booksRepository.delete(book);
}catch(Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
}
StudentService
content_copy
copy
package org.example.services;
import org.example.dtos.PaginationDto;
import org.example.dtos.ResponseDto;
import org.example.dtos.StudentDto;
import org.example.entities.Students;
import jakarta.transaction.Transactional;
import org.example.mappers.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.example.repositories.StudentsRepository;
import java.util.List;
@Service
public class StudentService {
@Autowired
StudentsRepository studentsRepository;
@Autowired
Mapper mapper;
@Autowired
CommonUtils commonUtils;
public ResponseDto<List<StudentDto>> getAllStudents(PaginationDto paginationDto) {
Pageable pageable = PageRequest.of(paginationDto.getCurrentPage(), paginationDto.getPageSize(), Sort.by("studentId"));
Page page = studentsRepository.findAll(pageable);
List<StudentDto> studentDtos = mapper.studentEntitiesToStudentDtos(page.getContent());
paginationDto.setTotalPages(page.getTotalPages());
return commonUtils.successResponseWithDataAndPagination(studentDtos, paginationDto);
}
@Transactional
public ResponseDto<Object> createStudent(StudentDto studentDto) {
try {
Students student = new Students();
student = mapper.studentDtoToStudentEntity(studentDto);
studentsRepository.save(student);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
@Transactional
public ResponseDto<Object> updateStudent(StudentDto studentDto) {
try {
Students student = studentsRepository.findByStudentId(studentDto.getStudentId());
student.setContact(studentDto.getContact());
student.setDepartment(studentDto.getDepartment());
student.setName(studentDto.getName());
studentsRepository.save(student);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
@Transactional
public ResponseDto<Object> deleteStudent(Long studentId){
try {
Students student = studentsRepository.findByStudentId(studentId);
studentsRepository.delete(student);
}catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
}
UserService
content_copy
copy
package org.example.services;
import org.example.dtos.PaginationDto;
import org.example.dtos.ResponseDto;
import org.example.dtos.UserDto;
import org.example.entities.Roles;
import org.example.entities.UserRoles;
import org.example.entities.Users;
import jakarta.transaction.Transactional;
import org.example.mappers.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.example.repositories.RolesRepository;
import org.example.repositories.UserRolesRepository;
import org.example.repositories.UsersRepository;
import java.util.List;
@Service
public class UserService {
@Autowired
UsersRepository usersRepository;
@Autowired
UserRolesRepository userRolesRepository;
@Autowired
RolesRepository rolesRepository;
@Autowired
Mapper mapper;
@Autowired
CommonUtils commonUtils;
public ResponseDto<List<UserDto>> getUsers(PaginationDto paginationDto) {
Pageable pageable = PageRequest.of(paginationDto.getCurrentPage(), paginationDto.getPageSize(), Sort.by("userId"));
Page page = usersRepository.findAll(pageable);
List<UserDto> userDtos = mapper.userEntitiesToUserDtos(page.getContent());
paginationDto.setTotalPages(page.getTotalPages());
return commonUtils.successResponseWithDataAndPagination(userDtos, paginationDto);
}
@Transactional
public ResponseDto<Object> createUser(UserDto userDto) {
try {
Users user = new Users();
user = mapper.userDtoToUserEntity(userDto);
user.setPassword("librarianPassword");
usersRepository.save(user);
//create user roles
UserRoles userRoles = new UserRoles();
Roles role = rolesRepository.findByRoleName("LIBRARIAN");
userRoles.setUsers(user);
userRoles.setRoles(role);
userRolesRepository.save(userRoles);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
@Transactional
public ResponseDto<Object> updateUser(UserDto userDto) {
try {
Users user = usersRepository.findByUserId(userDto.getUserId());
user.setUserName(userDto.getUserName());
user.setContact(userDto.getContact());
user.setEmail(userDto.getEmail());
usersRepository.save(user);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
@Transactional
public ResponseDto<Object> deleteUser(Long userId){
try {
Users user = usersRepository.findByUserId(userId);
UserRoles userRoles = userRolesRepository.findByUsers_userId(userId);
userRolesRepository.delete(userRoles);
usersRepository.delete(user);
}catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
}
LmsSerivce
content_copy
copy
package org.example.services;
import org.example.entities.Books;
import org.example.entities.IssuedBooks;
import org.example.entities.Students;
import jakarta.transaction.Transactional;
import org.example.mappers.Mapper;
import org.example.dtos.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.example.repositories.BooksRepository;
import org.example.repositories.IssuedBooksRepository;
import org.example.repositories.StudentsRepository;
import org.example.security.CustomUser;
import org.example.security.JwtUtils;
import java.util.Date;
import java.util.List;
@Service
public class LmsService {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
JwtUtils jwtUtils;
@Autowired
CommonUtils commonUtils;
@Autowired
StudentsRepository studentsRepository;
@Autowired
BooksRepository booksRepository;
@Autowired
IssuedBooksRepository issuedBooksRepository;
@Autowired
Mapper mapper;
public ResponseDto<LoginResDto> login(LoginReqDto loginReqDto) {
try {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginReqDto.getUserName(), loginReqDto.getPassword()));
CustomUser customUser = (CustomUser) authentication.getPrincipal();
String jwtToken = jwtUtils.generateJwt(customUser.getUsername());
LoginResDto loginResDto = new LoginResDto();
loginResDto.setAuthToken(jwtToken);
return commonUtils.successResponseWithData(loginResDto);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
@Transactional
public ResponseDto<Object> issueBook(IssueReturnDto issueReturnDto) {
try {
Books book = booksRepository.findByBookId(issueReturnDto.getBookId());
Students student = studentsRepository.findByStudentId(issueReturnDto.getStudentId());
if (book == null)
throw new RuntimeException("Book not found");
if (student == null)
throw new RuntimeException("student not found");
if (book.getInitialQty() - book.getIssuedQty() <= 0)
throw new RuntimeException("book not available");
IssuedBooks alreadyIssuedBook = issuedBooksRepository.findByBook_BookIdAndStudent_StudentId(issueReturnDto.getBookId(), issueReturnDto.getStudentId());
if (alreadyIssuedBook != null)
throw new RuntimeException("book is already issued to student");
book.setIssuedQty(book.getIssuedQty() + 1);
booksRepository.save(book);
IssuedBooks issuedBook = new IssuedBooks();
issuedBook.setBook(book);
issuedBook.setStudent(student);
issuedBook.setIssuedDate(new Date());
issuedBook.setDuration(issueReturnDto.getDuration());
issuedBooksRepository.save(issuedBook);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
@Transactional
public ResponseDto<Object> returnBook(IssueReturnDto issueReturnDto) {
try {
Books book = booksRepository.findByBookId(issueReturnDto.getBookId());
IssuedBooks issuedBook = issuedBooksRepository.findByBook_BookIdAndStudent_StudentId(issueReturnDto.getBookId(), issueReturnDto.getStudentId());
if (book == null)
throw new RuntimeException("book not found");
if (issuedBook == null)
throw new RuntimeException("either book id or student id is incorrect");
book.setIssuedQty(book.getIssuedQty() - 1);
booksRepository.save(book);
issuedBook.setReturnDate(new Date());
issuedBooksRepository.save(issuedBook);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return commonUtils.successResponseWithoutData();
}
public ResponseDto<List<IssuedBookDto>> viewIssuedBooks(PaginationDto paginationDto) {
Pageable pageable = PageRequest.of(paginationDto.getCurrentPage(), paginationDto.getPageSize());
Page page = issuedBooksRepository.findAll(pageable);
List<IssuedBookDto> issuedBookDtos = mapper.issuedBookEntitiesToIssuedBookDto(page.getContent());
paginationDto.setTotalPages(page.getTotalPages());
return commonUtils.successResponseWithDataAndPagination(issuedBookDtos, paginationDto);
}
public ResponseDto<List<IssuedBookDto>> viewDefaultersList(PaginationDto paginationDto){
Pageable pageable = PageRequest.of(paginationDto.getCurrentPage(), paginationDto.getPageSize());
Page page = issuedBooksRepository.findDefaulters(pageable);
List<IssuedBookDto> issuedBookDtos = mapper.issuedBookEntitiesToIssuedBookDto(page.getContent());
paginationDto.setTotalPages(page.getTotalPages());
return commonUtils.successResponseWithDataAndPagination(issuedBookDtos, paginationDto);
}
}
Rest Controller
LmsController
Create Rest Controller that will handle incoming requests on different endpoints.
content_copy
copy
package org.example.controllers;
import org.example.dtos.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.example.services.BookService;
import org.example.services.LmsService;
import org.example.services.StudentService;
import org.example.services.UserService;
import java.util.List;
@RestController
public class LmsController {
@Autowired
LmsService lmsService;
@Autowired
BookService bookService;
@Autowired
StudentService studentService;
@Autowired
UserService userService;
@PostMapping("/login")
public ResponseDto<LoginResDto> login(@RequestBody RequestDto<LoginReqDto> requestDto) {
return lmsService.login(requestDto.getData());
}
@PostMapping("/getUsers")
public ResponseDto<List<UserDto>> getUsers(@RequestBody RequestDto<UserDto> requestDto) {
return userService.getUsers(requestDto.getPagination());
}
@PostMapping("/createUser")
public ResponseDto<Object> createUser(@RequestBody RequestDto<UserDto> requestDto) {
return userService.createUser(requestDto.getData());
}
@PostMapping("/updateUser")
public ResponseDto<Object> updateUser(@RequestBody RequestDto<UserDto> requestDto) {
return userService.updateUser(requestDto.getData());
}
@PostMapping("/deleteUser/{userId}")
public ResponseDto<Object> deleteUser(@PathVariable Long userId) {
return userService.deleteUser(userId);
}
@PostMapping("/getBooks")
public ResponseDto<List<BookDto>> getBooks(@RequestBody RequestDto<BookDto> requestDto) {
return bookService.getAllBooks(requestDto.getPagination());
}
@PostMapping("/createBook")
public ResponseDto<Object> createBook(@RequestBody RequestDto<BookDto> requestDto) {
return bookService.createBook(requestDto.getData());
}
@PostMapping("/updateBook")
public ResponseDto<Object> updateBook(@RequestBody RequestDto<BookDto> requestDto) {
return bookService.updateBook(requestDto.getData());
}
@PostMapping("/deleteBook/{bookId}")
public ResponseDto<Object> deleteBook(@PathVariable Long bookId) {
return bookService.deleteBook(bookId);
}
@PostMapping("/getStudents")
public ResponseDto<List<StudentDto>> getStudents(@RequestBody RequestDto<StudentDto> requestDto) {
return studentService.getAllStudents(requestDto.getPagination());
}
@PostMapping("/createStudent")
public ResponseDto<Object> createStudent(@RequestBody RequestDto<StudentDto> requestDto) {
return studentService.createStudent(requestDto.getData());
}
@PostMapping("/updateStudent")
public ResponseDto<Object> updateStudent(@RequestBody RequestDto<StudentDto> requestDto) {
return studentService.updateStudent(requestDto.getData());
}
@PostMapping("/deleteStudent/{studentId}")
public ResponseDto<Object> deleteStudent(@PathVariable Long studentId) {
return studentService.deleteStudent(studentId);
}
@PostMapping("/issueBook")
public ResponseDto<Object> issueBook(@RequestBody RequestDto<IssueReturnDto> requestDto) {
return lmsService.issueBook(requestDto.getData());
}
@PostMapping("/returnBook")
public ResponseDto<Object> returnBook(@RequestBody RequestDto<IssueReturnDto> requestDto) {
return lmsService.returnBook(requestDto.getData());
}
@PostMapping("/viewIssuedBooks")
public ResponseDto<List<IssuedBookDto>> viewIssuedBooks(@RequestBody RequestDto<Object> requestDto) {
return lmsService.viewIssuedBooks(requestDto.getPagination());
}
@PostMapping("/viewDefaulters")
public ResponseDto<List<IssuedBookDto>> viewDefaulters(@RequestBody RequestDto<Object> requestDto){
return lmsService.viewDefaultersList(requestDto.getPagination());
}
}
LmsApplication
Lastly, create the Spring boot application class.
content_copy
copy
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LmsApplication {
public static void main(String[] args){
SpringApplication.run(LmsApplication.class, args);
}
}
This concludes our Library Management System using Spring boot.