Product Catalog Service ‐ API Integration Guide (Actual Implementation) - Wiz-DevTech/prettygirllz GitHub Wiki

Product Catalog Service - API Integration Guide (Actual Implementation)

API Overview

The Product Catalog Service provides REST APIs for managing products with specialized endpoints for Candy and Fashion categories. The service is currently unsecured and all endpoints are publicly accessible.

Base Configuration

URLs

  • Main API: http://localhost:8080/api
  • Swagger UI: http://localhost:8080/api/swagger-ui.html
  • API Documentation: http://localhost:8080/api/api-docs

Headers

  • Content-Type: application/json for all requests
  • No authentication required (all endpoints are public)

API Endpoints

Product API (General Operations)

1. Get All Products

  • Method: GET
  • URL: /api/products
  • Description: Retrieves all products
  • Authentication: None
  • Response Example:
[
  {
    "id": 3,
    "name": "Fashion Item",
    "description": "A trendy fashion item",
    "category": "FASHION",
    "active": true,
    "createdDate": "2025-05-10T04:58:17.889678",
    "lastModifiedDate": "2025-05-10T04:58:17.889678",
    "createdBy": "system",
    "lastModifiedBy": "system",
    "skus": []
  }
]

2. Get Product by ID

  • Method: GET
  • URL: /api/products/{id}
  • Description: Retrieves a specific product
  • Path Parameters:
    • id (required): Product ID
  • Response Codes:
    • 200 OK: Product found
    • 404 Not Found: Product doesn't exist

3. Get Product with SKUs

  • Method: GET
  • URL: /api/products/with-skus/{id}
  • Description: Retrieves product with all associated SKUs
  • Implementation: Uses JOIN FETCH for performance
  • Response: Product with populated SKUs array

4. Get Products by Category

  • Method: GET
  • URL: /api/products/category/{category}
  • Description: Filters products by category
  • Path Parameters:
    • category: Category name (e.g., "CANDY", "FASHION")
  • Example: /api/products/category/CANDY

5. Search Products by Name

  • Method: GET
  • URL: /api/products/search
  • Description: Case-insensitive name search
  • Query Parameters:
    • name (required): Search term
  • Example: /api/products/search?name=sweet

6. Get Products with Available Inventory

  • Method: GET
  • URL: /api/products/available
  • Description: Returns products with available SKU inventory
  • Filter Logic: availableQuantity > 0 AND active = true

7. Create Product

  • Method: POST
  • URL: /api/products
  • Request Body:
{
  "name": "New Product",
  "description": "Product description",
  "category": "CANDY"
}
  • Validation:
    • SKU codes must match pattern [A-Z]{2}[0-9]{6}
    • Throws InvalidSKUException for invalid formats

8. Update Product

  • Method: PUT
  • URL: /api/products/{id}
  • Description: Updates entire product
  • Validation: Same as create + existence check
  • Error: RuntimeException if product not found

9. Delete Product

  • Method: DELETE
  • URL: /api/products/{id}
  • Description: Permanently removes product and related SKUs
  • Cascade: Deletes associated SKUs and color variants

10. Deactivate Product

  • Method: PATCH
  • URL: /api/products/{id}/deactivate
  • Description: Soft delete (sets active=false)
  • Response: 204 No Content

Candy API (Category-Specific)

11. Get All Candy Products

  • Method: GET
  • URL: /api/candy
  • Filter: category = "CANDY"

12. Get Candy Product by ID

  • Method: GET
  • URL: /api/candy/{id}
  • Validation: Verifies product category is CANDY
  • Response: 404 if not candy product

13. Create Candy Product

  • Method: POST
  • URL: /api/candy
  • Auto-sets: category = "CANDY"
  • Request Body:
{
  "name": "Gummy Bears",
  "description": "Sweet gummy candy"
}

14. Update Candy Product

  • Method: PUT
  • URL: /api/candy/{id}
  • Validation: Ensures product remains CANDY category
  • Enforces: category = "CANDY"

