Backend Developer Onboarding Assessment
Purpose
This assessment evaluates your ability to work in a real-world backend codebase using Java + Spring Boot +
PostgreSQL. This is not a theory test. The focus is on clean structure, correct behavior, and practical
decision-making.
Timebox: ~3 hours
Deliverables: Git branch / Pull Request + [Link]
Evaluation focus: Code structure, validation, DB usage, API clarity
Part A – Architecture Warm-up (Written)
Answer briefly (3–5 lines each):
1. What responsibilities belong in Controller, Service, and Repository layers?
2. What is a database transaction? When should @Transactional be used or avoided?
3. Why are DTOs used instead of returning JPA entities directly from APIs?
4. What problem does Liquibase solve in a multi-developer / multi-environment setup?
Part B – Core Implementation Task
Feature Overview
Implement a backend feature that allows storing and retrieving notes for a device. This mirrors real features such as
comments, audit notes, or operational remarks.
1. Database (Liquibase)
Create a Liquibase changelog to add the following table:
Table: device_note
• id – BIGINT, auto-generated primary key
• device_id – BIGINT, NOT NULL
• note – TEXT, NOT NULL (max 1000 chars enforced at API level)
• created_at – TIMESTAMP, default current time
• created_by – VARCHAR(100), NOT NULL
If a device table does not exist in your environment, skip the foreign key and clearly mention this assumption in the README.
2. API Endpoints
Create Note
POST /api/v1/devices/{deviceId}/notes
Required Header: X-User
Request Body:
{ "note": "Device rebooted during maintenance" }
Rules:
• note must not be blank
• max length: 1000 characters
• X-User header is mandatory
List Notes
GET /api/v1/devices/{deviceId}/notes?limit=20
Rules:
• default limit = 20
• limit must be between 1 and 100
• results must be ordered by created_at DESC
3. Service Layer Rules
• Controllers should only handle request/response mapping
• All validation and business rules must live in the service layer
• Repository queries must handle ordering and limits (no in-memory filtering)
• Use transactions only where data consistency is required
4. Error Handling Expectations
• Missing X-User header → HTTP 400 with clear message
• Invalid or blank note → HTTP 400 with reason
• Invalid limit value → HTTP 400
Errors should be predictable and API-consumer friendly.
5. Logging
Add minimal but meaningful logs:
• Controller (INFO): incoming request with deviceId and username
• Service (INFO): successful note creation (noteId, deviceId)
• WARN: validation failures or missing headers