Skip to content
Dennis Chacko edited this page Jul 19, 2024 · 95 revisions

Tool Rental Service

A simple tool rental application

Table of Contents

Overview

The Tool Rental Service is simple tool rental application with the below features:

  • Customers rent a tool for a specified number of days.
  • When a customer checks out a tool, a Rental Agreement is produced.
  • The store charges a daily rental fee, whose amount is different for each tool type.
  • Some tools are free of charge on weekends or holidays.
  • Clerks may give customers a discount that is applied to the total daily charges to reduce the final charge.

High Level Design and Solution

Solution Overview

  • The service exposes an REST API that supports the below resources/operations
    • Operation to read all available tools
    • Operation to read pricing details per tool
    • Operation to checkout and create a rental agreement per tool
    • [Future state] Operation to add/delete tools available for rent
    • [Future state] Operation to add/update pricing details per tool
  • Each operation should validate user entered input and throw HTTP BAD Request for validation errors
  • The service should follow an API First Design approach while adding new functionality. See API First Design approach for more details
  • The service should auto-generate Spring REST code using the supplied Open API file. The OpenAPI file is available here

Class Diagram

The Class Diagram includes some classes auto-generated from the OpenApi specification for this service

  • The OpenAPI specification for the Tool Rental Service is available here.
  • The service uses an API first approach to implement this service. The Java and Spring annotated REST classes were auto generated from The Online Swagger Editor
  • The AbstractController clas implements the API interface
  • The below JPA repository classes are used to interface with the database
    • ToolRepository to fetch available tools from the database
    • ToolPriceRepository to fetch pricing details about a tool
    • RentalRequestRepository to persist each rental request in the database
    • RentalAgreementRepository to persist rental agreements in the database
---
title: ToolRentalService Class Diagram
---
classDiagram
    
   namespace ControllerClasses{
    
        class ToolRentalAPI{
        <<interface>>
        }
        class Tool{
        }
        class ToolRentalPrice{
        }
        class RentalRequest{
        }
        class RentalAgreement{
        }
        class AbstractController{
        }
    }

    Tool <-- ToolRentalAPI
    ToolRentalPrice <-- ToolRentalAPI
    RentalRequest <-- ToolRentalAPI
    RentalAgreement <-- ToolRentalAPI
    ToolRentalAPI <|-- AbstractController

    namespace ServiceClasses {
        class IRentalAgreementService {
        <<interface>>
        }
        class IHoliday {
            <<interface>>
        }
        class FourthJuly{
            +isHoliday()
        }
        class LaborDay{
            +isHoliday()
        }
        class Weekend{
            +isHoliday()
        }
        class ObserverableHoliday{
            +isHoliday()
        }
        class RentalAgreementService{
        }
        class RentalDurationService{
        }
        class DateRangeDetails {
        }
    }

    IRentalAgreementService <|-- RentalAgreementService
    RentalDurationService <-- RentalAgreementService
    Weekend <-- RentalDurationService
    ObserverableHoliday <-- RentalDurationService
    DateRangeDetails <-- RentalDurationService
    DateRangeDetails <-- RentalAgreementService

    
    IRentalAgreementService <-- AbstractController 
    
    namespace PersistenceClasses {
    
        class ToolRepository { 
        <<interface>>
        }
        class ToolPriceRepository { 
        <<interface>>
        }
        class RentalRequestRepository { 
        <<interface>>
        }
        class RentalAgreementRepository { 
        <<interface>>
        }   
        class ToolEntity{
        }
        
        class ToolPriceEntity{
        }
        
        class RentalRequestEntity{
        }
        
        class RentalAgreementEntity{
        }
    
    }

    ToolRepository <-- RentalAgreementService
    ToolPriceRepository <-- RentalAgreementService
    RentalRequestRepository <-- RentalAgreementService
    RentalAgreementRepository <-- RentalAgreementService
    RentalAgreementEntity <-- RentalAgreementRepository
    RentalRequestEntity <-- RentalRequestRepository
    ToolPriceEntity <-- ToolPriceRepository
    ToolEntity <-- ToolRepository

    IHoliday <|-- FourthJuly
    IHoliday <|-- LaborDay
    IHoliday <|-- Weekend
    IHoliday <|-- ObserverableHoliday
    LaborDay <-- ObserverableHoliday
    FourthJuly <-- ObserverableHoliday
    IHoliday: +isHoliday()
    
Loading

Observed Holidays

The service currently supports the below holidays:

  • Fourth of July
  • Labor Day

New holidays can be added by following the below steps:

  • Create a new class that implements the IHoliday interface
  • Create a instance of this new class and add it to the ObservedHoliday class. for e.g to support Memorial Day as an observed holiday:
public class ObservedHoliday implements IHoliday{
    private static final List<IHoliday> observedHolidays = List.of(
            new FourthJuly(),
            new LaborDay(),
            new MemorialDay());

OpenAPI Specification

The OpenAPI specification for this service is available here

Supported Operations

The below operations are supported by this service

Fetch All Tools available for Rental

Please see Fetch all tools available for rent

Fetch Pricing Details for each Tool

Please see Fetch Pricing Details for each Tool

Checkout a tool for rental

Please see Checkout a tool for rental

Error Handling

  • All business errors should be wrapped in an ValidationException class
  • Communicate business exception as HTTP 400 Bad Request

Sample error handling Spring-based RestService . Reference Error Handling for Spring Rest Services

@ControllerAdvice
public class RestResponseEntityExceptionHandler 
  extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value 
      = { ValidationException.class })
    protected ResponseEntity<Object> handleConflict(
      RuntimeException ex, WebRequest request) {
        String bodyOfResponse = "This should be application specific";
        return handleExceptionInternal(ex, bodyOfResponse, 
          new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
    }
}