15. Delete Candy Product

  • Method: DELETE
  • URL: /api/candy/{id}
  • Validation: Only deletes if category is CANDY

Fashion API (Category-Specific)

16-20. Fashion Endpoints

  • Same patterns as Candy API
  • Base URL: /api/fashion
  • Category filter: "FASHION"
  • All operations mirror candy endpoints

Data Models

Product Entity (Actual Implementation)

{
  "id": "Long (generated)",
  "name": "String (required)",
  "description": "String (optional)",
  "category": "String (required)",
  "active": "boolean (default: true)",
  "createdDate": "LocalDateTime",
  "lastModifiedDate": "LocalDateTime", 
  "createdBy": "String (default: 'system')",
  "lastModifiedBy": "String (default: 'system')",
  "skus": ["Array of SKU objects"]
}

SKU Entity

{
  "id": "Long (generated)",
  "skuCode": "String (unique, pattern: [A-Z]{2}[0-9]{6})",
  "productId": "Long (foreign key)",
  "price": "BigDecimal (required, > 0)",
  "availableQuantity": "Integer (default: 0, >= 0)",
  "active": "boolean (default: true)",
  "createdDate": "LocalDateTime",
  "lastModifiedDate": "LocalDateTime",
  "createdBy": "String",
  "lastModifiedBy": "String"
}

ColorVariant Entity

{
  "id": "Long (generated)",
  "skuId": "Long (foreign key)",
  "colorName": "String (required)",
  "colorCode": "String (optional)",
  "imageUrl": "String (optional)",
  "createdDate": "LocalDateTime",
  "lastModifiedDate": "LocalDateTime",
  "createdBy": "String",
  "lastModifiedBy": "String"
}

Error Handling (Current Implementation)

Global Exception Handler

InvalidSKUException (400 Bad Request)

{
  "status": "BAD_REQUEST",
  "timestamp": "2025-05-16T07:04:37.206",
  "message": "Invalid SKU format: XX1234567",
  "path": null
}

General Exception (500 Internal Server Error)

{
  "status": "INTERNAL_SERVER_ERROR",
  "timestamp": "2025-05-16T07:04:37.206",
  "message": "An unexpected error occurred: Product not found with id: 999",
  "path": null
}

Validation Exception (400 Bad Request)

{
  "fieldName": "Error message from messages.properties"
}

Validation Rules (Implemented)

SKU Code Validation

  • Pattern: [A-Z]{2}\\d{6}
  • Example Valid: "AB123456"
  • Example Invalid: "ab123456", "ABC12345", "AB12345X"

Database Constraints

  • Products: name NOT NULL, category NOT NULL
  • SKUs: price > 0, availableQuantity >= 0
  • SKU code must be unique

Integration Examples

JavaScript/TypeScript

class ProductService {
  private baseUrl = 'http://localhost:8080/api';

  async getAllProducts(): Promise<Product[]> {
    const response = await fetch(`${this.baseUrl}/products`);
    if (!response.ok) {
      throw new Error(`Failed to fetch: ${response.status}`);
    }
    return response.json();
  }

  async createCandyProduct(product: Partial<Product>): Promise<Product> {
    const response = await fetch(`${this.baseUrl}/candy`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(product),
    });
    
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.message || 'Failed to create product');
    }
    return response.json();
  }

  async searchProducts(name: string): Promise<Product[]> {
    const response = await fetch(
      `${this.baseUrl}/products/search?name=${encodeURIComponent(name)}`
    );
    return response.json();
  }
}

Python

import requests
from typing import List, Dict, Optional

class ProductService:
    def __init__(self, base_url: str = "http://localhost:8080/api"):
        self.base_url = base_url

    def get_all_products(self) -> List[Dict]:
        response = requests.get(f"{self.base_url}/products")
        response.raise_for_status()
        return response.json()

    def create_product(self, product: Dict) -> Dict:
        response = requests.post(
            f"{self.base_url}/products",
            json=product
        )
        response.raise_for_status()
        return response.json()

    def get_fashion_products(self) -> List[Dict]:
        response = requests.get(f"{self.base_url}/fashion")
        response.raise_for_status()
        return response.json()

