Matthew Chhay's Resourcing API using the Spring Boot framework in Java and MySQL.
- Introduction
- Features
- Technologies Used
- Tools Used
- Project Status
- MVP
- Going beyond the MVP
- Setup
- Requirements
- For launching locally and further development
- Issues discovered during development
- Room for Improvement
An API where consumers can create, update, and fetch jobs or temporary workers. Built using Spring Boot, Java and MySQL.
- Fetch all jobs or temps
- Create a job or a temp
- Fetch all jobs assigned to a temp or not
- A relationship with jobs and temps
- Java 17 and Maven Project
- Spring Boot 3.0.1
- Spring Web - build web, including RESTful, applications using Spring MVC
- Spring Boot DevTools - provides fast application restarts, LiveReload, and configurations for enhanced development experience
- Spring Data JPA - Persist data in SQL stores with Java Persistence API using Spring Data and Hibernate
- MySQL Driver - mySQL JDBC and R2DBC driver
- Validation - bean validation with hibernate validator
- MySQL Workbench
- Postman
- Spring Initializr - create a Spring app
- Postman - test endpoints and methods
- Spring Boot Dashboard VS Code Extension
Project is ongoing
Method | URL | Action | Created & works on Postman? |
---|---|---|---|
GET | jobs | Fetch all jobs | ✓ |
GET | jobs/{id} |
Fetch job by {id} |
✓ |
GET | jobs?assigned={true|false} |
Filter jobs by whether a job is assigned to a temp or not | ✓ |
POST | jobs | Create new job | ✓ |
PATCH | jobs/ {id} |
Update job by {id} , e.g. assigning a temp to a job |
✓ |
Method | URL | Action | Created & works on Postman? |
---|---|---|---|
GET | temps | Fetch all temps | ✓ |
GET | temps/{id} |
Fetch temp by {id} |
✓ |
GET | temps/tree | Fetch whole tree of temps | ✗ |
GET | temps?jobId={jobId} |
Fetch temps that are available for a job based on the jobs date range | ✓ |
POST | temps | Create new temp | ✓ |
PATCH | temps | Update temp by {id} , e.g. new name |
✓ |
// GET /jobs/{id}
{
"id": ...,
"name": ...,
"startDate": ...,
"endDate": ...,
"temp": {
"id": ...,
"firstName": ...,
"lastName": ...,
} // temp can also be null if a temp hasn't been assigned to the job
}
// GET /temps/{id}
{
"id": ...,
"firstName": ...,
"lastName": ...,
"jobs": [{
"id": ...,
"name": ...,
"startDate": ...,
"endDate": ...,
}, ...] // can be empty if temp hasn't been assigned to jobs
}
- Temps can only have one job at a time (can’t be doing 2 jobs on the same date)
- Temps can have many jobs, and job can have 1 temp assigned
- Should be able to assign existing temps to jobs via
POST /jobs
&PATCH /jobs/{id}
- Must use a relational database
- Temps should be able to manage other temps (will require an additional field)
- When you request a temp record it should display the reports of that temp
- Should be represented in the database as a nested set
-
GET /temps/tree
- should display the whole tree of temps
- Java 17
- MySQL Server
- Git clone this repo
git@github.com:chhaymatt/resourcing-api.git
- Modify
src/main/resources/application.properties
file with your device's credentials (e.g. different username or password) - Create resourcing database in mysql workbench
create database resourcing;
onlocalhost 3306
- Run
./mvnw spring-boot:run
or from filesrc/main/java/com/matthewchhay/resourcingapi/ResourcingApiApplication.java
- Confirm API returns "Hello World from Job' by using Postman and GET
localhost:9876/jobs/test
Unable to patch a job and console logs/Postman state the method is not supported.
How did I solve it?
- Confirmed the job exists by
GET /jobs/1
- Searched online and discovered how to enable debug in application.properties
logging.level.root=DEBUG
- Saw a post online and someone mentioned about them not passing in the {id}
- Checked the JobController and realised I doubled up on the URL, it was going to
/jobs/jobs/1
instead of/jobs/1
- Removed additional
/jobs
in the@PatchMapping
and error no longer appears
- Patching a job returns the original job instead of the patched payload
How did I solve it?
- Enabled debug mode, noticed JobUpdateDTO and compared file with JobCreateDTO
- Realised missing JobUpdateDTO constructor
- Added JobUpdateDTO constructor and it is working, considering combining both DTOs into one file
API stops working when using a relational database
How did I solve it?
- Attempt 1: Adding
@JsonManagedReference
and@JsonBackReference
to the entities with the relational field stops infinite recursion because jobs references temp and temp also references jobs, however the entity with @JsonBackReference will not appear in the payload - Attempt 2: Adding
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
to both entities allows both fields to appear but not ideal because getting all jobs will show all temps and jobs which is not neat - Attempt 3: Replaced
@JoinColumn(name = "temp")
with@JsonIgnoreProperties(value = { "jobs" })
on the job entity and added@JsonIgnoreProperties(value = { "temp" })
to the temp entity. Issue resolved adopting this annotation/decorator.
- Moved HTTP status from the @Service to the @Controller
- A temp cannot assign themselves, e.g. Ashley -> Ashley
- A temp cannot assign themselves through a different temp, e.g. Ashley -> Matt -> Ashley
- Create Factory Seeder for jobs and temps
- Create E2E tests
- Create Github Action to run tests on every commit