Authentication, Authorization, SQL, Async tasks, Unit Tests, Code Coverage.
- Building an Application with Spring Boot
- Spring Boot Examples
- Spring Boot – Starters
- Spring Boot Actuator
- Using Logback with Spring Boot
- @Controller and @RestController Annotations in Spring Boot
- Spring Data JPA - Reference Documentation
- Jackson Project Home @github
- Java Map Class
- Spring Boot Connect to PostgreSQL Database Examples
- Spring Boot PostgreSQL
- Spring Boot + PostgreSQL + JPA/Hibernate CRUD Restful API Tutorial
- Java 8 – Convert Optional to String
- Personalizar las relaciones con @JoinColumn
- Securing a Web Application
- Hashing a Password in Java
- Password authentication in Java
- Pagination and Sorting using Spring Data JPA
- Spring @Async Annotation for Asynchronous Processing
- Introduction to Spring Testing
- AssertJ Core
- How to configure maven surefire plugin work with JUnit 5
Attribute | Type | Description |
---|---|---|
id | int | User unique identifier. |
name | string | User name. |
password | string | User hashed password. |
Attribute | Type | Description |
---|---|---|
id | int | Job id. |
createdAt | date | Job creation date. |
startedAt | date | Job start date. |
endedAt | date | Job end date. |
status | int | Job status (Pending, Started, Ended, Failed). |
Attribute | Type | Description |
---|---|---|
id | int | Person unique identifier. |
name | string | Person name. |
Attribute | Type | Description |
---|---|---|
id | int | Property unique identifier. |
ownerId | int | Owner unique identifier. |
name | string | Property name. |
Methd | Endpoint | Description |
---|---|---|
POST | /api/v1/auth/signup/ | Create an User. |
POST | /api/v1/auth/logout/ | Logout endpoint. |
POST | /api/v1/auth/login/ | Login endpoint. |
GET | /api/v1/auth/session/ | Get session details. |
PUT | /api/v1/auth/session/ | Update your User. |
Methd | Endpoint | Description |
---|---|---|
GET | /api/v1/jobs/ | List the latest jobs. |
GET | /api/v1/jobs/:id | Get one job by id. |
Methd | Endpoint | Description |
---|---|---|
GET | /api/v1/persons/ | Lists persons. |
POST | /api/v1/persons/ | Create a person. |
GET | /api/v1/persons/:id/ | Person details. |
PUT | /api/v1/persons/:id/ | Update person. |
DELETE | /api/v1/persons/:id/ | Delete a person. |
Methd | Endpoint | Description |
---|---|---|
GET | /api/v1/properties/ | Lists properties. |
POST | /api/v1/properties/ | Create a Property. |
GET | /api/v1/properties/:id/ | Property details. |
PUT | /api/v1/properties/:id/ | Update Property. |
DELETE | /api/v1/properties/:id/ | Delete a Property. |
File | Description |
---|---|
pom.xml | Maven Configuration. |
application.properties | Application Properties. |
Application.java | Application Context. |
GlobalProperties.java | Application Configuration. |
File | Description |
---|---|
RootController.java | Root Endpoint. |
PersonController.java | Person API Resource. |
PropertyController.java | Property API Resource. |
UserController.java | User API Resource. |
JobController.java | Job API Resource. |
File | Description |
---|---|
Person.java | Person model. |
Property.java | Property model. |
User.java | User model. |
Job.java | Job model. |
File | Description |
---|---|
PersonTasks.java | Person tasks. |
PropertyTasks.java | Property tasks. |
File | Description |
---|---|
PersonRepository.java | Person model repository. |
PropertyRepository.java | Property model repository. |
UserRepository.java | User model repository. |
JobRepository.java | Job model repository. |
File | Description |
---|---|
PersonService.java | Person business logic. |
PropertyService.java | Property business logic. |
UserService.java | User business logic. |
JobService.java | Job business logic. |
File | Description |
---|---|
GlobalErrorHandler.java | Catches exceptions globally and generates pretty JSON responses. |
ErrorResponse.java | Pretty representation of a Java exception. |
PersonNotFoundError.java | Person not found. |
PropertyNotFoundError.java | Property not found. |
UserNotFoundError.java | User not found. |
JobNotFoundError.java | Job not found. |
File | Description |
---|---|
PersonApiTests.java | Testing the Person API. |
PersonControllerTests.java | Testing the Person controller. |
PersonRepositoryTests.java | Testing the Person repository. |
PersonServiceTests.java | Testing the Person service. |
File | Description |
---|---|
HashUtil.java | Utilities for hashsing password. |
Starting related servies
docker-compose up
[...]
db_1 | 2022-11-24 22:30:48.577 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
db_1 | 2022-11-24 22:30:48.577 UTC [1] LOG: listening on IPv6 address "::", port 5432
db_1 | 2022-11-24 22:30:48.602 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1 | 2022-11-24 22:30:48.639 UTC [48] LOG: database system was shut down at 2022-11-24 22:30:48 UTC
db_1 | 2022-11-24 22:30:48.659 UTC [1] LOG: database system is ready to accept connections
Running the application with Maven:
SALT="asdfasdf" DEBUG="true" ENVIRONMENT="martin" ./mvnw spring-boot:run
Checking the application health status:
curl -s http://localhost:8080/actuator/health
{
"environment": "martin",
"debug": "true"
}
Running unit tests:
./mvnw clean test
Opening the Code Coverage HTML:
google-chrome target/site/jacoco/index.html
Requests before authenticating are restricted.
curl --cookie-jar "/tmp/london" -X POST -s http://localhost:8080/api/v1/login/ -d 'username=user&password=password'
HTTP/1.1 403
Set-Cookie: JSESSIONID=773BEA4F294E1D05CD15CC80870F4F19; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
[...]
Sign up as a new User.
curl --cookie-jar "/tmp/london" -X POST -s http://localhost:8080/api/v1/signup/ -H 'content-type: application/json' -d '{"name": "lorem", "password": "ipsum"}'
{
"id": 1,
"name": "Lorem Ipsum"
}
Authenticating using username and password:
Retrieving a non-existent Person:
curl --cookie-jar "/tmp/london" -s http://localhost:8080/api/v1/persons/123/
{
"timestamp": "2022-11-25T14:58:55.492+00:00",
"type": "com.martincastroalvarez.london.PersonNotFoundError",
"message": null
}
Creating a Person:
curl --cookie-jar "/tmp/london" -X POST -s http://localhost:8080/api/v1/persons/ -H 'content-type: application/json' -d '{"name": "Lorem Ipsum"}'
{
"id": 1,
"name": "Lorem Ipsum"
}
Listing existing Persons:
curl --cookie-jar "/tmp/london" -X GET -s "http://localhost:8080/api/v1/persons/?sort_key="name&limit=10&offset=0"
[
{
"id": 3,
"name": "Lorem Ipsum"
},
{
"id": 1,
"name": "Sit Amet"
},
{
"id": 2,
"name": "Nisman"
}
]
Updating an existing Person:
curl --cookie-jar "/tmp/london" -X PUT -s http://localhost:8080/api/v1/persons/1 -H 'content-type: application/json' -d '{"name": "Sit Amet"}'
{
"id": 1,
"name": "Sit Amet"
}
Getting Person details:
curl --cookie-jar "/tmp/london" -s http://localhost:8080/api/v1/persons/2
{
"id" : 2,
"name" : "Nisman"
}
Deleting a Person:
curl --cookie-jar "/tmp/london" -X DELETE -s http://localhost:8080/api/v1/persons/3
{
"id" : 21,
"createdAt" : null,
"endedAt" : null,
"startedAt" : null,
"status" : null,
"message" : null
}
Searching for Persons by name:
curl --cookie-jar "/tmp/london" -X GET -s "http://localhost:8080/api/v1/persons/?name=Sit&sort_key=name"
[
{
"id": 1,
"name": "Sit Amet"
}
]
Listing jobs:
curl --cookie-jar "/tmp/london" -X GET -s "http://localhost:8080/api/v1/persons/?name=Sit&sort_key=name"
[
{
"id": 1,
"name": "Sit Amet"
}
]
Listing jobs:
curl --cookie-jar "/tmp/london" -X GET -s "http://localhost:8080/api/v1/jobs/?limit=2&offset=0"
[
{
"id": 12,
"createdAt": null,
"endedAt": "2022-11-25T22:54:34.484+00:00",
"startedAt": "2022-11-25T22:54:34.461+00:00",
"status": "FAILED",
"message": "Person now found!"
},
{
"id": 13,
"createdAt": null,
"endedAt": "2022-11-25T22:58:39.070+00:00",
"startedAt": "2022-11-25T22:58:39.045+00:00",
"status": "FAILED",
"message": "Person now found!"
},
{
"id": 11,
"createdAt": null,
"endedAt": "2022-11-25T22:54:11.839+00:00",
"startedAt": "2022-11-25T22:54:11.819+00:00",
"status": "FAILED",
"message": "Person now found!"
}
]
Retrieving a non-existent Propertes:
curl --cookie-jar "/tmp/london" -s http://localhost:8080/api/v1/properties/123/
{
"timestamp": "2022-11-25T14:58:55.492+00:00",
"type": "com.martincastroalvarez.london.PropertyNotFoundError",
"message": null
}
Creating a Property:
curl --cookie-jar "/tmp/london" -X POST -s http://localhost:8080/api/v1/properties/ -H 'content-type: application/json' -d '{"name": "Lorem Ipsum", "ownerId": 1}'
{
"id" : 10,
"owner" : {
"id" : 1,
"name" : "Sit Amet"
},
"name" : "Lorem Ipsum"
}
Listing existing properties:
curl --cookie-jar "/tmp/london" -X GET -s "http://localhost:8080/api/v1/properties/?sort_key=name"
[
{
"id" : 10,
"owner" : {
"id" : 1,
"name" : "Sit Amet"
},
"name" : "Lorem Ipsum"
}
]
Updating an existing Property:
curl --cookie-jar "/tmp/london" -X PUT -s http://localhost:8080/api/v1/properties/1 -H 'content-type: application/json' -d '{"name": "Sit Amet", "ownerId": 2}'
{
"id" : 10,
"owner" : {
"id" : 2,
"name" : "Nisman"
},
"name" : "Sit Amet"
}
Getting Property details:
curl --cookie-jar "/tmp/london" -s http://localhost:8080/api/v1/properties/1
{
"id" : 2,
"name" : "Nisman"
}
Deleting a Property:
curl --cookie-jar "/tmp/london" -X DELETE -s http://localhost:8080/api/v1/properties/10
{
"id" : 43,
"createdAt" : null,
"endedAt" : null,
"startedAt" : null,
"status" : null,
"message" : null
}