deprecated ‐ 2. Product Catalog Service‐Mongodb Edition‐ step‐by‐step guide - Wiz-DevTech/prettygirllz GitHub Wiki

Here's a comprehensive step-by-step guide for implementing the Product Catalog Service in Java with MongoDB, Maven, and full testing integration:


Java Product Catalog Service Guide

Step-by-Step Implementation with Testing

Architecture Diagram
(Visual representation of the components we'll build)


1. Environment Setup

1.1 Install Prerequisites

# Java JDK 17
sudo apt install openjdk-17-jdk

# Maven
sudo apt install maven

# MongoDB (Docker)
docker run -d -p 27017:27017 --name mongodb -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=secret mongo:6.0

# IDE (Optional)
sudo snap install intellij-idea-ultimate --classic

1.2 Verify Installations

java -version  # Should show 17+
mvn -v         # Should show 3.8+
docker ps      # Should show MongoDB running

2. Project Initialization

2.1 Create Maven Project

mvn archetype:generate -DgroupId=com.productcatalog -DartifactId=product-service -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd product-service

2.2 Update pom.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.0</version>
  </parent>

  <dependencies>
    <!-- Spring Boot -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- MongoDB -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    
    <!-- Testing -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>de.flapdoodle.embed</groupId>
      <artifactId>de.flapdoodle.embed.mongo</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

3. Core Implementation

3.1 MongoDB Entity

// src/main/java/com/productcatalog/model/Product.java
package com.productcatalog.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "products")
public class Product {
    @Id
    private String id;
    private String sku;  // Format: ABC-1234
    private String name;
    private int inventory;
    
    // Constructors, Getters, Setters
}

3.2 Repository Layer

// src/main/java/com/productcatalog/repository/ProductRepository.java
package com.productcatalog.repository;

import com.productcatalog.model.Product;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface ProductRepository extends MongoRepository<Product, String> {
    Product findBySku(String sku);
}

3.3 Service Layer with Validation

// src/main/java/com/productcatalog/service/ProductService.java
package com.productcatalog.service;

import com.productcatalog.exception.InvalidSKUException;
import com.productcatalog.model.Product;
import com.productcatalog.repository.ProductRepository;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    private final ProductRepository repository;

    public ProductService(ProductRepository repository) {
        this.repository = repository;
    }

    public Product createProduct(Product product) throws InvalidSKUException {
        if (!product.getSku().matches("^[A-Z]{3}-\\d{4}$")) {
            throw new InvalidSKUException("SKU must match format ABC-1234");
        }
        return repository.save(product);
    }
}

3.4 REST Controller

// src/main/java/com/productcatalog/controller/ProductController.java
package com.productcatalog.controller;

import com.productcatalog.exception.InvalidSKUException;
import com.productcatalog.model.Product;
import com.productcatalog.service.ProductService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/products")
public class ProductController {
    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @PostMapping
    public ResponseEntity<Product> createProduct(@RequestBody Product product) throws InvalidSKUException {
        return ResponseEntity.ok(productService.createProduct(product));
    }
}

4. Testing Implementation

4.1 Unit Tests

// src/test/java/com/productcatalog/service/ProductServiceTest.java
package com.productcatalog.service;

import com.productcatalog.exception.InvalidSKUException;
import com.productcatalog.model.Product;
import com.productcatalog.repository.ProductRepository;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@SpringBootTest
class ProductServiceTest {
    @Mock
    private ProductRepository repository;
    
    @InjectMocks
    private ProductService productService;

    @Test
    void whenInvalidSKU_thenThrowsException() {
        Product product = new Product("INVALID", "Test Product", 10);
        assertThrows(InvalidSKUException.class, () -> productService.createProduct(product));
    }
}

4.2 Integration Test with Embedded MongoDB

// src/test/java/com/productcatalog/ProductIntegrationTest.java
package com.productcatalog;

import com.productcatalog.model.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;

import static org.assertj.core.api.Assertions.assertThat;

@DataMongoTest
class ProductIntegrationTest {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    void whenSaveProduct_thenCanRetrieve() {
        Product product = new Product("ABC-1234", "Test Product", 10);
        mongoTemplate.save(product);
        
        Product found = mongoTemplate.findById(product.getId(), Product.class);
        assertThat(found.getSku()).isEqualTo(product.getSku());
    }
}

4.3 API Test (MockMVC)

// src/test/java/com/productcatalog/controller/ProductControllerTest.java
package com.productcatalog.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.productcatalog.model.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class ProductControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    void whenValidInput_thenReturns200() throws Exception {
        Product product = new Product("ABC-1234", "Test Product", 10);
        
        mockMvc.perform(post("/api/products")
                .contentType(MediaType.APPLICATION_JSON)
                .content(new ObjectMapper().writeValueAsString(product)))
                .andExpect(status().isOk());
    }
}

5. Running and Verification

5.1 Start the Application

mvn spring-boot:run

5.2 Test Endpoints

# Create Product
curl -X POST http://localhost:8080/api/products \
  -H "Content-Type: application/json" \
  -d '{"sku":"ABC-1234","name":"Sample Product","inventory":10}'

# Verify in MongoDB
docker exec -it mongodb mongosh -u admin -p secret
> use productcatalog
> db.products.find()

5.3 Run All Tests

mvn test

6. Deployment

6.1 Build JAR

mvn clean package

6.2 Docker Deployment

# Dockerfile
FROM eclipse-temurin:17-jdk
COPY target/product-service-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","app.jar"]

Build and run:

docker build -t product-service .
docker run -p 8080:8080 --link mongodb product-service

Troubleshooting Guide

Issue Solution
MongoDB connection refused Verify credentials in application.properties
Tests fail with port conflict Add @TestPropertySource(properties = "spring.mongodb.embedded.version=6.0.5")
Invalid SKU not caught Check regex pattern in ProductService

Next Steps

  1. Add Swagger UI for API documentation
  2. Implement JWT Authentication
  3. Set up CI/CD Pipeline (Jenkins/GitHub Actions)

Let me know if you'd like me to expand any section! 🚀

⚠️ **GitHub.com Fallback** ⚠️