A production-grade, scalable backend built with Java 21, Spring Boot 3.2, PostgreSQL, Hibernate Filters for tenant isolation, and JWT-based stateless authentication.
- Java 21
- Spring Boot 3.2
- Spring Security (JWT-based stateless auth)
- Spring Data JPA + Hibernate 6 (tenant isolation via Hibernate Filters)
- PostgreSQL 15
- JJWT 0.12.5
- Lombok
- Docker / Docker Compose
- Java 21+
- Maven 3.9+
- Docker & Docker Compose
docker compose up --buildThe application will be available at http://localhost:8080.
- Start PostgreSQL (or configure an existing instance):
docker compose up postgres- Build and run the application:
mvn spring-boot:run| Method | Endpoint | Auth Required | Description |
|---|---|---|---|
| POST | /api/v1/organizations | No | Create organization |
| GET | /api/v1/organizations/{id} | No | Get organization |
| PUT | /api/v1/organizations/{id} | No | Update organization |
| DELETE | /api/v1/organizations/{id} | No | Delete organization |
| POST | /api/v1/users | Yes | Create user |
| GET | /api/v1/users/{id} | Yes | Get user |
| PUT | /api/v1/users/{id} | Yes | Update user |
| DELETE | /api/v1/users/{id} | Yes | Delete user |
| POST | /api/v1/roles | Yes | Create role |
| GET | /api/v1/roles/{id} | Yes | Get role |
| PUT | /api/v1/roles/{id} | Yes | Update role |
| DELETE | /api/v1/roles/{id} | Yes | Delete role |
| POST | /api/v1/apikeys | Yes | Generate API key |
| GET | /api/v1/apikeys/{id} | Yes | Get API key info |
| POST | /api/v1/apikeys/{id}/revoke | Yes | Revoke API key |
| DELETE | /api/v1/apikeys/{id} | Yes | Delete API key |
Include a JWT token in requests:
Authorization: Bearer <token>
The JWT token must contain:
sub: User UUIDtenant_id: Tenant (Organization) UUIDrole: User's role
┌─────────────────────────────────────┐
│ HTTP Request │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ JwtAuthenticationFilter │
│ (extracts JWT, sets TenantContext) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ TenantFilterInterceptor │
│ (enables Hibernate tenantFilter) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Controllers │
│ (OrganizationController, etc.) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Services │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Repositories (JPA) │
│ (auto-filtered by tenantId) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ PostgreSQL │
└─────────────────────────────────────┘
All tenant-scoped entities (User, Role, ApiKey) are protected by a Hibernate Filter named tenantFilter. The filter is enabled per-request using the tenantId extracted from the JWT token.