A production-ready Spring Boot backend that manages employee payroll for full-time and part-time employees β with a fully AI-Powered Onboarding Pipeline that automates email creation, Slack invites, training assignments, payroll configuration, and generates a personalized welcome message using Groq (LLaMA 3.3) whenever a new employee is hired.
π‘ Handles complete employee lifecycle β from onboarding to payroll β with automation, security, and scalability in mind. π Designed as a production-level backend system, not just a CRUD API.
π Swagger UI: https://employeepayroll-app.onrender.com/swagger-ui.html
π Health Check: https://employeepayroll-app.onrender.com/actuator/health
β οΈ Hosted on Render free tier β may take 50 seconds to wake up on first request. Please wait and retry if it doesn't load immediately.
Test credentials:
| Username | Password | Role |
|---|---|---|
admin |
admin123 |
ROLE_ADMIN |
hr |
hr123 |
ROLE_HR |
- π JWT Authentication + Role-Based Access Control (RBAC)
- π€ AI-powered onboarding via Groq LLaMA 3.3 70B
- β‘ Redis caching with smart eviction strategy
- π§± Flyway database migrations (version-controlled schema)
- π‘οΈ Rate limiting with Bucket4j (prevents AI API abuse)
- π Prometheus metrics + Spring Actuator health checks
- ποΈ Soft-delete (no permanent data loss)
- π³ Fully Dockerized (PostgreSQL + Redis + App)
- π§ͺ Unit + Integration testing with Testcontainers + JaCoCo
This project simulates an internal HR system used by companies to:
- Automate employee onboarding workflows end-to-end
- Reduce manual HR operations with a 5-step pipeline
- Ensure consistent payroll configuration for all employee types
- Improve new employee experience using AI-generated welcome messages
Client (Swagger UI / curl / Postman)
β
βΌ
Spring Security (JWT Filter)
β
βΌ
REST Controllers
β
ββββ Redis Cache (GET by ID)
β
ββββ Service Layer
β β
β ββββ PostgreSQL (via JPA + Flyway)
β β
β ββββ Onboarding Pipeline
β β
β ββββ Email Service
β ββββ Slack Service
β ββββ Training Service
β ββββ Payroll Setup Service
β ββββ Groq AI API (WebClient)
β
βΌ
JSON Response (DTO)
Note: This is a modular monolith designed with microservice principles.
| Category | Technology | Details |
|---|---|---|
| Backend | Java 21, Spring Boot 3.3.4 | Core framework |
| Security | Spring Security + JJWT 0.12.6 | JWT stateless auth |
| Database | PostgreSQL + Spring Data JPA | Hibernate ORM |
| Migrations | Flyway | Version-controlled schema |
| Caching | Redis + Spring Cache | Response caching |
| AI | Groq API (LLaMA 3.3 70B) | Welcome message generation |
| HTTP Client | Spring WebFlux WebClient | Async AI API calls |
| Rate Limiting | Bucket4j | 10 req/min on onboard |
| Observability | Spring Actuator + Micrometer + Prometheus | Health + metrics |
| API Docs | SpringDoc OpenAPI (Swagger UI) | Interactive docs |
| Mapping | MapStruct | DTO mapping |
| Boilerplate | Lombok | Clean code |
| Testing | JUnit + Mockito + Testcontainers + JaCoCo | Full test suite |
| Build | Maven | Dependency management |
| Deployment | Docker + Docker Compose + Render | One-command setup |
| Concept | How It's Used |
|---|---|
| Abstraction | Employee is an abstract class with abstract calculateSalary() method |
| Inheritance | FullTimeEmployee and PartTimeEmployee extend Employee |
| Polymorphism | Each subclass overrides calculateSalary() with its own logic |
| Encapsulation | All fields are private with public getters/setters via Lombok |
The entire API is secured with JWT (JSON Web Token) stateless authentication and role-based access control.
| Role | Permissions |
|---|---|
ROLE_ADMIN |
Full access β GET, POST, PUT, DELETE |
ROLE_HR |
Read-only access β GET endpoints only |
| Username | Password | Role |
|---|---|---|
admin |
admin123 |
ROLE_ADMIN |
hr |
hr123 |
ROLE_HR |
β οΈ Change these passwords immediately before going to production!
- Call
POST /api/auth/loginwith your credentials - Receive a signed JWT token in the response
- Pass the token as
Authorization: Bearer <token>on every subsequent request - Tokens are fully stateless β no sessions stored on the server
src/
βββ main/java/com/vikas/
βββ PayrollApplication.java
βββ config/
β βββ SecurityConfig.java # JWT auth, CORS, role-based route protection
β βββ SwaggerConfig.java # Swagger UI + Bearer auth configuration
β βββ DataSeeder.java # Seeds default admin & HR users on startup
βββ controller/
β βββ AuthController.java # POST /api/auth/login
β βββ EmployeeController.java # Employee CRUD + onboarding (rate limited)
βββ service/
β βββ AuthService.java # Login β verifies credentials, issues JWT
β βββ EmployeeService.java # Core CRUD + Redis caching + soft-delete
β βββ OnboardingService.java # Orchestrates the 5-step onboarding pipeline
β βββ AIOnboardingService.java # AI welcome message via Groq API
β βββ EmailService.java # Generates work email address
β βββ SlackService.java # Sends Slack workspace invite
β βββ TrainingService.java # Assigns training modules by designation
β βββ PayrollSetupService.java # Configures payroll (FULLTIME or PARTTIME)
βββ entity/
β βββ Employee.java # Abstract base β soft-delete, audit timestamps
β βββ FullTimeEmployee.java # monthlySalary field
β βββ PartTimeEmployee.java # hoursWorked + hourlyRate fields
β βββ User.java # Login credentials (BCrypt hashed)
βββ security/
β βββ JwtUtil.java # Token generation & validation
β βββ JwtAuthFilter.java # Per-request JWT filter
βββ repository/
β βββ EmployeeRepository.java
β βββ UserRepository.java
βββ dto/
β βββ EmployeeRequestDTO.java
β βββ EmployeeResponseDTO.java
β βββ SalaryResponseDTO.java
β βββ OnboardingResponseDTO.java
β βββ LoginRequestDTO.java
β βββ LoginResponseDTO.java
βββ enums/
β βββ EmployeeType.java # FULLTIME | PARTTIME
βββ exception/
β βββ EmployeeNotFoundException.java
β βββ OnboardingException.java
βββ ExceptionHandler/
βββ GlobalExceptionHandler.java # Handles 400, 401, 403, 404, 429, 500
Schema is version-controlled via V1__init_schema.sql and applied automatically on startup β no manual SQL needed.
| Table | Contents |
|---|---|
employees |
id, name, designation, deleted_at (soft-delete), created_at, updated_at |
fulltime_employees |
monthly_salary |
parttime_employees |
hours_worked, hourly_rate |
users |
username, BCrypt-hashed password, role |
audit_log |
entity_type, action, changed_by, old_value, new_value, changed_at |
Records are never physically deleted. DELETE sets the
deleted_attimestamp (soft-delete).
The app is live on Render (free tier) with PostgreSQL as the database.
| Key | Description |
|---|---|
spring.datasource.url |
PostgreSQL connection URL |
spring.datasource.username |
Database username |
spring.datasource.password |
Database password |
jwt.secret |
Random string, minimum 32 characters |
jwt.expiration-ms |
Token expiry in ms (e.g. 86400000 = 24 hours) |
groq.api.key |
Groq API key from console.groq.com |
spring.cache.type |
Set to none on free tier (no Redis available) |
management.health.redis.enabled |
Set to false on free tier |
β οΈ Free tier instances spin down after inactivity β first request may take 50+ seconds.
- Java 21+
- Maven
- PostgreSQL running locally
- Redis running locally
- Groq API Key β free at console.groq.com
git clone https://github.com/vikas9013/EmployeePayrollSystem.git
cd EmployeePayrollSystemCREATE DATABASE payrolldb;Set these environment variables:
| Variable | Description |
|---|---|
DB_USERNAME |
Your PostgreSQL username |
DB_PASSWORD |
Your PostgreSQL password |
GROQ_API_KEY |
Your Groq API key from console.groq.com |
JWT_SECRET |
A random string, minimum 32 characters |
Windows CMD:
set DB_USERNAME=postgres
set DB_PASSWORD=yourpassword
set GROQ_API_KEY=gsk_your_key_here
set JWT_SECRET=ThisIsASecretKeyThatMustBe32CharsLong!!Mac/Linux:
export DB_USERNAME=postgres
export DB_PASSWORD=yourpassword
export GROQ_API_KEY=gsk_your_key_here
export JWT_SECRET=ThisIsASecretKeyThatMustBe32CharsLong!!mvn spring-boot:runApp starts at: http://localhost:8080
Flyway automatically creates all tables on first startup. No manual SQL needed.
Run the full stack β App + PostgreSQL + Redis β with a single command:
docker-compose up --build| Service | Port |
|---|---|
| App | 8080 |
| PostgreSQL | 5432 |
| Redis | 6379 |
# Stop all services
docker-compose down
# Stop and wipe the database
docker-compose down -vReplace placeholder credentials in
docker-compose.ymlbefore deploying to any environment.
Interactive API documentation β test every endpoint directly in the browser.
| URL | Description |
|---|---|
https://employeepayroll-app.onrender.com/swagger-ui.html |
Live Swagger UI |
https://employeepayroll-app.onrender.com/v3/api-docs |
Live OpenAPI JSON |
http://localhost:8080/swagger-ui.html |
Local Swagger UI |
http://localhost:8080/v3/api-docs |
Local OpenAPI JSON |
- Call
POST /api/auth/loginβ Try it out β Execute - Copy the
tokenfrom the response - Click Authorize π at the top of the page
- Enter
Bearer <your-token>β click Authorize - All subsequent requests will include the token automatically β
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/api/auth/login |
β Public | Login and receive a JWT token |
| Method | Endpoint | Role Required | Description |
|---|---|---|---|
GET |
/api/employees |
ADMIN or HR | Get all employees (paginated) |
GET |
/api/employees/{id} |
ADMIN or HR | Get employee by ID (Redis cached) |
GET |
/api/employees/{id}/salary |
ADMIN or HR | Get calculated salary |
POST |
/api/employees/onboard |
ADMIN only | Add employee + full onboarding pipeline |
PUT |
/api/employees/{id} |
ADMIN only | Update an employee |
DELETE |
/api/employees/{id} |
ADMIN only | Soft-delete an employee |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/actuator/health |
β Public | Application health check |
GET |
/actuator/prometheus |
β Public | Prometheus metrics |
POST /api/auth/login
{
"username": "admin",
"password": "admin123"
}{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"username": "admin",
"role": "ROLE_ADMIN"
}Use as: Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
POST /api/employees/onboard
Authorization: Bearer <your-token>
{
"name": "Vikas Singh Rawat",
"designation": "Software Engineer",
"type": "FULLTIME",
"monthlySalary": 85000,
"hoursWorked": 0,
"hourlyRate": 0
}POST /api/employees/onboard
Authorization: Bearer <your-token>
{
"name": "Rahul Mehta",
"designation": "Intern",
"type": "PARTTIME",
"monthlySalary": 0,
"hoursWorked": 40,
"hourlyRate": 200
}{
"employeeId": 1,
"employeeName": "Vikas Singh Rawat",
"workEmail": "vikas.singh.rawat@company.com",
"slackInviteSent": true,
"trainingAssigned": true,
"payrollConfigured": true,
"message": "Onboarding completed successfully for Vikas Singh Rawat",
"aiOnboardingMessage": "Welcome aboard, Vikas! We are thrilled to have you join our Engineering team."
}GET /api/employees?page=0&size=10&sort=id,asc
Authorization: Bearer <your-token>
- Open
https://employeepayroll-app.onrender.com/swagger-ui.html - Login β copy token β click Authorize π
- Use Try it out on any endpoint
POST /api/auth/loginβ get JWT tokenPOST /api/employees/onboardβ create employee, note theidGET /api/employeesβ confirm employee is listedGET /api/employees/{id}β fetch by id (Redis cached on second call)GET /api/employees/{id}/salaryβ verify salary calculationPUT /api/employees/{id}β update (clears Redis cache)DELETE /api/employees/{id}β soft-delete (clears Redis cache)
:: Login
curl -X POST https://employeepayroll-app.onrender.com/api/auth/login -H "Content-Type: application/json" -d "{\"username\": \"admin\", \"password\": \"admin123\"}"
:: Get all employees
curl -X GET https://employeepayroll-app.onrender.com/api/employees -H "Authorization: Bearer TOKEN"
:: Get by ID
curl -X GET https://employeepayroll-app.onrender.com/api/employees/1 -H "Authorization: Bearer TOKEN"
:: Get salary
curl -X GET https://employeepayroll-app.onrender.com/api/employees/1/salary -H "Authorization: Bearer TOKEN"
:: Onboard full-time
curl -X POST https://employeepayroll-app.onrender.com/api/employees/onboard -H "Content-Type: application/json" -H "Authorization: Bearer TOKEN" -d "{\"name\": \"Vikas\", \"designation\": \"Software Engineer\", \"type\": \"FULLTIME\", \"monthlySalary\": 85000, \"hoursWorked\": 0, \"hourlyRate\": 0}"
:: Onboard part-time
curl -X POST https://employeepayroll-app.onrender.com/api/employees/onboard -H "Content-Type: application/json" -H "Authorization: Bearer TOKEN" -d "{\"name\": \"Rahul\", \"designation\": \"Intern\", \"type\": \"PARTTIME\", \"monthlySalary\": 0, \"hoursWorked\": 40, \"hourlyRate\": 200}"
:: Update
curl -X PUT https://employeepayroll-app.onrender.com/api/employees/1 -H "Content-Type: application/json" -H "Authorization: Bearer TOKEN" -d "{\"name\": \"Vikas Updated\", \"designation\": \"Senior Engineer\", \"type\": \"FULLTIME\", \"monthlySalary\": 95000, \"hoursWorked\": 0, \"hourlyRate\": 0}"
:: Delete
curl -X DELETE https://employeepayroll-app.onrender.com/api/employees/1 -H "Authorization: Bearer TOKEN"When POST /api/employees/onboard is called, 5 steps execute automatically:
New Employee Saved to DB
β
βΌ
1. EmailService β Creates work email (name@company.com)
β
βΌ
2. SlackService β Sends Slack workspace invite
β
βΌ
3. TrainingService β Assigns training modules by designation
β
βΌ
4. PayrollSetupService β Configures payroll (FULLTIME or PARTTIME)
β
βΌ
5. AIOnboardingService β Generates personalized welcome message via Groq AI
β
βΌ
OnboardingResponseDTO returned β
The onboard endpoint is rate-limited to 10 requests per minute to prevent AI API abuse.
| Designation | Modules Assigned |
|---|---|
| Engineer / Developer / SDE | Company Orientation, Secure Coding Practices, Git Workflow |
| Manager / Team Lead | Company Orientation, Leadership Fundamentals, HR Policies |
| HR / Human Resources | Company Orientation, Recruitment Basics, Compliance Training |
| Any other | Company Orientation, Code of Conduct |
| Operation | Cache Behaviour |
|---|---|
GET /api/employees/{id} |
Cached under key employees::{id} |
PUT /api/employees/{id} |
Cache evicted on update |
DELETE /api/employees/{id} |
Cache evicted on delete |
| Feature | Details |
|---|---|
| Health Check | GET /actuator/health β reports UP/DOWN |
| Prometheus Metrics | GET /actuator/prometheus β JVM, HTTP, custom metrics |
| Structured Logging | All controllers & services use @Slf4j with consistent log levels |
# Run all tests
mvn test
# Run tests + generate JaCoCo coverage report
mvn verifyCoverage report: target/site/jacoco/index.html
| Test Class | What It Covers |
|---|---|
EmployeeControllerTest |
Full HTTP layer tests with MockMvc |
EmployeeEntityTest |
OOP inheritance & salary calculation |
OnboardingServiceTest |
Mocked 5-step pipeline |
AIOnboardServiceTest |
Mocked Groq API calls |
ServiceUnitTests |
Core service logic |
PayrollSystemTest |
Integration tests with real PostgreSQL (Testcontainers) |
- Convert into a fully distributed microservices architecture
- Add Kafka / RabbitMQ for event-driven async onboarding
- Integrate real email (SendGrid) and Slack APIs
- Add a React frontend dashboard
- Deploy on AWS with a CI/CD pipeline (GitHub Actions)
- Add refresh token support for longer JWT sessions
This project is actively evolving towards a full production-grade system.
- Never commit
application.propertieswith real credentials β it is in.gitignore - Always use environment variables for
DB_PASSWORD,GROQ_API_KEY, andJWT_SECRET - Use
application.properties.exampleas a safe template for new contributors - Change default admin/HR passwords before any production deployment
- In production, replace
allowedOrigins("*")inSecurityConfigwith your actual frontend URL
Vikas Singh Rawat β Backend Developer | Java | Spring Boot | System Design
π Open to internship and backend development opportunities



