Architecture

Multi-module Maven architecture, layered design, and Quarkus conventions used in the Integration Service.

Multi-Module Maven Project

Shell
data-integration-service/ ← parent POM (Java 21, Quarkus 3.30.6)
├── common/ ← shared DTOs (BulkUpsertRequestDTO, BulkUpsertResponseDTO)
├── supplier/ ← suppliers + certifications
├── product/ ← supplier products + company products
├── textile/ ← yarns, fibers, fabrics (extends product)
├── purchase/ ← purchase records + status lifecycle
├── chemical/ ← chemical products + compliance + purchases
├── traceability/ ← traceability records + processing stages
├── user/ ← entity-only (User), not wired to REST
└── app/ ← runnable Quarkus module (aggregates all above)

Domain modules are libraries — the app module provides the Quarkus runtime and wires them all together.

Layered Architecture

Each domain module follows the same layered pattern:

Shell
REST Resource (@Path, /api/v1/...)
Service (business logic, @ApplicationScoped)
Mapper (Entity ↔ DTO)
Entity (PanacheEntity, Hibernate ORM)
PostgreSQL

Dependencies flow only forward. Resources never access Entities directly.

Cross-Module Relations

Modules do not have JPA joins between them. Relations are expressed as Long IDs (supplierId, userId, companyId, productId) with validation in the Service layer. This keeps modules decoupled and independently testable.

API Prefix

All REST endpoints use the prefix /api/v1/:

ModuleBase Path
Suppliers/api/v1/suppliers
Supplier Certifications/api/v1/supplier-certifications
Supplier Products/api/v1/supplier/products
Company Products/api/v1/company/products
Textile (Yarns/Fibers/Fabrics)/api/v1/textile/{yarns,fibers,fabrics}
Purchases/api/v1/purchases
Chemicals/api/v1/chemicals
Chemical Purchases/api/v1/chemical-purchases
Traceability Records/api/v1/traceability
Processing Stages/api/v1/product/traceability

Entity Design

All entities extend PanacheEntity (Active Record pattern) with public fields:

Java
@Entity
@Table(name = "supplier")
public class Supplier extends PanacheEntity {
@NotBlank public String name;
@NotBlank public String category;
public String country;
@JdbcTypeCode(SqlTypes.JSON)
public Map<String, Object> metadata;
@PrePersist
public void prePersist() {
if (createdAt == null) createdAt = LocalDateTime.now();
if (updatedAt == null) updatedAt = LocalDateTime.now();
}
@PreUpdate
public void preUpdate() {
updatedAt = LocalDateTime.now();
}
}

Entity Metadata

Most entities support a metadata field — a jsonb column in PostgreSQL mapped as Map<String, Object>. This allows storing arbitrary key-value pairs without schema changes.

Testing

ScopeToolDatabase
Integration test@QuarkusTestH2 in-memory
Transaction rollback@TestTransactionH2
Dev modeQuarkus Dev ServicesPostgreSQL (Docker)
ProductionPostgreSQL (validate only)

Jandex Bean Indexing

Every domain module must include the Jandex Maven plugin to enable CDI scanning:

XML
<plugin>
<groupId>io.smallrye</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<executions>
<execution><id>make-index</id><goals><goal>jandex</goal></goals></execution>
</executions>
</plugin>