TP3.2 — Complete CRUD Application (Autonomous Mode)
This TP is exactly the same assignment as TP3.1, but without any provided code. You must do everything yourself. If you're stuck, refer to TP3.1 as a reference.
Estimated duration: 2h to 3h
Prerequisites: Understanding of Module 3 concepts (layered architecture, Spring Data JPA, REST API)
Context
You are a backend developer in a school. You are asked to create a student management REST API with Spring Boot.
What you need to deliver
Step 1 — Create the Spring Boot project
- Create a new Spring Boot project via Spring Initializr
- Choose the necessary dependencies for:
- Creating a REST API
- Using an in-memory database (H2)
- JPA persistence
- Validating input data
Step 2 — Create the Student entity
Create a Student entity with the following fields:
| Field | Type | Constraints |
|---|---|---|
| id | Long | Primary key, auto-generated |
| firstName | String | Required, between 2 and 50 characters |
| lastName | String | Required, between 2 and 50 characters |
| String | Required, valid email format, unique | |
| age | Integer | Required, between 18 and 100 |
| program | String | Required (e.g., "Computer Science", "Software Engineering") |
Step 3 — Create the Repository
- Create a Repository interface for the
Studententity - Add a method to check if an email already exists
- Add a method to search students by program
Step 4 — Create the Service
Create a Service that implements the following business logic:
- Retrieve all students
- Retrieve a student by ID — if the student does not exist, throw an appropriate exception
- Create a student — check that the email is not already used before saving. If the email already exists, return a 409 (Conflict) error
- Update a student — check that the student exists, then update their information
- Delete a student — check that the student exists, then delete them
Step 5 — Create the REST Controller
Create a Controller that exposes the following endpoints:
| HTTP Method | URL | Action | Expected Return Code |
|---|---|---|---|
| GET | /api/students | List all students | 200 OK |
| GET | /api/students/\{id\} | Student details | 200 OK or 404 Not Found |
| POST | /api/students | Create a student | 201 Created or 409 Conflict |
| PUT | /api/students/\{id\} | Update a student | 200 OK or 404 Not Found |
| DELETE | /api/students/\{id\} | Delete a student | 204 No Content or 404 Not Found |
- Data sent in POST and PUT must be automatically validated
- If validation fails, return a 400 Bad Request code
Step 6 — Configure the H2 database
- Configure the application to use an in-memory H2 database
- Enable the H2 console to view data in the browser
- The console should be accessible at the URL
/h2-console
Step 7 — Test all endpoints
Test your API with Postman (or an equivalent tool). You must perform and capture the following tests:
- Create 3 students (POST) — check for code 201
- List all students (GET) — verify there are 3
- Retrieve a student by ID (GET) — verify the data
- Update a student (PUT) — change their program, verify the update
- Delete a student (DELETE) — check for code 204
- Relist all students — verify only 2 remain
- Test errors:
- GET on a non-existent ID → 404
- POST with an already used email → 409
- POST with an invalid email → 400
- POST with an empty first name → 400
Bonus exercises
Bonus 1 — Search by program
Add an endpoint to search students by program:
GET /api/students/program/{program}
For example: GET /api/students/program/Computer Science returns all students in Computer Science.
Bonus 2 — Statistics
Add an endpoint that returns statistics:
GET /api/students/stats
The returned JSON should contain:
- The total number of students
- The average age
- The number of students per program
Bonus 3 — Pagination
Modify the GET /api/students endpoint to support pagination:
GET /api/students?page=0&size=10&sort=lastName
Bonus 4 — Centralized error handling
Create a global exception handler that:
- Returns clear error messages in JSON
- Handles cases: student not found (404), duplicate email (409), validation failed (400)
Expected error response format:
{
"status": 404,
"message": "Student not found with ID: 99",
"timestamp": "2025-01-15T10:30:00"
}
Bonus 5 — Migration to PostgreSQL
Replace H2 with PostgreSQL:
- Create a
studentdbdatabase in PostgreSQL - Modify the configuration to point to PostgreSQL
- Verify that data persists after restarting the application
Deliverables
| # | Deliverable | Format |
|---|---|---|
| 1 | Complete project source code | Git repository or ZIP |
| 2 | Postman screenshots of the 10 tests (7 + 3 errors) | Images |
| 3 | Screenshot of the H2 console with data | Image |
| 4 | At least 2 completed bonus exercises | Code |
| 5 | Answers to the review questions (below) | Text document |
Review questions
Answer these questions in your own words:
- What is the responsibility of each layer (Controller, Service, Repository)?
- Why do we separate code into distinct layers?
- What is the difference between
@RestControllerand@Service? - How does Spring Data JPA automatically generate SQL queries?
- What HTTP code should be returned after a successful creation? After a deletion?
- Why check the uniqueness of the email in the Service and not just in the database?
- What happens if an invalid JSON is sent to the Controller?
- What is the difference between
findById()that returns anOptionaland a method that directly returns the object?
Evaluation criteria
| Criterion | Points |
|---|---|
| Correctly implemented layered architecture (Controller → Service → Repository) | 20% |
| Student entity with all validations | 15% |
| Repository with custom methods | 10% |
| Service with complete business logic (checks, exceptions) | 20% |
| Controller with 5 functional CRUD endpoints | 20% |
| Successful Postman tests (normal cases + error cases) | 10% |
| Bonus exercises | 5% |
| Total | 100% |
If you're stuck, don't spend more than 15 minutes on a problem. Check TP3.1 to see how it's done, then come back here and try to do it again without looking.