Comprehensive Restaurant Review Platform with modern authentication and search capabilities:
- Restaurant Management: Create, update, delete, and search restaurants with detailed information
- Review System: Users can post, update, and delete reviews with ratings (1-5 stars)
- Photo Uploads: Upload and manage restaurant photos with captions
- Advanced Search: Full-text search with filters (name, cuisine, location, rating range)
- Pagination: Efficient data retrieval with customizable page sizes (1-50 items)
- Sorting: Flexible sorting by date, rating, or relevance
- JWT Authentication: Secure OAuth2 integration with Keycloak
- Role-Based Access Control: Fine-grained permissions for different user roles
- Elasticsearch Integration: High-performance search and analytics
- File Storage: Local file uploads with size limits (5MB max)
- Health Monitoring: Actuator endpoints for system health and metrics
- Java 25 - Latest LTS version with performance improvements
- Spring Boot 4.0 - Enterprise-grade framework
- Spring Security - Comprehensive security framework
- Spring Data Elasticsearch - Search engine integration
- Spring Web MVC - RESTful API development
- Spring Validation - Request validation
- Spring Actuator - Production monitoring
- Keycloak 26.4 - Open-source identity and access management
- OAuth2 Resource Server - JWT token validation
- Spring Security OAuth2 - Authentication integration
- Elasticsearch 9.2 - Distributed search and analytics engine
- H2 Database (for Keycloak) - Embedded database for development
- Maven 3.0 - Dependency management and build tool
- Lombok - Code generation for boilerplate reduction
- MapStruct 1.6 - Type-safe mapping between objects
- Spotless - Code formatting and style enforcement
- SpringDoc OpenAPI 3.0 - OpenAPI 3.0 documentation
- Swagger UI - Interactive API documentation
- Docker Compose - Container orchestration
- Kibana 9.2 - Data visualization for Elasticsearch
critique/
βββ src/
β βββ main/
β β βββ java/com/critique/
β β β βββ configs/ # Configuration classes
β β β βββ controllers/ # REST API endpoints
β β β βββ dtos/ # Data Transfer Objects
β β β β βββ requests/ # Request payloads
β β β β βββ responses/ # Response payloads
β β β βββ entities/ # JPA/Elasticsearch entities
β β β βββ exceptions/ # Custom exception handling
β β β βββ mappers/ # MapStruct mappers
β β β βββ repositories/ # Data access layers
β β β βββ services/ # Business logic
β β β βββ utils/ # Utility classes
β β βββ resources/
β β βββ application.yaml # Configuration properties
β βββ test/ # Unit and integration tests
βββ uploads/ # File upload storage
βββ compose.yaml # Docker Compose configuration
βββ pom.xml # Maven build configuration
βββ README.md # Project documentation- Java 25 or higher
- Maven 3.8+
- Docker and Docker Compose (for local development)
- Minimum 4GB RAM (for Elasticsearch container)
- Ports: 8080 (app), 9200 (Elasticsearch), 5601 (Kibana), 9090 (Keycloak)
git clone https://github.com/nathsagar96/critique.git
cd critiquedocker compose up -dThis will start:
- Elasticsearch (port 9200)
- Kibana (port 5601)
- Keycloak (port 9090)
- Access Keycloak admin console: http://localhost:9090
- Login with credentials:
admin/admin - Create a new realm named
critique - Create roles:
ROLE_USER,ROLE_ADMIN - Create users and assign appropriate roles
# Build the project
./mvnw clean package
# Run the application
./mvnw spring-boot:run- API: http://localhost:8080/api/v1
- Swagger UI: http://localhost:8080/swagger-ui.html
- Actuator: http://localhost:8080/actuator
| Method | Endpoint | Description | Authentication |
|---|---|---|---|
| GET | /restaurants |
Search restaurants with filters | Optional |
| POST | /restaurants |
Create new restaurant | Required |
| GET | /restaurants/{id} |
Get restaurant details | Optional |
| PUT | /restaurants/{id} |
Update restaurant | Required |
| DELETE | /restaurants/{id} |
Delete restaurant | Required |
| GET | /restaurants/{id}/reviews |
Get restaurant reviews | Optional |
| POST | /restaurants/{id}/reviews |
Create review | Required |
| PUT | /restaurants/{id}/reviews/{reviewId} |
Update review | Required |
| DELETE | /restaurants/{id}/reviews/{reviewId} |
Delete review | Required |
| POST | /photos |
Upload photo | Required |
| GET | /photos/{id} |
Get photo data | Optional |
| PATCH | /photos/{id} |
Update photo caption | Required |
| DELETE | /photos/{id} |
Delete photo | Required |
POST /api/v1/restaurants
Content-Type: application/json
Authorization: Bearer {jwt_token}
{
"name": "Gourmet Bistro",
"description": "French cuisine with modern twist",
"cuisineType": "FRENCH",
"address": {
"street": "123 Main St",
"city": "Paris",
"state": "Γle-de-France",
"postalCode": "75001",
"country": "France"
},
"operatingHours": {
"monday": {
"openTime": "18:00:00",
"closeTime": "23:00:00"
}
}
}GET /api/v1/restaurants?name=Bistro&cuisineType=FRENCH&minRating=4&page=1&size=10- Issuer URI:
http://localhost:9090/realms/critique - JWK Set URI:
http://localhost:9090/realms/critique/protocol/openid-connect/certs - Token Format: JWT with OAuth2 Bearer tokens
- Roles Claim:
rolesclaim in JWT, prefixed withROLE_
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:9090/realms/critique
jwk-set-uri: http://localhost:9090/realms/critique/protocol/openid-connect/certs- Obtain token from Keycloak:
POST /realms/critique/protocol/openid-connect/token - Include in requests:
Authorization: Bearer {token} - Token validation: Automatic JWT validation with Spring Security
- CORS: Configured for frontend domains (
http://localhost:3000,http://localhost:8080) - CSRF Protection: Disabled for stateless API
- Public Endpoints: Swagger UI, health checks, and read-only operations
| Parameter | Type | Description | Example |
|---|---|---|---|
name |
String | Restaurant name (partial match) | name=Bistro |
cuisineType |
Enum | Cuisine type filter | cuisineType=ITALIAN |
location |
String | City or area | location=Paris |
minRating |
Number | Minimum rating (1-5) | minRating=4 |
maxRating |
Number | Maximum rating (1-5) | maxRating=5 |
page |
Integer | Page number (1-based) | page=2 |
size |
Integer | Items per page (1-50) | size=10 |
sort |
String | Sort criteria | sort=rating,desc |
- Elasticsearch Indexing: Real-time indexing for instant search results
- Pagination: Efficient cursor-based pagination
- Caching: Response caching for frequent queries
- Query Optimization: Analyzed fields for full-text search
| Variable | Description | Default |
|---|---|---|
ELASTICSEARCH_URIS |
Elasticsearch cluster URI | http://localhost:9200 |
ELASTICSEARCH_USERNAME |
Elasticsearch username | - |
ELASTICSEARCH_PASSWORD |
Elasticsearch password | - |
KEYCLOAK_ISSUER_URI |
Keycloak issuer URI | http://localhost:9090/realms/critique |
KEYCLOAK_JWK_SET_URI |
Keycloak JWK set URI | http://localhost:9090/realms/critique/protocol/openid-connect/certs |
- Development:
application.yaml(default) - Production:
application-prod.yaml(activated withprodprofile)
# Development (default)
./mvnw spring-boot:run
# Production
./mvnw spring-boot:run -Dspring.profiles.active=prod- Ownership: Only restaurant owners can update/delete their restaurants
- Validation: Required fields: name, address, operating hours
- Rating Calculation: Average of all reviews (1-5 stars)
- Single Review: One review per user per restaurant
- Rating Range: 1-5 stars (integer values only)
- Edit Window: Reviews can be edited within 24 hours
- Deletion: Only review authors or admins can delete
- File Types: JPEG, PNG, GIF
- Max Size: 5MB per file
- Content Types: Automatic detection from file headers
- Storage: Local filesystem with unique filenames
- JUnit 5 - Unit testing
- Mockito - Mocking framework
- Spring Boot Test - Integration testing
- Testcontainers - Containerized testing (Elasticsearch)
# Unit tests
./mvnw test
# Integration tests
./mvnw verify
# Specific test class
./mvnw test -Dtest=RestaurantControllerTest- Branch Naming:
feature/,bugfix/,docs/prefixes - Commit Messages: Follow Conventional Commits
- Pull Requests: Reference issue numbers, include screenshots for UI changes
# Create feature branch
git checkout -b feature/new-search-filter
# Commit changes
git commit -m "feat: add cuisine type filter to search"
# Push and create PR
git push origin feature/new-search-filter- Formatting: Spotless with Palantir Java format
- Imports: Organized, no wildcards
- Documentation: Javadoc for public APIs
MIT License Β© 2026 Critique
- Permissions: Commercial use, modification, distribution
- Limitations: Liability, warranty
- Conditions: License and copyright notice
graph TD
A[Client] -->|HTTP Requests| B[Spring Boot App]
B -->|JWT Validation| C[Keycloak]
B -->|Data Operations| D[Elasticsearch]
D -->|Visualization| E[Kibana]
B -->|File Storage| F[Local Filesystem]
B -->|Monitoring| G[Actuator Endpoints]