Commerce Cart API is a Spring Boot REST service for authentication, product catalog management, shopping carts, and order history. It uses JWT bearer tokens for authenticated operations and Spring Data JPA for persistence.
- Java 21
- Spring Boot 4.1.1
- Spring Web MVC
- Spring Data JPA and Hibernate
- PostgreSQL for the configured application database
- H2 for test/runtime support
- Spring Security with JWT authentication
- JJWT 0.13.0
- Lombok and MapStruct
- Maven Wrapper
- JDK 21 or newer
- PostgreSQL available locally or at a reachable host
Maven does not need to be installed because this repository includes mvnw and mvnw.cmd.
The application reads its default settings from src/main/resources/application.properties:
spring.application.name=CommerceCartApi
spring.datasource.url=jdbc:postgresql://localhost:5432/commerce_api_db
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username=postgres
spring.jpa.hibernate.ddl-auto=updateCreate the commerce_api_db PostgreSQL database and provide the database password through spring.datasource.password. The application also requires a Base64-encoded value for application.security.jwt.secret-key. Use private environment-specific values rather than committing credentials or signing keys.
For a local override, set the missing values in src/main/resources/application.properties:
spring.datasource.password=<postgres-password>
application.security.jwt.secret-key=<base64-encoded-secret>Hibernate is configured with ddl-auto=update, so the schema is updated automatically at startup. No custom server port is configured; Spring Boot therefore uses port 8080.
Windows:
.\mvnw.cmd spring-boot:runmacOS/Linux:
./mvnw spring-boot:runBuild the application without starting it:
.\mvnw.cmd clean packageRegistration and login are public. New registrations receive the USER role; the API does not expose an admin-registration endpoint.
Login returns a JWT. Send it with protected requests using:
Authorization: Bearer <jwt-token>Tokens expire after 12 hours. The authorization rules implemented in SecurityConfig are:
| Endpoint | Access |
|---|---|
POST /api/auth/register |
Public |
POST /api/auth/login |
Public |
GET /api/products |
Public |
POST /api/products |
ADMIN authority |
DELETE /api/products/{id} |
ADMIN authority |
| Cart and order endpoints | Authenticated users |
All request bodies use JSON. Validation rules below reflect the request DTOs in the source code.
POST /api/auth/register
Content-Type: application/json{
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"password": "change-me"
}firstName and lastName must not be blank, email must be a valid email address, and password must contain at least six characters. A successful request returns 201 Created with the created user's id, firstName, lastName, email, and role.
POST /api/auth/login
Content-Type: application/json{
"email": "ada@example.com",
"password": "change-me"
}Successful authentication returns 200 OK:
{
"token": "<jwt-token>"
}GET /api/productsReturns 200 OK with products whose status is not DELETED. Results can therefore include ACTIVE and OUT_OF_STOCK products.
POST /api/products
Authorization: Bearer <admin-jwt-token>
Content-Type: application/json{
"name": "Laptop",
"description": "13-inch laptop",
"price": 1299.99
}name must not be blank and price must be positive. A successful request returns 201 Created with the product id, name, description, price, and status. New products are created as ACTIVE.
DELETE /api/products/{id}
Authorization: Bearer <admin-jwt-token>Returns 200 OK and changes the product status to DELETED; the database row is not physically removed.
All cart endpoints require authentication and operate on the current user's cart.
GET /api/cart
Authorization: Bearer <jwt-token>Example response:
{
"cartId": 1,
"cartItems": [
{
"productId": 1,
"productName": "Laptop",
"quantity": 1,
"unitPrice": 1299.99,
"totalPrice": 1299.99
}
],
"cartTotalPrice": 1299.99
}POST /api/cart/items
Authorization: Bearer <jwt-token>
Content-Type: application/json{
"productId": 1,
"quantity": 1
}quantity must be positive. The product must be ACTIVE, and the requested total quantity must not exceed available stock.
DELETE /api/cart/items/{productId}
Authorization: Bearer <jwt-token>DELETE /api/cart
Authorization: Bearer <jwt-token>Cart mutation endpoints return the updated cart.
All order endpoints require authentication.
POST /api/orders
Authorization: Bearer <jwt-token>
Content-Type: application/json{
"deliveryAddress": "1 Example Street, London"
}deliveryAddress must not be blank. The current cart must contain at least one item, and stock is checked again during order creation. Successful requests return 201 Created, create an order with PENDING status, reduce product stock, and clear the cart.
GET /api/orders
Authorization: Bearer <jwt-token>Returns 200 OK with orders containing orderId, deliveryAddress, status, totalAmount, orderDate, and item details.
Userstores a unique email, hashed password, andUSERorADMINrole.Productstores name, description, price, stock quantity, lifecycle status, and audit timestamps.Cartbelongs one-to-one to a user and containsCartItemrecords.CartItemreferences a product and stores its quantity.Orderbelongs to a user and containsOrderItemrecords, delivery address, status, total amount, and order date.OrderItemstores the ordered product, quantity, and unit price captured at order time.
Product statuses are ACTIVE, OUT_OF_STOCK, and DELETED. Order statuses are PENDING, SHIPPED, DELIVERED, and CANCELED.
GlobalExceptionHandler converts validation failures and domain exceptions into ApiErrorResponse responses. Depending on the condition, the API returns 400 Bad Request, 404 Not Found, 406 Not Acceptable, 409 Conflict, or 500 Internal Server Error.
Run the complete test suite:
Windows:
.\mvnw.cmd testmacOS/Linux:
./mvnw testThe repository includes:
CommerceCartApiApplicationTestsfor application context loadingProductControllerTestfor MVC/controller behaviorProductServiceTestfor product service behaviorProductRepositoryTestfor JPA repository behaviorProductIntegrationTestfor a random-port product API flow