A production-ready RESTful API for an Event Management Platform built with Spring Boot 3.3.0, featuring secure access, comprehensive filtering capabilities, and scalable architecture.
π Table of Contents
- Project Overview
- Features
- Architecture
- Database Schema
- API Endpoints
- Folder Structure
- Key Code Files
- Exception Handling
- Dependencies
- Setup & Installation
- Configuration
- Security
- Performance Features
- Testing
- Monitoring & Health Checks
- Deployment
- API Documentation
- Troubleshooting
- Contributing
- License
The Event Management System is a comprehensive backend solution designed to handle all aspects of event planning and management. This system provides a robust RESTful API that enables users to create, manage, and attend events with full authentication and authorization capabilities.
- Scalable Architecture: Built with Spring Boot 3.x and modern design patterns
- Security First: JWT-based authentication with role-based access control
- Performance Optimized: Caching, pagination, and database optimizations
- Production Ready: Comprehensive testing, monitoring, and deployment configurations
- Enterprise Grade: Soft deletes, audit trails, and advanced filtering capabilities
- Streamlines event management workflows
- Provides secure multi-tenant event hosting
- Enables real-time attendance tracking
- Supports complex event filtering and search
- Offers comprehensive administrative controls
- User Management: Registration, authentication, and role-based access control
- Event Management: Create, update, delete, and manage events with advanced filtering
- Attendance Tracking: RSVP system with status tracking (
GOING,MAYBE,DECLINED) - Security: JWT-based authentication with role-based authorization
- Soft Deletes: Archive entities instead of permanent deletion
- Caching: Caffeine cache for improved performance
- Rate Limiting: Request throttling per user/IP using Bucket4j
- Pagination & Filtering: Advanced search and sorting capabilities
- Audit Trail: Automatic tracking of creation and modification timestamps
- Database Migrations: Flyway for version-controlled schema management
- Java 17
- Spring Boot 3.3.0
- Spring Security 6 with JWT
- Spring Data JPA with Hibernate
- PostgreSQL
- Maven
- Caffeine Caching
- MapStruct
- Flyway
- Layered Architecture (
Controller β Service β Repository) - Repository Pattern with Spring Data JPA
- Builder Pattern for complex object creation
- Strategy Pattern for filtering mechanisms
- Factory Pattern for user principal creation
Core Entities
User
CREATE TABLE users (
id UUID PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role VARCHAR(20) NOT NULL DEFAULT 'USER',
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP,
deleted_at TIMESTAMP
);Event
CREATE TABLE events (
id UUID PRIMARY KEY,
title VARCHAR(200) NOT NULL,
description TEXT,
host_id UUID NOT NULL REFERENCES users(id),
start_time TIMESTAMP NOT NULL,
end_time TIMESTAMP NOT NULL,
location VARCHAR(500) NOT NULL,
visibility VARCHAR(20) NOT NULL DEFAULT 'PUBLIC',
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP,
deleted_at TIMESTAMP
);
Attendance
sql
CREATE TABLE attendance (
event_id UUID NOT NULL REFERENCES events(id),
user_id UUID NOT NULL REFERENCES users(id),
status VARCHAR(20) NOT NULL DEFAULT 'GOING',
responded_at TIMESTAMP NOT NULL,
deleted_at TIMESTAMP,
PRIMARY KEY (event_id, user_id)
);| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/register | User registration | No |
| POST | /api/auth/login | User login | No |
| POST | /api/auth/logout | User logout | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/events | Create event | Yes (USER/ADMIN) |
| GET | /api/events | List events with filters | No |
| GET | /api/events/{id} | Get event details | No |
| PUT | /api/events/{id} | Update event | Yes (Host/ADMIN) |
| DELETE | /api/events/{id} | Delete event | Yes (Host/ADMIN) |
| GET | /api/events/upcoming | Get upcoming events | No |
| GET | /api/events/my-events | Get user's hosted events | Yes |
| GET | /api/events/attending | Get user's attending events | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/events/attendance | Update attendance status | Yes |
| GET | /api/events/{id}/attendance-status | Get user's attendance status | Yes |
Users
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/users/me | Get current user profile | Yes |
| GET | /api/users | Get all users | Yes (ADMIN) |
| GET | /api/users/{id} | Get user by ID | Yes (ADMIN) |
| DELETE | /api/users/{id} | Deactivate user | Yes (ADMIN) |
event-management-system/
βββ src/
β βββ main/
β β βββ java/com/eventmanagement/
β β β βββ config/ # Application configuration classes
β β β β βββ AuditorAwareConfig.java
β β β β βββ CacheConfig.java
β β β β βββ HibernateConfig.java
β β β β βββ JpaAuditingConfig.java
β β β β βββ JpaConfig.java
β β β β βββ JwtConfig.java
β β β β βββ MethodSecurityConfig.java
β β β β βββ RateLimitConfig.java
β β β β βββ SecurityConfig.java
β β β β βββ SoftDeleteFilterConfig.java
β β β βββ controller/ # REST API controllers
β β β β βββ AuthController.java
β β β β βββ EventController.java
β β β β βββ UserController.java
β β β βββ dto/ # Data Transfer Objects (request/response)
β β β β βββ request/
β β β β β βββ AttendanceRequest.java
β β β β β βββ CreateEventRequest.java
β β β β β βββ LoginRequest.java
β β β β β βββ RegisterRequest.java
β β β β β βββ UpdateEventRequest.java
β β β β βββ response/
β β β β Β Β βββ AuthResponse.java
β β β β Β Β βββ EventDetailResponse.java
β β β β Β Β βββ EventResponse.java
β β β β Β Β βββ EventWithAttendeeCountResponse.java
β β β β Β Β βββ PagedResponse.java
β β β β Β Β βββ UserResponse.java
β β β βββ entity/ # JPA entities (database models)
β β β β βββ Attendance.java
β β β β βββ AttendanceId.java
β β β β βββ BaseEntity.java
β β β β βββ Event.java
β β β β βββ User.java
β β β βββ enums/ # Enumeration classes
β β β β βββ AttendanceStatus.java
β β β β βββ Role.java
β β β β βββ Visibility.java
β β β βββ exception/ # Custom exceptions and global handler
β β β β βββ BadRequestException.java
β β β β βββ GlobalExceptionHandler.java
β β β β βββ ResourceNotFoundException.java
β β β β βββ UnauthorizedException.java
β β β βββ mapper/ # MapStruct interfaces for DTO-entity mapping
β β β β βββ EventMapper.java
β β β β βββ UserMapper.java
β β β βββ repository/ # Spring Data JPA repositories
β β β β βββ AttendanceRepository.java
β β β β βββ EventRepository.java
β β β β βββ UserRepository.java
β β β βββ security/ # Security components (JWT, UserDetails)
β β β β βββ CustomUserDetailsService.java
β β β β βββ JwtAuthenticationEntryPoint.java
β β β β βββ JwtAuthenticationFilter.java
β β β β βββ JwtTokenProvider.java
β β β β βββ UserPrincipal.java
β β β βββ service/ # Business logic interfaces
β β β β βββ impl/
β β β β β βββ AuthServiceImpl.java
β β β β β βββ EventServiceImpl.java
β β β β β βββ UserServiceImpl.java
β β β β βββ AttendanceService.java
β β β β βββ AuthService.java
β β β β βββ EventService.java
β β β β βββ FilterService.java
β β β β βββ SoftDeleteService.java
β β β β βββ UserService.java
β β β βββ util/ # Utility classes
β β β β βββ DateUtils.java
β β β β βββ ValidationUtils.java
β β β βββ EventManagementApplication.java # Main Spring Boot application class
β β βββ resources/
β β Β Β βββ application.yml
β β Β Β βββ application-dev.yml
β β Β Β βββ application-prod.yml
β β Β Β βββ db/migration/ # Flyway database migration scripts
β β Β Β Β Β βββ V1__Create_users_table.sql
β β Β Β Β Β βββ V2__Create_events_table.sql
β β Β Β Β Β βββ V3__Create_attendance_table.sql
β βββ test/
β Β Β βββ java/com/eventmanagement/
β Β Β β βββ config/ # Test-specific configurations
β Β Β β β βββ BaseWebMvcTest.java
β Β Β β β βββ TestJpaAuditingConfig.java
β Β Β β β βββ TestJpaConfig.java
β Β Β β β βββ TestMethodSecurityConfig.java
β Β Β β β βββ TestSecurityBeans.java
β Β Β β β βββ TestSecurityConfig.java
β Β Β β βββ controller/ # Unit tests for controllers
β Β Β β β βββ AuthControllerTest.java
β Β Β β β βββ EventControllerTest.java
β Β Β β β βββ UserControllerTest.java
β Β Β β βββ integration/ # Integration tests
β Β Β β β βββ EventManagementIntegrationTest.java
β Β Β β βββ repository/ # Unit tests for repositories
β Β Β β β βββ AttendanceRepositoryTest.java
β Β Β β β βββ BaseRepositoryTest.java
β Β Β β β βββ EventRepositoryTest.java
β Β Β β β βββ UserRepositoryTest.java
β Β Β β βββ security/ # Unit tests for security components
β Β Β β β βββ JwtTokenProviderTest.java
β Β Β β βββ service/ # Unit tests for services
β Β Β β Β Β βββ AuthServiceTest.java
β Β Β β Β Β βββ EventServiceTest.java
β Β Β β Β Β βββ TestFilterService.java
β Β Β β Β Β βββ UserServiceTest.java
β Β Β β βββ util/ # Unit tests for utility classes
β Β Β β Β Β βββ DateUtilsTest.java
β Β Β β Β Β βββ ValidationUtilsTest.java
β Β Β βββ EventManagementApplicationTests.java # Main Spring Boot test class
β Β Β βββ resources/
β Β Β Β Β βββ application-test.yml # Test-specific application properties
βββ target/ # Build output directory
βββ pom.xml # Maven project configuration
βββ README.md # Project documentation
βββ .gitignore # Git ignore rules
Location: src/main/java/com/eventmanagement/controller/EventController.java
The main REST controller handling all event-related operations. This file demonstrates:
- RESTful API design with proper HTTP methods and status codes
- Method-level security with
@PreAuthorizeannotations - Request validation using
@Validannotations - Pagination and filtering support
- Comprehensive CRUD operations
Key Features:
- Event creation, updating, and deletion with authorization checks
- Advanced filtering by date, location, visibility, and host
- Pagination support for large datasets
- Attendance management integration
Location: src/main/java/com/eventmanagement/service/impl/EventServiceImpl.java
The core business logic implementation for event management. This file showcases:
- Clean separation of concerns between controller and business logic
- Caching strategies with
@Cacheableand@CacheEvict - Soft delete implementation
- Complex business rule validation
- Transaction management
Key Features:
- Event validation (future dates, end time after start time)
- Permission checking (host or admin only for modifications)
- Soft delete filter management
- Attendance statistics calculation
- Cache management for performance optimization
Location: src/main/java/com/eventmanagement/config/SecurityConfig.java
Comprehensive security configuration demonstrating:
- JWT-based authentication setup
- Role-based access control configuration
- CORS policy management
- Security filter chain configuration
- Password encoding setup
Key Features:
- Stateless session management
- Custom JWT authentication filter
- Public and protected endpoint configuration
- Security exception handling
Location: src/main/java/com/eventmanagement/exception/GlobalExceptionHandler.java
Centralized exception handling showcasing:
- Global exception handling with
@RestControllerAdvice - Custom exception types for different error scenarios
- Proper HTTP status code mapping
- Validation error handling with field-specific messages
- Structured error response format
Key Features:
- Resource not found handling (404)
- Validation error handling (400)
- Authorization error handling (401/403)
- UUID format validation
- Generic exception fallback
Location: src/test/java/com/eventmanagement/integration/EventManagementIntegrationTest.java
Comprehensive integration testing demonstrating:
- End-to-end API testing with RestAssured
- Authentication flow testing
- All CRUD operations testing
- Exception scenario testing
- Security testing for different user roles
Key Features:
- Complete test coverage for all endpoints
- Authentication and authorization testing
- Validation error testing
- Status code verification
- Response body validation
The Event Management System implements a comprehensive exception handling strategy that ensures robust error management and meaningful error responses to clients.
The system defines specific exception types for different error scenarios:
// Base custom exceptions
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
public ResourceNotFoundException(String resourceName, String fieldName, Object fieldValue) {
super(String.format("%s not found with %s: '%s'", resourceName, fieldName, fieldValue));
}
}
public class BadRequestException extends RuntimeException {
public BadRequestException(String message) {
super(message);
}
}
public class UnauthorizedException extends RuntimeException {
public UnauthorizedException(String message) {
super(message);
}
}The GlobalExceptionHandler class provides centralized exception handling using @RestControllerAdvice:
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
// Handle resource not found (404)
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(
ResourceNotFoundException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
"Resource Not Found",
ex.getMessage(),
request.getDescription(false).replace("uri=", ""),
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
// Handle bad requests (400)
@ExceptionHandler(BadRequestException.class)
public ResponseEntity<ErrorResponse> handleBadRequestException(
BadRequestException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
"Bad Request",
ex.getMessage(),
request.getDescription(false).replace("uri=", ""),
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
// Handle unauthorized access (401)
@ExceptionHandler(UnauthorizedException.class)
public ResponseEntity<ErrorResponse> handleUnauthorizedException(
UnauthorizedException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.UNAUTHORIZED.value(),
"Unauthorized",
ex.getMessage(),
request.getDescription(false).replace("uri=", ""),
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.UNAUTHORIZED);
}
// Handle access denied (403)
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<ErrorResponse> handleAccessDeniedException(
AccessDeniedException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.FORBIDDEN.value(),
"Access Denied",
"You don't have permission to access this resource",
request.getDescription(false).replace("uri=", ""),
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.FORBIDDEN);
}
// Handle validation errors (400)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
// Handle invalid UUID format (400)
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<ErrorResponse> handleTypeMismatch(
MethodArgumentTypeMismatchException ex, WebRequest request) {
if (ex.getRequiredType() == java.util.UUID.class) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
"Bad Request",
"Invalid UUID format",
request.getDescription(false).replace("uri=", ""),
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
return handleGlobalException(ex, request);
}
// Handle all other exceptions (500)
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(
Exception ex, WebRequest request) {
logger.error("Unexpected error occurred", ex);
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"Internal Server Error",
"An unexpected error occurred",
request.getDescription(false).replace("uri=", ""),
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}The system uses a standardized error response format:
public static class ErrorResponse {
private int status;
private String error;
private String message;
private String path;
private LocalDateTime timestamp;
// Constructors, getters, and setters
}- Validation Errors (400 Bad Request)
- Trigger: Invalid request data (empty fields, invalid email format, etc.)
- Response: Field-specific validation error messages
Example:
{
"name": "Name cannot be blank",
"email": "Email should be valid",
"password": "Password must be at least 8 characters"
}- Resource Not Found (404 Not Found)
- Trigger: Requesting non-existent resources
- Response: Structured error with resource details
Example:
{
"status": 404,
"error": "Resource Not Found",
"message": "Event not found with id: '123e4567-e89b-12d3-a456-426614174000'",
"path": "/api/events/123e4567-e89b-12d3-a456-426614174000",
"timestamp": "2024-01-15T10:30:00"
}- Unauthorized Access (401 Unauthorized)
- Trigger: Missing or invalid JWT token
- Response: Unauthorized error message
Example:
{
"status": 401,
"error": "Unauthorized",
"message": "JWT token is expired or invalid",
"path": "/api/events",
"timestamp": "2024-01-15T10:30:00"
}- Forbidden Access (403 Forbidden)
- Trigger: Insufficient permissions for the requested operation
- Response: Access denied message
Example:
{
"status": 403,
"error": "Access Denied",
"message": "You don't have permission to access this resource",
"path": "/api/users",
"timestamp": "2024-01-15T10:30:00"
}- Business Logic Errors (400 Bad Request)
- Trigger: Business rule violations (e.g., event start time in the past)
- Response: Descriptive business error message
Example:
{
"status": 400,
"error": "Bad Request",
"message": "Event start time must be in the future",
"path": "/api/events",
"timestamp": "2024-01-15T10:30:00"
}- Invalid UUID Format (400 Bad Request)
- Trigger: Malformed UUID in path parameters
- Response: UUID format error message
Example:
{
"status": 400,
"error": "Bad Request",
"message": "Invalid UUID format",
"path": "/api/events/invalid-uuid",
"timestamp": "2024-01-15T10:30:00"
}The system includes comprehensive exception testing in integration tests:
@Test
void shouldReturnBadRequestForInvalidRegister() throws Exception {
RegisterRequest registerRequest = new RegisterRequest();
registerRequest.setName(""); // Invalid name
registerRequest.setEmail("bademail"); // Invalid email
registerRequest.setPassword("123"); // Invalid password
given()
.contentType(ContentType.JSON)
.body(objectMapper.writeValueAsString(registerRequest))
.when()
.post("/api/auth/register")
.then()
.statusCode(400)
.body("name", notNullValue())
.body("email", notNullValue())
.body("password", notNullValue());
}
@Test
void shouldReturnNotFoundForNonExistentEvent() {
given()
.header("Authorization", "Bearer " + userToken)
.when()
.get("/api/events/" + UUID.randomUUID())
.then()
.statusCode(404)
.body("error", equalTo("Resource Not Found"));
}
@Test
void shouldReturnForbiddenForUserAccessingAdminEndpoints() {
given()
.header("Authorization", "Bearer " + userToken)
.when()
.get("/api/users")
.then()
.statusCode(403);
}- Consistent Error Responses: All errors follow the same structure
- Meaningful Error Messages: Clear, actionable error descriptions
- Proper HTTP Status Codes: Correct status codes for different error types
- Security: No sensitive information leaked in error messages
- Debugging Support: Comprehensive logging for internal errors
- Client-Friendly: Structured responses that frontend applications can easily parse
- Comprehensive Coverage: Handles all common error scenarios
This exception handling approach ensures that the API provides clear, consistent, and helpful error responses while maintaining security and system stability.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency><!-- PostgreSQL Driver -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Flyway Migration -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<!-- H2 Database for Testing -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency><!-- JWT Support -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency><!-- Caffeine Cache -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<!-- Rate Limiting -->
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
<version>7.6.0</version>
</dependency><!-- MapStruct for DTO Mapping -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
<scope>provided</scope>
</dependency><!-- Spring Boot Test Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Security Test -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- RestAssured for Integration Testing -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<!-- Testcontainers for Database Testing -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency><build>
<plugins>
<!-- Spring Boot Maven Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Maven Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<!-- Surefire Plugin for Testing -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<!-- JaCoCo for Code Coverage -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
</plugin>
</plugins>
</build>- Java 17 or higher
- PostgreSQL 12+
- Maven 3.6+
export DB_USERNAME=your_db_username
export DB_PASSWORD=your_db_password
export DATABASE_URL=jdbc:postgresql://localhost:5432/event_management_dev
export JWT_SECRET=your_jwt_secret_key_minimum_256_bits-- Create database
CREATE DATABASE event_management_dev;
-- Create user (optional)
CREATE USER event_user WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE event_management_dev TO event_user;- Clone the repository
git clone https://github.com/NelushGayashan/Event_Management
cd event-management-system- Install dependencies
./mvnw clean install- Run the application
./mvnw spring-boot:runThe application will start on http://localhost:8080
# Run all tests
./mvnw test
# Run specific test class
./mvnw test -Dtest=EventManagementIntegrationTest
# Run with coverage
./mvnw test jacoco:reportDevelopment (application-dev.yml)
- Detailed logging
- Database DDL auto-update
- Debug mode enabled
- H2 console access
Production (application-prod.yml)
- Optimized logging
- Connection pooling
- SSL requirements
- Performance monitoring
Test (application-test.yml)
- H2 in-memory database
- JPA auditing enabled
- Hardcoded JWT secret
# JWT Configuration
jwt:
secret: ${JWT_SECRET}
expiration: 86400000 # 24 hours
# Database Configuration
spring:
datasource:
url: ${DATABASE_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
# Caching Configuration
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=1000,expireAfterWrite=10m
- User registers/logs in with credentials
- Server validates credentials and generates JWT token
- Client includes JWT token in
Authorization: Bearer <token>header - Server validates token for protected endpoints
- USER: Can create events, manage own events, update attendance
- ADMIN: Full access to all resources, user management
- Password encryption using BCrypt
- JWT token validation and blacklisting
- Method-level security with
@PreAuthorize - CORS configuration for frontend integration
- Request rate limiting
@Cacheable(value = "events", key = "#eventId + '_' + #userId")
public EventDetailResponse getEventDetails(UUID eventId, UUID userId) {
// Implementation
}
@CacheEvict(value = "events", allEntries = true)
public EventResponse createEvent(CreateEventRequest request, UUID userId) {
// Implementation
}- Proper indexing on frequently queried columns
- Lazy loading for entity relationships
- Connection pooling with HikariCP
- Query optimization with custom JPQL
@Filter(name = "softDeleteFilter", condition = "(:isDeleted = false and deleted_at IS NULL)")
public class BaseEntity {
@Column(name = "deleted_at")
private LocalDateTime deletedAt;
public void softDelete() {
this.deletedAt = LocalDateTime.now();
}
}- Unit Tests: Controller, Service, and Repository layers
- Integration Tests: End-to-end API testing with RestAssured
- Security Tests: Authentication and authorization scenarios
- Exception Handling Tests: Global exception handler coverage
src/test/java/
βββ controller/ # Controller unit tests
βββ service/ # Service layer tests
βββ repository/ # Repository tests with H2
βββ integration/ # Full integration tests
βββ config/ # Test configuration
@Test
void shouldCreateEventSuccessfully() throws Exception {
CreateEventRequest createRequest = new CreateEventRequest();
createRequest.setTitle("Integration Test Event");
// ... set other fields
given()
.contentType(ContentType.JSON)
.header("Authorization", "Bearer " + userToken)
.body(objectMapper.writeValueAsString(createRequest))
.when()
.post("/api/events")
.then()
.statusCode(201)
.body("title", equalTo("Integration Test Event"));
}/actuator/health- Application health status/actuator/info- Application information/actuator/metrics- Application metrics
logging:
level:
com.eventmanagement: INFO
org.springframework.security: WARN
file:
name: logs/event-management.log
max-size: 100MB
max-history: 30
Environment-Specific Deployment
# Development
./mvnw spring-boot:run -Dspring.profiles.active=dev
# Production
java -jar target/event-management-system-*.jar --spring.profiles.active=prod- Create Event
curl -X POST http://localhost:8080/api/events \
-H "Authorization: Bearer <jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"title": "Tech Conference 2024",
"description": "Annual technology conference",
"startTime": "2024-06-15T09:00:00",
"endTime": "2024-06-15T17:00:00",
"location": "Convention Center",
"visibility": "PUBLIC"
}'- Filter Events
curl "http://localhost:8080/api/events?location=Convention&startDate=2024-06-01T00:00:00&visibility=PUBLIC&page=0&size=10"- JWT Token Issues
Error: 401 Unauthorized
Solution: Ensure JWT_SECRET environment variable is set and token is valid
- Database Connection Issues
Error: Connection refused
Solution: Verify PostgreSQL is running and credentials are correct
- Soft Delete Filter Issues
Error: Deleted entities still appearing
Solution: Ensure FilterService.enableSoftDeleteFilter() is called
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Java naming conventions
- Write comprehensive tests for new features
- Update documentation for API changes
- Ensure all tests pass before submitting PR
This project is licensed under the MIT License - see the LICENSE file for details.
Nelush Gayashan - https://github.com/NelushGayashan
- Spring Boot team for the excellent framework
- Hibernate team for ORM capabilities
- JWT.io for token standards
- All contributors who helped improve this project
Built with β€οΈ using Spring Boot 3.3.0