cURL Examples

# Get all products
curl http://localhost:8080/api/products

# Create a candy product
curl -X POST http://localhost:8080/api/candy \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Chocolate Bar",
    "description": "Rich dark chocolate"
  }'

# Search products
curl "http://localhost:8080/api/products/search?name=sweet"

# Get product with SKUs
curl http://localhost:8080/api/products/with-skus/3

# Deactivate product
curl -X PATCH http://localhost:8080/api/products/3/deactivate

Notable Implementation Details

No Authentication/Authorization

  • All endpoints are publicly accessible
  • No rate limiting implemented
  • No CORS configuration

No Pagination

  • All list endpoints return complete datasets
  • Could be problematic with large datasets
  • No sorting options available

Transaction Management

  • All service methods use @Transactional
  • Read-only transactions for queries
  • Proper cascade deletes configured

Audit Fields

  • All entities have created/modified timestamps
  • Created/modified by fields (default: "system")
  • JPA auditing enabled with system-wide auditor

Performance Characteristics

Database Queries

  • SQL queries are logged (debug level)
  • N+1 problem avoided with JOIN FETCH queries
  • No query optimization implemented

Response Times

  • No caching implemented
  • Direct database queries for all requests
  • Connection pooling uses Hikari defaults

Testing Your Integration

Using Swagger UI

  1. Open http://localhost:8080/api/swagger-ui.html
  2. Expand endpoint sections
  3. Click "Try it out" buttons
  4. Fill parameters and execute
  5. View responses and status codes

Test Data Available

  • Products with IDs: 3, 4, 5, 6, 7
  • Categories: FASHION, CANDY
  • All created by "system" user
  • Created around 2025-05-10

Security Considerations

Current State (Insecure)

  • No authentication required
  • No input sanitization beyond SKU validation
  • Database credentials in plain text
  • No HTTPS enforcement
  • No request rate limiting

Recommendations

  1. Add authentication (JWT/OAuth2)
  2. Implement HTTPS
  3. Add input validation annotations
  4. Encrypt configuration properties
  5. Add CORS headers for web clients

API Documentation

OpenAPI Specification

  • Available at /api/api-docs
  • Version: 1.0
  • Format: OAS 3.0
  • Includes all endpoints with parameters
  • Schema definitions for all models

Swagger UI Features

  • Interactive API testing
  • Request/response examples
  • Model schema visualization
  • Operation grouping by controller
  • Try-it-out functionality

Error Handling Best Practices

Expected Errors

  1. 404 Not Found: Resource doesn't exist
  2. 400 Bad Request: Invalid SKU format
  3. 500 Internal Error: Unexpected exceptions

Client Error Handling

// Example error handling
try {
  const product = await productService.getProduct(id);
} catch (error) {
  if (error.status === 404) {
    console.log('Product not found');
  } else if (error.status === 400) {
    console.log('Invalid request:', error.message);
  } else {
    console.log('Unexpected error:', error.message);
  }
}

Future Enhancements

High Priority Missing Features

  1. Authentication/Authorization system
  2. Input validation with Bean Validation
  3. Pagination and sorting
  4. Unit and integration tests
  5. Health check endpoints

Medium Priority Improvements

  1. Response caching
  2. Rate limiting
  3. Better error messages
  4. API versioning
  5. Batch operations

Low Priority Enhancements

  1. Full-text search
  2. Image upload for products
  3. WebSocket notifications
  4. Export/import functionality
  5. Admin dashboard

Contact Information

  • Service: Product Catalog Service
  • Version: 0.0.1-SNAPSHOT
  • Port: 8080
  • Context Path: /api
  • Documentation: Swagger UI available
  • Database: PostgreSQL with Flyway migrations
⚠️ **GitHub.com Fallback** ⚠️