A library management system built with a layered architecture, focusing on data integrity, input validation, and comprehensive testing.
- Language: Java 21
- Framework: Spring Boot 4.0.2, Spring Security
- Database: PostgreSQL
- Mapping: MapStruct (Entity & DTO)
- Documentation: Swagger UI
- Testing: JUnit 5, Mockito, MockMvc
erDiagram
AUTHOR ||--o{ BOOK : "writes"
READER ||--o{ LOAN : "borrows"
BOOK ||--o{ LOAN : "is subject of"
USER ||--|| READER : "is linked to"
USER ||--o{ USER_ROLE : "has"
ROLE ||--o{ USER_ROLE : "assigned to"
AUTHOR {
Long id PK
String name
String biography
}
BOOK {
Long id PK
String title
String isbn
boolean available
Long authorId FK
}
USER {
Long id PK
String email
String password
}
ROLE {
Long id PK
String name
}
USER_ROLE {
Long userId FK
Long roleId FK
}
READER {
Long id PK
String fullName
Long userId FK
}
LOAN {
Long id PK
Long bookId FK
Long readerId FK
LocalDateTime loanDate
LocalDateTime dueDate
LocalDateTime returnDate
}
Note: Entities
Author,Book,Loan,Reader, andUsertrack creation and modification timestamps (createdAt,modifiedAt) via JPA Auditing. These fields are omitted from the diagram for clarity.
- Authentication & Authorization: REST API secured with JSON Web Tokens (JWT). Role-based access control (RBAC) separating regular users and administrators.
- Advanced Loan System: Full lifecycle of book borrowing and returns with automated availability management and overdue tracking.
- JPA Auditing: Automated tracking of creation and modification timestamps for every resource using
@CreatedDateand@LastModifiedDate. - Global Exception Handling: Centralized error management using
@RestControllerAdviceto ensure consistent JSON error responses across the API. - Validation: Input data is strictly validated using Hibernate Validator annotations (e.g.,
@NotBlank,@Size) to maintain data quality. - API-Entity Decoupling: Strict separation between database entities and API response models (DTOs) to ensure data security and interface stability.
- Database Versioning: Full schema control and versioning using Liquibase.
- Optimized Persistence: Utilization of JPA EntityGraphs to eliminate N+1 query problems during data retrieval, improving performance by reducing database round-trips.
- Externalized Configuration: Business rules (loan limits, duration) are managed via YAML profiles.
The project maintains a high standard of quality through different testing layers:
- Unit Tests: Focused on business logic within the Service layer, utilizing Mockito for dependency isolation.
- Web Layer Tests: Utilizing MockMvc to verify REST endpoints, HTTP status codes, JSON serialization, and validation logic without starting the full server.
- Persistence Tests:
@DataJpaTestused to verify complex JPQL queries and relationship mapping. - Code Coverage: Automated code coverage analysis using JaCoCo, with reports generated for every build.
- CI/CD Integration: Automated test execution via GitHub Actions on every push.
The application is configured using environment variables and application.yaml properties.
Infrastructure & Security
| Variable / Property | Description | Default |
|---|---|---|
BD_INITIAL_ADMIN_EMAIL |
Email for the initial admin account | root@biblionode.com |
BD_INITIAL_ADMIN_PASSWORD |
Password for the initial admin account | root1234 |
RSA_PUBLIC_KEY |
Path to RSA public key for JWT | file:./certs/public_key.pem |
RSA_PRIVATE_KEY |
Path to RSA private key for JWT | file:./certs/private_key.pem |
SPRING_PROFILES_ACTIVE |
Active Spring profile (dev, prod) |
prod |
Business Rules
Can be adjusted in application.yaml or overridden via environment variables (e.g. app.loan.max-active-loans -> APP_LOAN_MAX_ACTIVE_LOANS).
| Property Key | Default | Description |
|---|---|---|
app.loan.max-active-loans |
5 |
Maximum active loans per reader |
app.loan.default-loan-days |
14 |
Loan duration in days |
app.security.jwt-expiration-hours |
1 |
JWT token validity (hours) |
app.pagination.default-page-size |
20 |
Default page size for lists |
Best for quick preview. No Java/Gradle installation required.
-
Clone the repository:
git clone https://github.com/mgrablo/BiblioNode.git cd BiblioNode -
Start the application:
# Run with default 'prod' profile docker-compose up -dAlternatively, force the 'dev' profile:
SPRING_PROFILES_ACTIVE=dev docker-compose up -d
Default Credentials: See Configuration.
[!TIP] You can also create a
.envfile in the root directory to set variables. Check.env.example.
Best for making changes to the code with fast feedback.
-
Start only database:
docker-compose up -d db
-
Start the app locally:
[!NOTE] Requires JDK 21 and Gradle locally. The app will connect to the database running in Docker. Keys are generated automatically in
certs/on first run (devprofile).Navigate to the API directory:
cd biblionode-api# Linux/Mac SPRING_PROFILES_ACTIVE=dev ./gradlew bootRun # Windows (PowerShell) $env:SPRING_PROFILES_ACTIVE="dev"; ./gradlew bootRun
Once the server is running, navigate to:
http://localhost:8080/swagger-ui.html
To stop containers and remove volumes (resets database):
docker-compose down -v- Basic CRUD for Books and Authors.
- Database Auditing & Pagination.
- Database Migrations with Liquibase.
- Loan System Implementation.
- Automatic availability management.
- Overdue tracking.
- Personal loan history for readers (
api/me/).
- JWT Authentication & User Roles.