This is a practical project of a RESTful API built with Java and Spring Boot, connected to a PostgreSQL relational database, and secured with JWT authentication via Spring Security.
🌱 About this project: This repository marks my first hands-on experience with the Spring Boot framework. The main goal was to understand the basics of data persistence (CRUD) using JPA and Hibernate, and I later expanded it to include authentication and authorization with Spring Security and JWT. I am using this project as a study lab and I intend to dive deeper and deeper into the Spring ecosystem!
- Java
- Spring Boot (Web, Data JPA, Security)
- Spring Security (Authentication & Authorization)
- JWT (JSON Web Token, via
jjwt) - PostgreSQL (Database)
- Hibernate (ORM)
- BCrypt (Password hashing)
- Insomnia (For API testing and sending JSON requests)
Before you begin, you will need to have the following installed on your machine:
- Java JDK (version 17 or higher recommended)
- PostgreSQL
- An IDE of your choice (IntelliJ IDEA, Eclipse, VS Code)
-
Clone this repository:
git clone https://github.com/andynnnfw/spring-rest-api-postgres.git
-
Configure the Database: Open pgAdmin or your PostgreSQL terminal and create a database named
meubanco:CREATE DATABASE meubanco;
-
Configure the credentials: Open the
src/main/resources/application.propertiesfile and change the username and password to your local PostgreSQL credentials:spring.datasource.username=your_username_here spring.datasource.password=your_password_here
-
Start the application: Run the project through your IDE or by using Maven. The API will be running at
http://localhost:8080.
This API uses JWT (JSON Web Token) for stateless authentication. Passwords are hashed with BCrypt before being stored in the database, and most routes require a valid token to be accessed — except for the /auth/** endpoints, which are public.
- Route:
POST /auth/register - Description: Creates a new user with an encrypted password.
- Request Body (JSON):
{ "username": "andyn", "password": "yourpassword" } - Success Response:
200 OK
- Route:
POST /auth/login - Description: Validates the credentials and returns a JWT token to be used in protected routes.
- Request Body (JSON):
{ "username": "andyn", "password": "yourpassword" } - Success Response:
200 OK{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } - Error Response:
401 Unauthorizedif credentials are invalid.
For protected routes, include the token in the Authorization header:
Authorization: Bearer <your_token_here>
Below are the available routes in the application:
- Route:
GET /api/produtos - Description: Returns a list of all products registered in the database.
- Success Response:
200 OK
- Route:
GET /api/produtos/{id} - Description: Returns a single product by its ID.
- Success Response:
200 OK - Error Response:
404 Not Foundif the product doesn't exist.
- Route:
POST /api/produtos - Description: Saves a new product in the database.
- How to test: During development, I used Insomnia to test this endpoint, sending the product structure in JSON format through the request Body.
- Request Body (JSON):
{ "nome": "chocolati", "preco": 6.70 } - Success Response:
200 OKor201 Created
- Route:
DELETE /api/produtos/{id} - Description: Removes a product from the database by its ID.
- Success Response:
204 No Content - Error Response:
404 Not Foundif the product doesn't exist.
The API has a global exception handler that returns structured error responses instead of default stack traces, for example:
{
"timestamp": "2026-09-17T12:00:00",
"status": 404,
"error": "recurso nao encontrado",
"message": "produto com ID: 99 nao encontrado"
}