2. Product Catalog Service‐Postgresql Edition‐ Guide - Wiz-DevTech/prettygirllz GitHub Wiki
# Java & Maven sudo apt install openjdk-17-jdk maven# PostgreSQL (Docker) docker run -d -p 5432:5432 --name postgres </span> -e POSTGRES_USER=gateway </span> -e POSTGRES_PASSWORD=secret </span> -e POSTGRES_DB=gateway_cache </span> postgres:15
git clone https://github.com/yourrepo/product-catalog-java.git cd product-catalog-java
src/ ├── main/ │ ├── java/ │ │ ├── com.productcatalog/ │ │ │ ├── CandyModule/ # SKU/Inventory (now JPA entities) │ │ │ ├── FashionModule/ # Size/Color (now JPA entities) │ │ │ ├── VirtualTryOn/ # Avatar/AR │ │ │ └── ProductCatalogApplication.java │ └── resources/ │ ├── application.yml # PostgreSQL config │ ├── db/ │ │ └── migration/ # Flyway scripts │ └── logback.xml └── test/ # JUnit tests
<dependencies> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency><!-- PostgreSQL Driver --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency>
<!-- Flyway for migrations --> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> </dependency>
<!-- Testing --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>postgresql</artifactId> <scope>test</scope> </dependency> </dependencies>
// CandyModule/SKU.java @Entity @Table(name = "skus") public class SKU { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;@Column(name = "code", unique = true, length = 8) private String code; // Format: "ABC-1234"
@Column(name = "inventory") private int inventory; }
public interface SKURepository extends JpaRepository<SKU, Long> { @Query("SELECT s FROM SKU s WHERE s.code = :code") Optional<SKU> findByCode(@Param("code") String code); }
@Service @Transactional public class SKUService { @Autowired private SKURepository skuRepo;public void createSKU(SKU sku) { // Database will validate format via CHECK constraint skuRepo.save(sku); } }
@RestController @RequestMapping("/api/candy") public class CandyController { @Autowired private SKUService skuService;@PostMapping("/skus") public ResponseEntity<String> addSKU(@RequestBody SKU sku) { skuService.createSKU(sku); return ResponseEntity.ok("SKU created"); } }
public class InvalidSKUException extends RuntimeException { public InvalidSKUException(String message) { super(message); } }
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(DataIntegrityViolationException.class) public ResponseEntity<String> handleDataError(DataIntegrityViolationException ex) { return ResponseEntity.badRequest().body("Database constraint violation"); }@ExceptionHandler(InvalidSKUException.class) public ResponseEntity<String> handleSKUError(InvalidSKUException ex) { return ResponseEntity.badRequest().body(ex.getMessage()); } }
@Test void testInvalidSKU() { SKUService service = new SKUService(); SKU invalidSKU = new SKU(); invalidSKU.setCode("INVALID"); assertThrows(ConstraintViolationException.class, () -> service.createSKU(invalidSKU)); }
@SpringBootTest @Testcontainers public class CandyControllerIT { @Container static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");@DynamicPropertySource static void configureProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgres::getJdbcUrl); registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); }
@Test void createSKU_ValidFormat_Returns200() { // Test with actual PostgreSQL instance } }
mvn spring-boot:run
# Access: http://localhost:8080/api/candy/skus
FROM eclipse-temurin:17-jdk COPY target/product-catalog-0.0.1.jar app.jar ENTRYPOINT ["java","-jar","app.jar"]
Build:
mvn package docker build -t product-catalog . docker run -p 8080:8080 --network host product-catalog
spring: datasource: url: jdbc:postgresql://localhost:5432/gateway_cache username: gateway password: secret hikari: maximum-pool-size: 10 jpa: hibernate: ddl-auto: validate show-sql: true properties: hibernate: dialect: org.hibernate.dialect.PostgreSQLDialect flyway: locations: classpath:db/migration
-- In V1__Initial_schema.sql ALTER TABLE skus ADD CONSTRAINT valid_sku_format CHECK (code ~ '^[A-Z]{3}-\d{4}$');
Add to pom.xml
:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
Access:
http://localhost:8080/actuator/health http://localhost:8080/actuator/metrics http://localhost:8080/actuator/flyway
Issue | Solution |
---|---|
PostgreSQL connection refused | Check docker ps and credentials |
Constraint violation | Verify CHECK constraints in schema |
Flyway migration failed | Check SQL syntax in migration files |
✅ PostgreSQL Compatibility:
Uses Spring Data JPA repositories
Relational modeling with constraints
✅ Maven Build System:
Standardized dependency management
✅ Java 17:
Records, sealed classes support
✅ Data Integrity:
Database-level validations
ACID transactions
Add Swagger for API docs
Implement JWT Auth for admin/customer roles
Set up PostgreSQL replication for high availability