A comprehensive backend REST API built with Spring Boot for managing job postings, applications, and the hiring process. This is a pure backend solution designed to be consumed by any frontend application or API client like Postman.
The project follows a clean layered architecture with clear separation of concerns:
com.talentflow
βββ config # Configuration classes (Security, OpenAPI)
βββ controller # REST API endpoints
βββ dto # Data Transfer Objects (request/response)
β βββ request
β βββ response
βββ entity # JPA entities
βββ enums # Enumeration types
βββ exception # Custom exceptions and global handler
βββ repository # Data access layer
βββ security # JWT authentication and authorization
βββ service # Business logic layer
- Token-based stateless authentication using JWT (JSON Web Tokens)
- BCrypt password hashing for secure password storage
- Role-based access control with three roles:
ADMIN: Full system accessRECRUITER: Can post jobs and manage applicationsCANDIDATE: Can apply for jobs and view own applications
- JWT filter for request authentication
- Stateless sessions (no server-side session storage)
- Role-based endpoint protection
- Secure password encoding with BCrypt
Once the application is running, you can interact with the API directly using Swagger UI:
URL: http://localhost:8080/swagger-ui/index.html
The Swagger UI provides:
- β Complete API documentation
- β Request/response examples
- β Interactive "Try it out" feature to test endpoints
- β JWT authentication support (click "Authorize" button)
- β Real-time API testing without external tools
How to use Swagger UI:
- Navigate to
http://localhost:8080/swagger-ui/index.html - Click the green "Authorize" button
- Paste your JWT token in the
Bearerfield - Click any endpoint to expand it
- Click "Try it out" to test the endpoint
- View request/response details
The login endpoint accepts email and password credentials:
{
"email": "abc@gmail.com",
"password": "password123"
}Response contains:
- β
tokenβ JWT token for authenticated requests - β
emailβ User email - β
roleβ User role (ADMIN, RECRUITER, JOB_SEEKER) - β
fullNameβ User's full name - β
userIdβ User ID in database
Token Usage:
Copy the token and use it in the Authorization header for all protected endpoints:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
This endpoint:
- β Retrieves paginated list of all job postings
- β Supports pagination (page, size parameters)
- β Supports sorting (sortBy, sortDir parameters)
- β No authentication required (public endpoint)
- β Returns real job data from database
Example Response:
{
"success": true,
"data": [
{
"id": 1,
"title": "Senior Java Developer",
"description": "5+ years experience required",
"company": "TechCorp",
"location": "Remote",
"salary": "120000-150000",
"employmentType": "FULL_TIME",
"status": "OPEN"
}
]
}POST /api/auth/register
Content-Type: application/json
{
"fullName": "John Doe",
"email": "john@example.com",
"password": "password123",
"role": "CANDIDATE"
}Response:
{
"success": true,
"message": "User registered successfully",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"email": "john@example.com",
"role": "CANDIDATE",
"fullName": "John Doe",
"userId": 1
},
"timestamp": "2024-01-15T10:30:00"
}POST /api/auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "password123"
}Response: Same structure as register response
POST /api/jobs
Authorization: Bearer {token}
Content-Type: application/json
{
"title": "Senior Java Developer",
"description": "We are looking for an experienced Java developer...",
"location": "New York, NY",
"employmentType": "FULL_TIME",
"requiredSkills": ["Java", "Spring Boot", "MySQL"],
"experienceLevel": "5+ years"
}GET /api/jobs?page=0&size=10&sortBy=createdAt&sortDir=DESCGET /api/jobs/search?skill=Java&location=New York&status=OPEN&page=0&size=10PUT /api/jobs/{id}
Authorization: Bearer {token}
Content-Type: application/json
{
"title": "Updated Job Title",
"description": "Updated description...",
"location": "Remote",
"employmentType": "FULL_TIME",
"requiredSkills": ["Java", "Spring"],
"experienceLevel": "3+ years"
}DELETE /api/jobs/{id}
Authorization: Bearer {token}POST /api/applications/apply/{jobId}
Authorization: Bearer {token}
Content-Type: application/json
{
"resumeLink": "https://example.com/resume.pdf"
}GET /api/applications/my
Authorization: Bearer {token}GET /api/applications/job/{jobId}
Authorization: Bearer {token}PUT /api/applications/{applicationId}/status
Authorization: Bearer {token}
Content-Type: application/json
{
"status": "SHORTLISTED"
}Status values: APPLIED, SHORTLISTED, REJECTED, HIRED
The application uses MySQL database. Update the connection details in application.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/talentflow_db?createDatabaseIfNotExist=true
username: root
password: rootThe application uses JPA with Hibernate's ddl-auto: update, which automatically creates/updates tables based on entities.
Key Tables:
users: User accounts with rolesjobs: Job postingsapplications: Job applicationsjob_skills: Job required skills (collection table)
- User β Job: One-to-Many (One recruiter can post many jobs)
- User β Application: One-to-Many (One candidate can have many applications)
- Job β Application: One-to-Many (One job can have many applications)
- Java 20 (Oracle JDK 20)
- Maven 3.6+
- MySQL 8.0+
- IDE (IntelliJ IDEA, Eclipse, or VS Code)
-
Clone/Download the project
-
Configure MySQL
- Create a MySQL database (or let the app create it automatically)
- Update
application.ymlwith your MySQL credentials:spring: datasource: username: your_username password: your_password
-
Configure JWT Secret (Optional but recommended)
- Update
application.ymlor set environment variable:jwt: secret: your-256-bit-secret-key-minimum-32-characters
- Or set environment variable:
JWT_SECRET=your-secret-key
- Update
-
Build the project
mvn clean install
-
Run the application
mvn spring-boot:run
Or run the
TalentFlowApplicationclass from your IDE. -
Access the API
- Base URL:
http://localhost:8080 - Swagger UI:
http://localhost:8080/swagger-ui.html - API Docs:
http://localhost:8080/api-docs
- Base URL:
The application includes Swagger UI for interactive API documentation:
- URL:
http://localhost:8080/swagger-ui.html - Features:
- Test endpoints directly from the browser
- JWT authentication support
- Complete API documentation with request/response examples
- Register/Login to get a JWT token
- Click the "Authorize" button in Swagger UI
- Enter:
Bearer {your-token} - Now you can test protected endpoints
POST http://localhost:8080/api/auth/register
Content-Type: application/json
{
"fullName": "Jane Recruiter",
"email": "recruiter@example.com",
"password": "password123",
"role": "RECRUITER"
}POST http://localhost:8080/api/auth/login
Content-Type: application/json
{
"email": "recruiter@example.com",
"password": "password123"
}Copy the token from the response.
POST http://localhost:8080/api/jobs
Authorization: Bearer {paste-token-here}
Content-Type: application/json
{
"title": "Full Stack Developer",
"description": "We need a full stack developer with React and Spring Boot experience.",
"location": "San Francisco, CA",
"employmentType": "FULL_TIME",
"requiredSkills": ["React", "Spring Boot", "PostgreSQL"],
"experienceLevel": "3-5 years"
}POST http://localhost:8080/api/auth/register
Content-Type: application/json
{
"fullName": "John Candidate",
"email": "candidate@example.com",
"password": "password123",
"role": "CANDIDATE"
}POST http://localhost:8080/api/applications/apply/1
Authorization: Bearer {candidate-token}
Content-Type: application/json
{
"resumeLink": "https://drive.google.com/resume.pdf"
}GET http://localhost:8080/api/applications/job/1
Authorization: Bearer {recruiter-token}PUT http://localhost:8080/api/applications/1/status
Authorization: Bearer {recruiter-token}
Content-Type: application/json
{
"status": "SHORTLISTED"
}The application includes a global exception handler that returns consistent error responses:
- ResourceNotFoundException β 404 Not Found
- UnauthorizedAccessException β 403 Forbidden
- ValidationException β 400 Bad Request
- BadCredentialsException β 401 Unauthorized
- MethodArgumentNotValidException β 400 Bad Request (with field errors)
Error Response Format:
{
"success": false,
"message": "Error message here",
"data": null,
"timestamp": "2024-01-15T10:30:00"
}All request DTOs are validated using Jakarta Validation:
@NotNull,@NotBlank,@Email,@Size,@Valid- Validation errors are automatically handled and returned with field-level details
Key configurations in application.yml:
- Server Port: 8080
- Database: MySQL with auto-create
- JWT Expiration: 24 hours (86400000 ms)
- Logging: DEBUG level for application, SQL queries visible
JWT_SECRET: Override JWT secret key (default provided but should be changed in production)
- User: Represents users (ADMIN, RECRUITER, CANDIDATE)
- Job: Job postings with skills, location, employment type
- Application: Job applications linking candidates to jobs
- AuthService: Handles registration and authentication
- JobService: Manages job CRUD operations and search
- ApplicationService: Handles application submission and status updates
- JwtTokenProvider: JWT token generation and validation
- CustomUserDetailsService: User details loading for Spring Security
- JwtAuthenticationFilter: Filters requests and validates JWT tokens
- SecurityConfig: Spring Security configuration with role-based access
- Use Swagger UI for interactive testing
- Use Postman with the sample requests above
- Use cURL commands
# Register
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"fullName":"Test User","email":"test@example.com","password":"password123","role":"CANDIDATE"}'
# Login
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"password123"}'- JWT Secret: Change the default JWT secret in production
- Database: Ensure MySQL is running before starting the application
- Port: Default port is 8080, change if needed in
application.yml - CORS: If connecting from a frontend, configure CORS in
SecurityConfig - Password: Minimum 6 characters required
- Email: Must be unique across all users
β
JWT-based authentication
β
Role-based authorization (ADMIN, RECRUITER, CANDIDATE)
β
User registration and login
β
Job CRUD operations with pagination and sorting
β
Job search by skill, location, and status
β
Application submission and management
β
Application status updates
β
Global exception handling
β
Request validation
β
Swagger/OpenAPI documentation
β
Clean layered architecture
β
SOLID principles
β
Proper logging
β
MySQL database with JPA/Hibernate
This project is provided as-is for educational and development purposes.
For issues or questions, please refer to the API documentation at /swagger-ui.html or check the application logs.
Built with Spring Boot 3.2.0 and Java 20



