Fall 2025
This document is an exam assignment for 3rd semester Datamatiker students at EK. After submission, the code in the main branch must no longer be changed.
- Allowed resources: written materials, personal computers, laptops, extra monitors, and internet resources. Headphones, and listening to music.
- Prohibited: communication with anyone. So no use of social media, forums, emails, SMS, chatrooms, etc.
- Do not store solutions on external networks or drives/hosts like Facebook, OneDrive, Google Drive, etc. And don’t share your code on Github until the end of the exam.
- Duration: 5 hours.
Upload a document (.txt or .pdf) to Wiseflow with:
- A link to your public GitHub repository. Remember to push your solutions at the very end of the exam. If you push it before that, then make sure the repository is private until hand-in. Do not copy the clone link from GitHub, but grab the link from the browser address bar and paste it into a document and upload to Wiseflow.
The Candidate Matcher Application is a backend system for a recruitment platform helping companies match candidates to relevant skills and technologies. Users can browse, create, update, and delete candidates and skills, view their market insights, and analyze top talent.
The system exposes REST endpoints via Javalin, uses JPA/Hibernate for persistence, integrates with an external Skill Stats API, and includes JWT-based authentication and REST testing.
| Category | Requirement |
|---|---|
| Architecture & Technology | The backend must be built using Java, Javalin, and JPA/Hibernate. |
| Data Persistence | Entities and DAOs must use JPA annotations and connect through a Hibernate configuration. |
| DTO Usage | All REST communication must use DTOs to decouple internal entities from exposed data. |
| API Design | The system must expose RESTful endpoints that conform to standard HTTP methods (GET, POST, PUT, DELETE). |
| Error Handling and Validation | All exceptions must be returned as structured JSON objects with appropriate HTTP status codes. Validation of input must be demonstrated and return meaningful error messages. |
| External Integration | The system must consume an external Skill Stats API to enrich candidates’ skills with market data. |
| Testing | Each REST endpoint must be tested using JUnit and Rest Assured, including data setup and teardown. |
| Security | The system must implement JWT authentication, support role-based access control, and secure all endpoints except login and register. |
| Documentation | The system must include a clear README.md with a status overview of how far you have come, and notes about any important design decisions. |
| Maintainability | Code should be modular, with a clean separation between layers (Controller, DAO, DTO, Entity, Routes). |
| Reliability | Unit and integration tests must be performed for all critical business logic and API endpoints. |
| Data Integrity | Deleting a candidate or skill must handle cascading relationships correctly and safely. |
I want to configure the database connection and entity management using Hibernate
so that the application can persist and retrieve candidate and skill data reliably.
- Each candidate has a name, phone, and education background.
- Each skill has a name, category (enum), and description.
- Each candidate can have many skills, and each skill can belong to many candidates.
Acceptance Criteria
- The system must include entities for
Candidate,Skill, and the join tableCandidateSkill. - The system must initialize with sample data via a Populator class.
Suggested Skill Categories and skills for inspiration:
| Enum value | Example skills | Description |
|---|---|---|
| PROG_LANG | Java, Python, C#, JavaScript | General-purpose programming languages |
| DB | PostgreSQL, MySQL, MongoDB | Databases and data storage technologies |
| DEVOPS | Docker, Kubernetes, GitHub Actions | Tools and practices for deployment, CI/CD, and infrastructure |
| FRONTEND | HTML, CSS, TypeScript, Vue.js | Front-end and UI-related technologies |
| TESTING | JUnit, Cypress, Jest | Tools and frameworks for testing and QA |
| DATA | Pandas, TensorFlow, Power BI | Data science, analytics, and machine learning tools |
| FRAMEWORK | Spring Boot, React, Angular | Application frameworks and libraries |
I want to create, read, update, and delete candidate and skill records through DAOs
so that I can manage data consistently across the application.
Acceptance Criteria
CandidateDAOimplements CRUD and allows linking candidates and skills.SkillDAOimplements basic CRUD as needed.- DTOs are used for all data exchange between layers.
I want to manage candidates using HTTP endpoints
so that I can perform standard CRUD operations and attach skills to candidates.
Acceptance Criteria
GET /candidatesreturns all candidates.GET /candidates/{id}returns candidate details including skills.POST /candidatescreates a candidate.PUT /candidates/{id}updates a candidate.DELETE /candidates/{id}deletes a candidate.PUT /candidates/{candidateId}/skills/{skillId}links an existing skill to a candidate.
I want to view and filter candidates by skill category
so that I can find candidates with specific expertise areas.
Acceptance Criteria
GET /candidates?category={category}filters candidates based on their skills’ category using JPA or streams.
I want to see market insights (popularity and salary) for each candidate’s skills
so that I can assess how valuable their skill set is.
Acceptance Criteria:
- When retrieving a candidate by ID, the response must include enriched skill data fetched from the external Skill Stats API.
- Each skill in the response must include:
popularityScoreandaverageSalary. - If the candidate has no skills, enrichment returns an empty list.
- If a skill is unknown in the external API, it is returned without enrichment data.
The external API is available at
https://apiprovider.cphbusinessapps.dk/api/v1/skills/stats?slugs=java,spring-boot,postgresqlThe API returns a JSON object with market data for each skill in this format:
{
"data": [
{
"id": "0a1",
"slug": "java",
"name": "Java",
"categoryKey": "prog-lang",
"description": "General-purpose, strongly-typed language for backend and Android.",
"popularityScore": 93,
"averageSalary": 120000,
"updatedAt": "2025-10-01T10:15:00.000Z"
},
{
"id": "1a1",
"slug": "spring-boot",
"name": "Spring Boot",
"categoryKey": "framework",
"description": "Java framework for building microservices and REST APIs.",
"popularityScore": 88,
"averageSalary": 115000,
"updatedAt": "2025-10-01T10:15:00.000Z"
},
{
"id": "2a1",
"slug": "postgresql",
"name": "PostgreSQL",
"categoryKey": "db",
"description": "Open-source relational database with strong SQL compliance.",
"popularityScore": 86,
"averageSalary": 130000,
"updatedAt": "2025-10-01T10:15:00.000Z"
}
]
}
Hint: The external API can be called once per candidate, passing multiple slug parameters.
NB: Each skill also has a slug, a short, unique identifier (e.g. “spring-boot”), used to match local skills with data from the external API.
NB: The date format for updatedAt is ZonedDateTime format, e.g. 2025-10-01T10:15:00.000Z.
Jackson might need an extra dependency to handle this format and this custom configuration of the ObjectMapper:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
I want to see the candidate with the highest average popularity score so that I can identify top talent.
Acceptance Criteria
- Endpoint:
GET /reports/candidates/top-by-popularityreturns JSON with the candidate’s ID and average popularity score.
I want automated tests for all REST endpoints so that the application’s functionality is verified and regressions are avoided.
Acceptance Criteria:
- Each endpoint has corresponding unit/integration tests.
- Tests set up mock data and verify JSON responses and status codes.
- Candidate-by-ID tests confirm enrichment data is included.
I want to log in and access protected endpoints using a JWT token so that only authorized users can modify or view sensitive data.
Acceptance Criteria:
POST /loginauthenticates and returns a JWT.- Protected endpoints validate the token and enforce roles.
- Unauthorized requests return
401 Unauthorized. - Tests verify secure access behavior.
| Dimension | Points | What to consider |
|---|---|---|
| REST design & correctness | 20 | Endpoints, Controller, status codes, DTO shapes |
| Data model & JPA mapping | 20 | Relations, cascading, constraints |
| Skill Stats API integration | 15 | Correct call, enrichment logic, inclusion in responses |
| Security (JWT + roles) | 10 | Add roles to endpoints, adjust REST Assured tests to JWT |
| Testing | 20 | Coverage of success & failure paths, isolation |
| Error handling & validation | 10 | Consistent JSON errors, field errors |
| Code quality & README | 5 | Structure, clarity, how-to-run |
| Total | 100 |