Example Spring Boot REST API application simulating tennis club reservation system.
It uses the following technologies:
- Java 20
- Spring Boot
- Hibernate
- H2 database
- Lombok
- JUnit
- Mockito
mvn clean install
mvn spring-boot:run
mvn spring-boot:run -Dspring-boot.run.arguments=--initialize=TRUE
Runs the app and creates two surfaces and four courts.
The REST API to the example app is described below.
POST /api/courts
{
"name": "Court 1",
"surfaceId": 1
}
{
"id": 1,
"name": "Court 1",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10.0
}
}
GET /api/courts/all
[
{
"id": 1,
"name": "Court 1",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
},
{
"id": 2,
"name": "Court 2",
"surface": {
"id": 2,
"name": "Grass",
"minutePrice": 15
}
}
]
GET /api/courts/id/{id}
{
"id": 1,
"name": "Court 1",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
PUT /api/courts/id/{id}
{
"name": "Court 1",
"surfaceId": 2
}
{
"id": 1,
"name": "Court 1",
"surface": {
"id": 2,
"name": "Grass",
"minutePrice": 15
}
}
PATCH /api/courts/id/{id}
{
"surfaceId": 2
}
{
"id": 1,
"name": "Court 1",
"surface": {
"id": 2,
"name": "Grass",
"minutePrice": 15
}
}
DELETE /api/courts/id/{id}
POST /api/reservations
{
"courtId": 2,
"customerPhoneNumber": "123456789",
"customerName": "John Doe",
"isDoubles": false,
"startsAt": "2023-05-01T10:00:00Z",
"endsAt": "2023-05-01T11:00:00Z"
}
600.0
- price of the reservation
GET /api/reservations/all
[
{
"id": 1,
"doubles": false,
"createdAt": "2023-05-02T23:24:52.779+00:00",
"startsAt": "2023-05-01T10:00:00.000+00:00",
"endsAt": "2023-05-01T11:00:00.000+00:00",
"price": 600.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
}
]
GET /api/reservations/id/{id}
{
"id": 1,
"doubles": false,
"createdAt": "2023-05-02T23:24:52.779+00:00",
"startsAt": "2023-05-01T10:00:00.000+00:00",
"endsAt": "2023-05-01T11:00:00.000+00:00",
"price": 600.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
}
GET /api/reservations/court/{id}
[
{
"id": 1,
"doubles": false,
"createdAt": "2023-05-02T23:24:52.779+00:00",
"startsAt": "2023-05-01T10:00:00.000+00:00",
"endsAt": "2023-05-01T11:00:00.000+00:00",
"price": 600.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
},
{
"id": 2,
"doubles": true,
"createdAt": "2023-05-02T23:30:37.837+00:00",
"startsAt": "2023-05-01T13:00:00.000+00:00",
"endsAt": "2023-05-01T14:00:00.000+00:00",
"price": 900.0,
"customer": {
"id": 2,
"phoneNumber": "987654321",
"name": "Jane Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
}
]
GET /api/reservations/phone/all/{phoneNumber}
[
{
"id": 1,
"doubles": true,
"createdAt": "2023-05-02T23:33:05.806+00:00",
"startsAt": "2025-05-01T13:00:00.000+00:00",
"endsAt": "2025-05-01T14:00:00.000+00:00",
"price": 900.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
},
{
"id": 2,
"doubles": false,
"createdAt": "2023-05-02T23:33:22.098+00:00",
"startsAt": "2015-05-01T13:00:00.000+00:00",
"endsAt": "2015-05-01T14:00:00.000+00:00",
"price": 600.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
}
]
GET /api/reservations/phone/future/{phoneNumber}
[
{
"id": 1,
"doubles": true,
"createdAt": "2023-05-02T23:33:05.806+00:00",
"startsAt": "2025-05-01T13:00:00.000+00:00",
"endsAt": "2025-05-01T14:00:00.000+00:00",
"price": 900.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
}
]
PUT /api/reservations/id/{id}
{
"courtId": 2,
"customerPhoneNumber": "123456789",
"customerName": "John Doe",
"isDoubles": true,
"startsAt": "2023-05-01T10:00:00Z",
"endsAt": "2023-05-01T12:00:00Z"
}
{
"id": 1,
"doubles": true,
"createdAt": "2023-05-02T23:43:51.754+00:00",
"startsAt": "2023-05-01T10:00:00.000+00:00",
"endsAt": "2023-05-01T12:00:00.000+00:00",
"price": 1800.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 2,
"name": "Court 2",
"surface": {
"id": 1,
"name": "Clay",
"minutePrice": 10
}
}
}
PATCH /api/reservations/id/{id}
{
"courtId": 4
}
{
"id": 1,
"doubles": true,
"createdAt": "2023-05-02T23:43:51.754+00:00",
"startsAt": "2023-05-01T10:00:00.000+00:00",
"endsAt": "2023-05-01T12:00:00.000+00:00",
"price": 2700.0,
"customer": {
"id": 1,
"phoneNumber": "123456789",
"name": "John Doe"
},
"court": {
"id": 4,
"name": "Court 4",
"surface": {
"id": 2,
"name": "Grass",
"minutePrice": 15
}
}
}
DELETE /api/reservations/id/{id}