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

EXPERIMENT11 Ejava

Uploaded by

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

EXPERIMENT11 Ejava

Uploaded by

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

EXPERIMENT -11

AIM OF THE EXPERIMENT: Spring Boot Book Inventory System.

Create a basic book inventory system using Spring Boot to help a small library
manage itsbook collection. The system should allow librarians to add new books,
update existing book details, remove books from inventory, and search for books
by title, author, or category.

Code
configure

package com.sudhanshu.lms.auth.config;

import com.dhitha.lms.auth.dto.ErrorDTO;
import com.dhitha.lms.auth.error.GenericException; import
java.time.LocalDateTime;
import java.util.stream.Collectors;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpHeaders; import
org.springframework.http.HttpStatus; import
org.springframework.http.ResponseEntity; import
org.springframework.lang.NonNull;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException; import
org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import
org.springframework.web.context.request.WebRequest; import
org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/**
* Common Exception Handler
*
* @author Dhiraj
*/
@ControllerAdvice
@Log4j2
public class GenericExceptionHandler extends ResponseEntityExceptionHandler {

@NonNull
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex,
@NonNull HttpHeaders headers,
@NonNull HttpStatus status,
@NonNull WebRequest request) {
log.error("handleMethodArgumentNotValid():{} -> {}", ex.getCause(), ex.getBindingResult());
BindingResult bindingResult = ex.getBindingResult();
String description = bindingResult.getFieldErrors().stream()
.map(
objectError ->
String.join(" : ", objectError.getField(), objectError.getDefaultMessage()))
.collect(Collectors.joining(", ")); ErrorDTO
err =
ErrorDTO.builder()
.error("invalid_input")
.error_description(description)
.status(HttpStatus.BAD_REQUEST.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.badRequest().body(err);
}

@NonNull
@Override
protected ResponseEntity<Object> handleExceptionInternal(
Exception ex,
Object body,
@NonNull HttpHeaders headers,
HttpStatus status,
@NonNull WebRequest request) {
log.error("handleExceptionInternal():{} -> {}", ex.getCause(), ex);
ErrorDTO err =
ErrorDTO.builder()
.error("invalid_request")
.error_description(ex.getLocalizedMessage())
.status(status.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(status).body(err);
}

@ExceptionHandler({GenericException.class})
private ResponseEntity<ErrorDTO> handleGeneric(GenericException ex) { log.error(
"handleGeneric():{} -> {} : status: {}", ex.getCause(), ex.getMessage(), ex.getStatus());
ErrorDTO err =
ErrorDTO.builder()
.error("invalid_request")
.error_description(ex.getLocalizedMessage())
.status(ex.getStatus())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(ex.getStatus()).body(err);
}

@ExceptionHandler({IllegalArgumentException.class}) private
ResponseEntity<ErrorDTO>
handleIllegalArgumentException(IllegalArgumentException ex) { ErrorDTO
err =
ErrorDTO.builder()
.error("invalid_request")
.error_description(ex.getLocalizedMessage())
.status(HttpStatus.BAD_REQUEST.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.badRequest().body(err);
}

@ExceptionHandler({Exception.class})
private ResponseEntity<ErrorDTO> handleException(Exception ex) {
log.error("handleException():", ex);
ErrorDTO err =
ErrorDTO.builder()
.error("server_error")
.error_description("Something went wrong")
.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(err);
}
}
inventory.java
package com.dhitha.lms.auth.config;

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value; import
org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.BadCredentialsException; import
org.springframework.security.config.annotation.web.builders.HttpSecurity; import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapt er;
import org.springframework.security.config.http.SessionCreationPolicy; import
org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingF ilter;
/**
* Security Configuration to protect from non internal calls
*
* @author Dhiraj
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Value("${lms.client.key}") private
String clientKey;

@Override
protected void configure(HttpSecurity http) throws Exception {

AbstractPreAuthenticatedProcessingFilter filter = getApiAuthenticatingFilter();

http.csrf()
.disable()
.addFilter(filter)
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.formLogin()
.disable();
}

private AbstractPreAuthenticatedProcessingFilter getApiAuthenticatingFilter() {


AbstractPreAuthenticatedProcessingFilter filter =
new AbstractPreAuthenticatedProcessingFilter() {
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { return
request.getHeader("lms-key");
}

@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { return
"";
}
};
filter.setAuthenticationManager( aut
hentication -> {
Object principal = authentication.getPrincipal();
if (clientKey == null || !clientKey.equals(principal)) { throw new
BadCredentialsException("Invalid Api Key");
}
authentication.setAuthenticated(true); return
authentication;
});
return filter;
}
}
Book Inventory Management

Control
package com.dhitha.lms.auth.controller;

import com.dhitha.lms.auth.dto.AuthRequestDTO; import


com.dhitha.lms.auth.dto.AuthResponseDTO; import
com.dhitha.lms.auth.error.GenericException; import
com.dhitha.lms.auth.service.AuthService; import
javax.validation.Valid;
import lombok.RequiredArgsConstructor; import
lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders; import
org.springframework.http.MediaType; import
org.springframework.http.ResponseEntity; import
org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import
org.springframework.web.bind.annotation.RequestHeader; import
org.springframework.web.bind.annotation.RequestMapping; import
org.springframework.web.bind.annotation.RestController;

/**
* REST controller for Auth Service
*
* @author Dhiraj
*/
@RestController
@RequestMapping("/v1")
@RequiredArgsConstructor @Slf4j
public class AuthController {
private final AuthService authService;

@PostMapping(
value = "/token/authenticate",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<AuthResponseDTO> authenticateUser(
@RequestBody @Valid AuthRequestDTO authDTO) throws GenericException {
log.info("Authenticating............");
AuthResponseDTO authenticate = authService.authenticate(authDTO);
log.info("Authenticated : {}", authenticate);
return ResponseEntity.ok().body(authenticate);
}

@PostMapping(
value = "/token/verify",
produces = MediaType.APPLICATION_JSON_VALUE, consumes =
MediaType.APPLICATION_JSON_VALUE) public
ResponseEntity<AuthResponseDTO> verifyToken(
@RequestHeader(value = HttpHeaders.AUTHORIZATION) String token) throws GenericException {
log.info("Verification token {} ", token);
Assert.notNull(token, "token cannot be null");
if(token.startsWith("Bearer ")){
token = token.substring(7);
}else{
throw new IllegalArgumentException("Bearer token missing");
}
return ResponseEntity.ok(authService.verifyToken(token));
}
}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>LMS</title>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css"
/>
</head>
<body>
<noscript>
<strong
>We're sorry but Library Management System doesn't work properly without JavaScript
enabled. Please enable it to continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Model
package com.dhitha.lms.inventory.config;

import com.dhitha.lms.inventory.dto.ErrorDTO;
import com.dhitha.lms.inventory.error.GenericException;
import com.dhitha.lms.inventory.error.InventoryNotFoundException; import
java.time.LocalDateTime;
import java.util.stream.Collectors;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpHeaders; import
org.springframework.http.HttpStatus; import
org.springframework.http.ResponseEntity; import
org.springframework.lang.NonNull;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException; import
org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import
org.springframework.web.context.request.WebRequest; import
org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/**
* Common Exception Handler
*
* @author Dhiraj
*/
@ControllerAdvice
@Log4j2
public class GenericExceptionHandler extends ResponseEntityExceptionHandler { @NonNull

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex,
@NonNull HttpHeaders headers,
@NonNull HttpStatus status,
@NonNull WebRequest request) {
log.error("handleMethodArgumentNotValid():{} -> {}", ex.getCause(), ex.getBindingResult());
BindingResult bindingResult = ex.getBindingResult();
String description = bindingResult.getFieldErrors().stream()
.map(
objectError ->
String.join(" : ", objectError.getField(), objectError.getDefaultMessage()))
.collect(Collectors.joining(", ")); ErrorDTO
err =
ErrorDTO.builder()
.error("invalid_input")
.error_description(description)
.status(HttpStatus.BAD_REQUEST.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.badRequest().body(err);
}

@NonNull
@Override
protected ResponseEntity<Object> handleExceptionInternal(
Exception ex,
Object body,
@NonNull HttpHeaders headers,
HttpStatus status,
@NonNull WebRequest request) {
log.error("handleExceptionInternal():{} -> {}", ex.getCause(), ex);
ErrorDTO err =
ErrorDTO.builder()
.error("invalid_request")
.error_description(ex.getLocalizedMessage())
.status(status.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(status).body(err);
}

@ExceptionHandler({InventoryNotFoundException.class})
private ResponseEntity<ErrorDTO> handleInventoryNotFound(Exception ex) {
log.error("handleNotFound():{} -> {}", ex.getCause(), ex.getMessage()); ErrorDTO err =
ErrorDTO.builder()
.error("invalid_request")
.error_description(ex.getLocalizedMessage())
.status(HttpStatus.NOT_FOUND.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(err);
}

@ExceptionHandler({GenericException.class})
private ResponseEntity<ErrorDTO> handleGeneric(GenericException ex) { log.error(
"handleGeneric():{} -> {} : status: {}", ex.getCause(), ex.getMessage(), ex.getStatus());
ErrorDTO err =
ErrorDTO.builder()
.error("invalid_request")
.error_description(ex.getLocalizedMessage())
.status(ex.getStatus())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(ex.getStatus()).body(err);
}

@ExceptionHandler({IllegalArgumentException.class}) private
ResponseEntity<ErrorDTO>
handleIllegalArgumentException(IllegalArgumentException ex) { ErrorDTO
err =
ErrorDTO.builder()
.error("invalid_request")
.error_description(ex.getLocalizedMessage())
.status(HttpStatus.BAD_REQUEST.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.badRequest().body(err);
}

@ExceptionHandler({Exception.class})
private ResponseEntity<ErrorDTO> handleException(Exception ex) {
log.error("handleException()", ex);
ErrorDTO err =
ErrorDTO.builder()
.error("server_error")
.error_description("Something went wrong")
.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.timestamp(LocalDateTime.now())
.build();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(err);
}
}

Book Inventory Management


Services
package com.dhitha.lms.inventory.service;

import com.dhitha.lms.inventory.dto.InventoryDTO; import


com.dhitha.lms.inventory.error.GenericException;
import com.dhitha.lms.inventory.error.InventoryNotFoundException; import
java.util.List;

/**
* Service for {@link InventoryDTO}
*
* @author Dhiraj
*/
public interface InventoryService {

/**
* Find all inventory details by book id
*
* @param bookId -
* @return List of inventory for existing book id
*/
List<InventoryDTO> findAllBook(Long bookId);

/**
* Check if any book reference for a book id is available in LMS If yes mark the first book as
* unavailable and return the marked book
*
* @param bookId -
* @return first available book
* @throws InventoryNotFoundException if none of the books are available for a book id
*/
InventoryDTO orderBookIfAvailable(Long bookId) throws InventoryNotFoundException;

/**
* Mark the book with corresponding reference as available in inventory
*
* @param bookId -
* @param bookReferenceId -
* @return true if book is present in LMS and marking the book as available was successful
*/
boolean returnBook(Long bookId, String bookReferenceId);

/**
* Count of books available
*
* @param bookId -
* @return total number of book available for requested book id
*/
long getAvailableCount(Long bookId);

/**
* Add {@literal 'count'} number of books. Generates unique reference number for each book
*
* @param inventory DTO containing the book id , isbn , category for the new book
* @param count total inventory to add
* @throws GenericException if a book with combination of book id and book reference is already
* present
*/
List<InventoryDTO> add(InventoryDTO inventory, Integer count) throws GenericException;

/**
* Delete an inventory of all books by book id
*
* @param bookId -
* @throws InventoryNotFoundException if no inventory present with book id
*/
void delete(Long bookId) throws InventoryNotFoundException;

/**
* Delete specific book reference of a book type
*
* @param bookId -
* @param bookReferenceId -
* @throws InventoryNotFoundException in case no book is present wih combination of book id and
* book reference id
*/
void delete(Long bookId, List<String> bookReferenceId) throws InventoryNotFoundException;
}

Book Inventory

TASK
package com.dhitha.lms.inventory.service;

import com.dhitha.lms.inventory.dto.InventoryDTO; import


com.dhitha.lms.inventory.entity.Inventory; import
com.dhitha.lms.inventory.error.GenericException;
import com.dhitha.lms.inventory.error.InventoryNotFoundException; import
com.dhitha.lms.inventory.repository.InventoryRepository; import
java.security.SecureRandom;
import java.util.HashSet;
import java.util.List; import
java.util.Optional; import
java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors; import
javax.transaction.Transactional;
import lombok.RequiredArgsConstructor; import
lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper; import
org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service; import
org.springframework.util.Assert;

/**
* Implementation for {@link InventoryService}
*
* @author Dhiraj
*/
@Service
@Slf4j
@RequiredArgsConstructor
@Transactional
public class InventoryServiceImpl implements InventoryService {
private final InventoryRepository inventoryRepository;
private final ModelMapper modelMapper;

@Override
public List<InventoryDTO> findAllBook(Long bookId) {
return inventoryRepository.findByIdBookId(bookId).stream()
.map(this::mapToDTO)
.collect(Collectors.toList());
}

@Override
public InventoryDTO orderBookIfAvailable(Long bookId) throws InventoryNotFoundException
{
InventoryDTO inventoryDTO =
inventoryRepository.findByIdBookId(bookId).stream()
.filter(Inventory::getAvailable)
.findFirst()
.map(this::mapToDTO)
.orElseThrow( (
) ->
new InventoryNotFoundException(
"No inventory available for book id: " + bookId));
inventoryRepository.updateAvailability(
inventoryDTO.getBookId(), inventoryDTO.getBookReferenceId(), false); return
inventoryDTO;
}

@Override
public boolean returnBook(Long bookId, String bookReferenceId) {
return inventoryRepository.updateAvailability(bookId, bookReferenceId, true) > 0;
}

@Override
public long getAvailableCount(Long bookId) {
return inventoryRepository.countByIdBookIdAndAvailable(bookId, true);
}

@Override
@Transactional(rollbackOn = Exception.class)
public List<InventoryDTO> add(InventoryDTO inventoryDTO, Integer count) throws GenericException {
Assert.notNull(inventoryDTO, "Inventory cannot be null"); count
= count != null && count > 0 ? count : 1; Set<Inventory> set =
new HashSet<>(count); SecureRandom secureRandom = new
SecureRandom(); while (count-- > 0) {
Inventory inventory = this.mapToEntity(inventoryDTO);

inventory.getId().setBookReferenceId(String.valueOf(secureRandom.nextInt(Integer.MAX_VALU E)));
inventory.setAvailable(true);
set.add(inventory);
}
try { inventoryRepository.saveAll(set);
} catch (Exception e) {
throw new GenericException(
"Error while saving inventory", HttpStatus.INTERNAL_SERVER_ERROR.value());
}
return set.stream().map(this::mapToDTO).collect(Collectors.toList());
}

@Override
public void delete(Long bookId) throws InventoryNotFoundException { List<Inventory>
bookInventory = inventoryRepository.findByIdBookId(bookId); if
(bookInventory.isEmpty()) {
return;
}
long count = bookInventory.stream().filter(inventory -> !inventory.getAvailable()).count(); if (count
> 0) {
throw new InventoryNotFoundException(
"Some books of book id " + bookId + " are loaned and cannot be deleted ");
}
inventoryRepository.deleteByIdBookId(bookId);
}

@Override
@Transactional(rollbackOn = InventoryNotFoundException.class)
public void delete(Long bookId, List<String> bookReferenceIdList) throws
InventoryNotFoundException {
for(String bookReferenceId: bookReferenceIdList) {
Optional<Inventory> inventory =
inventoryRepository.findByIdBookIdAndIdBookReferenceId(bookId, bookReferenceId); if
(inventory.isEmpty()) {
throw new InventoryNotFoundException(
String.format("No Book found with id %s and reference id %s", bookId, bookReferenceId));
}
if (!inventory.get().getAvailable()) {
throw new InventoryNotFoundException(
String.format(
"Book with id %s and reference id %s is loaned and cannot be deleted", bookId,
bookReferenceId));
}
inventoryRepository.deleteByIdBookIdAndIdBookReferenceId(bookId, bookReferenceId);
}
}
private InventoryDTO mapToDTO(Inventory inventory) { return
modelMapper.map(inventory, InventoryDTO.class);
}

private Inventory mapToEntity(InventoryDTO inventoryDTO) { return


modelMapper.map(inventoryDTO, Inventory.class);
}
}
}

Book Inventory Management

spackage com.dhitha.lms.order.service;

import com.dhitha.lms.order.dto.BookOrderDTO; import


com.dhitha.lms.order.entity.BookOrder; import
com.dhitha.lms.order.error.GenericException;
import com.dhitha.lms.order.error.OrderNotFoundException; import
java.util.List;

/**
* Service for {@link BookOrder}
*
* @author Dhiraj
*/
public interface BookOrderService {
/**
* Find a book order by id
*
* @param id - order id
* @return order details
* @throws OrderNotFoundException if no order present with corresponding id
*/
BookOrderDTO findById(Long id) throws OrderNotFoundException;

/**
* Find all orders of a user
*
* @param userId -
* @return list of orders or empty list if none found
*/
List<BookOrderDTO> findAllByUser(Long userId);

/**
* Find all orders for a book
*
* @param bookId -
* @return list of orders or empty list if none found
*/
List<BookOrderDTO> findAllByBook(Long bookId);

/**
* Find all orders for which the returned date is overdue
*
* @return list of
*/
List<BookOrderDTO> findAllReturnOverdue();

/**
* Find all orders for which the returned date is overdue for a user
*
* @param userId
* @return
*/
List<BookOrderDTO> findAllReturnOverdueForUser(Long userId);

/**
* Find all order for which collection date is overdue
*
* @return
*/
List<BookOrderDTO> findAllCollectionOverdue();

/**
* Find all orders for which collection date is overdue for a user
*
* @param userId
* @return
*/
List<BookOrderDTO> findAllCollectionOverdueForUser(Long userId);

/**
* Order a new book, Connects with Inventory service to fnd if book is available
*
* @param orderDTO order details to add if possible
* @return new order with generated id
* @throws GenericException if order cannot be placed due to book/service unavailability
*/
BookOrderDTO orderBook(BookOrderDTO orderDTO) throws GenericException;

/**
* Mark a order as collected
*
* @param id - order id
* @return order detail with collectedAt date marked as present datetime
* @throws OrderNotFoundException if no order present with id
*/
BookOrderDTO collectBook(Long id) throws OrderNotFoundException;

/**
* Mark the book as returned, Connects with inventory servie to return the book and deletes the
* order and adds it to order history
*
* @param id order id
* @throws OrderNotFoundException if no order present with id
* @throws GenericException if order cannot be returned due to book/service unavailability
*/
BookOrderDTO returnBook(Long id) throws OrderNotFoundException, GenericException;

/**
* Delete an order
*
* @param id
* @throws OrderNotFoundException
*/
void delete(Long id) throws OrderNotFoundException;

} Book Inventory Management

NAME- KUSAGRA RAJ


Reg.- 2201030103
GROUP- 5A
BRANCH- CSE

You might also like