The Product service manages the product catalog for QeetMart, including products, categories, and product variants. It provides comprehensive product management with search and filtering capabilities.
Overview
Built with Spring Boot 3.3.8, the product service handles product CRUD operations, categorization, variant management, and includes OpenAPI documentation via Swagger UI.
The Product service runs on port 8083 by default and uses PostgreSQL for data persistence.
Technology stack
Framework : Spring Boot 3.3.8
Language : Java 17
Database : PostgreSQL
Security : Spring Security + OAuth2 Resource Server
API Documentation : SpringDoc OpenAPI 2.6.0
Key dependencies :
Spring Data JPA
Spring Security OAuth2 Resource Server
Spring Boot Actuator
Micrometer Prometheus
Lombok
Configuration
Environment variables
Database configuration
DB_HOST
string
default: "localhost"
PostgreSQL host
DB_NAME
string
default: "product_db"
Database name
Hibernate DDL auto (update for dev, validate for prod)
JWT configuration
JWT verification secret (must match auth-service)
JWT_ISSUER_URI
string
default: "http://localhost:4001"
JWT issuer URI for validation
API endpoints
Product endpoints
Create product (Admin only)
curl -X POST http://localhost:8083/products \
-H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Wireless Headphones",
"description": "High-quality wireless headphones",
"brand": "TechBrand",
"categoryId": 1,
"price": 99.99,
"currency": "USD",
"status": "ACTIVE"
}'
Get products with filters
curl "http://localhost:8083/products?categoryId=1&brand=TechBrand&status=ACTIVE&page=0&size=10" \
-H "Authorization: Bearer <token>"
Get product by ID
GET /products/{productId}
Response
curl http://localhost:8083/products/1 \
-H "Authorization: Bearer <token>"
Update product (Admin only)
PUT /products/{productId}
Response
curl -X PUT http://localhost:8083/products/1 \
-H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Wireless Headphones",
"price": 129.99,
"status": "ACTIVE"
}'
Delete product (Admin only)
DELETE /products/{productId}
Response
curl -X DELETE http://localhost:8083/products/1 \
-H "Authorization: Bearer <admin-token>"
Deletes are soft deletes - products are marked as deleted but not removed from the database.
Search products
GET /products/search
Response
curl "http://localhost:8083/products/search?query=headphones" \
-H "Authorization: Bearer <token>"
Category endpoints
The service provides full CRUD operations for product categories. See CategoryController for details.
Product variant endpoints
Manage product variants (different colors, sizes, SKUs) via ProductVariantController.
Data models
Product entity
@ Entity
@ Table ( name = "products" )
public class Product extends BaseAuditEntity {
@ Id
@ GeneratedValue ( strategy = GenerationType . IDENTITY )
private Long id ;
@ Column ( nullable = false , length = 150 )
private String name ;
@ Column ( length = 1000 )
private String description ;
@ Column ( nullable = false , length = 100 )
private String brand ;
@ ManyToOne ( fetch = FetchType . LAZY , optional = false )
@ JoinColumn ( name = "category_id" , nullable = false )
private Category category ;
@ Column ( nullable = false , precision = 19 , scale = 2 )
private BigDecimal price ;
@ Column ( nullable = false , length = 3 )
private String currency ;
@ Enumerated ( EnumType . STRING )
@ Column ( nullable = false , length = 30 )
private ProductStatus status ; // ACTIVE, INACTIVE, OUT_OF_STOCK
@ Column ( name = "is_deleted" , nullable = false )
private boolean isDeleted = false ;
@ OneToMany ( mappedBy = "product" , cascade = CascadeType . ALL )
private List < ProductVariant > variants = new ArrayList <>();
}
Product status enum
ACTIVE - Product is available for purchase
INACTIVE - Product is not currently available
OUT_OF_STOCK - Product is temporarily unavailable
OpenAPI documentation
Swagger UI is available for interactive API exploration:
Access Swagger UI
OpenAPI JSON
open http://localhost:8083/swagger-ui.html
Health check
GET /actuator/health
Response
curl http://localhost:8083/actuator/health
Metrics
Prometheus metrics are available at /actuator/prometheus.
Running the service
cd product-service
mvn spring-boot:run
Search and filtering
The service uses Spring Data JPA Specifications for dynamic filtering:
ProductSpecification.java
public static Specification < Product > withFilters (
Long categoryId,
String brand,
ProductStatus status
) {
return (root, query, cb) -> {
List < Predicate > predicates = new ArrayList <>();
if (categoryId != null ) {
predicates . add ( cb . equal ( root . get ( "category" ). get ( "id" ), categoryId));
}
if (brand != null ) {
predicates . add ( cb . equal ( root . get ( "brand" ), brand));
}
if (status != null ) {
predicates . add ( cb . equal ( root . get ( "status" ), status));
}
predicates . add ( cb . equal ( root . get ( "isDeleted" ), false ));
return cb . and ( predicates . toArray ( new Predicate [ 0 ]));
};
}
Authorization
Public access : GET endpoints for browsing products
Admin only : POST, PUT, DELETE operations require ADMIN role
Ensure the JWT_SECRET matches the secret used in the auth-service for proper token validation.
Dependencies
PostgreSQL : For product catalog storage
Auth service : For JWT token validation
Inventory service : For stock level integration
Source code
Location: ~/workspace/source/micros/product-service/
Key files:
src/main/java/com/qeetmart/product/controller/ProductController.java - Product endpoints
src/main/java/com/qeetmart/product/controller/CategoryController.java - Category endpoints
src/main/java/com/qeetmart/product/entity/Product.java - Product entity
src/main/java/com/qeetmart/product/specification/ProductSpecification.java - Search filters
src/main/resources/application.yml - Configuration