Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Library Resource Booking & Reservation Queue API

Spring Boot REST API for borrowing shared library resources (books, equipment, AV kits) with FIFO waitlists and time-limited reservations.

Prerequisites

  • Java 17+
  • Maven 3.9+

Run locally

mvn spring-boot:run

API base URL: http://localhost:8080

H2 file database persists under ./data/librarydb.mv.db. H2 console: http://localhost:8080/h2-console (JDBC URL jdbc:h2:file:./data/librarydb, user sa, empty password).

Run tests

mvn test

Integration tests use in-memory H2 with library.reservation.claim-window-hours=0 to exercise expiry cascade in one request.

API endpoints

Capability Method & path
Create resource POST /api/resources
Create employee POST /api/employees
Borrow (or join waitlist) POST /api/resources/{resourceId}/borrow
Return copy POST /api/resources/{resourceId}/return
View waitlist GET /api/resources/{resourceId}/waitlist
Leave waitlist DELETE /api/resources/{resourceId}/waitlist/{employeeId}
Claim reservation POST /api/reservations/{reservationId}/claim
Process expired reservations POST /api/reservations/process-expired
Employee activity GET /api/employees/{employeeId}/activity

Request bodies for borrow/return/claim:

{ "employeeId": 1 }

Create resource:

{ "title": "Clean Code", "type": "BOOK", "totalCopies": 2 }

type enum: BOOK, EQUIPMENT, AV_KIT.

Design

Domain model

  • Resource — catalog item with totalCopies
  • BorrowRecord — active/historical loans (returned_at null = active)
  • WaitlistEntry — FIFO queue per resource (WAITINGRESERVEDFULFILLED / LEFT)
  • Reservation — separate entity with lifecycle (PENDINGCLAIMED / EXPIRED), linked to waitlist entry

Availability:

available = totalCopies - activeBorrows - pendingReservations

Expiry & queue advancement

No background scheduler. POST /api/reservations/process-expired checks pending reservations past expires_at, marks them EXPIRED, removes the holder from the waitlist, and offers the freed copy to the next WAITING entry with a fresh claim window. The service loops until no expired pending reservations remain, so chained expiries advance through the queue in one call.

On return, if the waitlist has WAITING entries, a reservation is created for the front person immediately.

Default claim window: 24 hours (library.reservation.claim-window-hours in application.properties).

Assumptions

  • One borrow record per employee per resource at a time (no double-borrow).
  • Employee cannot join the same waitlist twice while WAITING or RESERVED.
  • Employee with RESERVED status cannot leave waitlist until they claim or the reservation expires.
  • Borrow endpoint auto-joins waitlist when no copy is available (not rejected).
  • process-expired is the documented mechanism for expiry; callers invoke it on a schedule or after the claim window.

HTTP status codes

Code When
201 Resource/employee created; borrow/waitlist join
200 Successful read or mutation
204 Left waitlist
400 Validation failure
404 Missing resource/employee/reservation/waitlist entry
409 Business rule conflict

Database schema

See schema.sql for the full DDL. The schema models Resource, WaitlistEntry, and Reservation as separate tables so reservation expiry can release a copy and advance the FIFO queue without overloading a single reserved_by column on the resource.

erDiagram
    RESOURCES ||--o{ BORROW_RECORDS : has
    EMPLOYEES ||--o{ BORROW_RECORDS : makes
    RESOURCES ||--o{ WAITLIST_ENTRIES : has
    EMPLOYEES ||--o{ WAITLIST_ENTRIES : joins
    WAITLIST_ENTRIES ||--o| RESERVATIONS : triggers
    RESOURCES ||--o{ RESERVATIONS : holds
    EMPLOYEES ||--o{ RESERVATIONS : assigned_to

    RESOURCES {
        bigint id PK
        string title
        string type
        int total_copies
    }
    EMPLOYEES {
        bigint id PK
        string name
        string email UK
    }
    BORROW_RECORDS {
        bigint id PK
        bigint resource_id FK
        bigint employee_id FK
        timestamp borrowed_at
        timestamp returned_at
    }
    WAITLIST_ENTRIES {
        bigint id PK
        bigint resource_id FK
        bigint employee_id FK
        timestamp joined_at
        string status
    }
    RESERVATIONS {
        bigint id PK
        bigint waitlist_entry_id FK
        bigint resource_id FK
        bigint employee_id FK
        timestamp created_at
        timestamp expires_at
        string status
    }
Loading

Availability is derived at runtime:

available = total_copies − active_borrows − pending_reservations

Manual API testing

File Purpose
api-tests.http Happy path, all rule violations, validation, 404s
api-tests-expiry-cascade.http Multi-step expiry cascade + claim-after-expiry (start app with --library.reservation.claim-window-hours=0)
postman/Library-Resource-Booking-Oman.postman_collection.json Postman collection (Alharith + Omani resources, ordered steps)

Automated evidence: mvn test (includes expiry-cascade integration test).

Project structure

src/main/java/com/library/
  controller/   REST layer
  service/      Business rules
  repository/   JPA persistence
  model/        Entities & enums
  dto/          Request/response records
  exception/    404/409/400 handling

Submission checklist

  • Spring Boot REST API with SQL persistence (H2 file mode)
  • All required endpoints implemented
  • Business rules enforced (409 for conflicts)
  • Layered architecture (controller / service / repository)
  • schema.sql + ER diagram above
  • README with run instructions, assumptions, and design notes
  • API test collection (.http files) with rule violations and expiry cascade
  • Integration tests (mvn test)

To submit:

git init
git add .
git commit -m "Submit Library Resource Booking API"
git remote add origin <your-repo-url>
git push -u origin main

Or zip the project (exclude target/ and data/).

library-project

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages