Skip to main content
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

SERVER_PORT
number
default:"8083"
Server port

Database configuration

DB_HOST
string
default:"localhost"
PostgreSQL host
DB_PORT
number
default:"5432"
PostgreSQL port
DB_NAME
string
default:"product_db"
Database name
DB_USERNAME
string
default:"postgres"
Database username
DB_PASSWORD
string
required
Database password
JPA_DDL_AUTO
string
default:"validate"
Hibernate DDL auto (update for dev, validate for prod)

JWT configuration

JWT_SECRET
string
required
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

curl http://localhost:8083/products/1 \
  -H "Authorization: Bearer <token>"

Update product (Admin only)

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)

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

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:
open http://localhost:8083/swagger-ui.html

Health check

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:
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

Build docs developers (and LLMs) love