Initial implementation of HTTP Sender Plugin following TDD methodology with hexagonal architecture. All 313 tests passing (0 failures). This commit adds: - Complete domain model and port interfaces - All adapter implementations (HTTP, gRPC, file logging, config) - Application services (data collection, transmission, backpressure) - Comprehensive test suite with 18 integration tests Test fixes applied during implementation: - Fix base64 encoding validation in DataCollectionServiceIntegrationTest - Fix exception type handling in IConfigurationPortTest - Fix CompletionException unwrapping in IHttpPollingPortTest - Fix sequential batching in DataTransmissionServiceIntegrationTest - Add test adapter failure simulation for reconnection tests - Use adapter counters for gRPC verification Files added: - pom.xml with all dependencies (JUnit 5, Mockito, WireMock, gRPC, Jackson) - src/main/java: Domain model, ports, adapters, application services - src/test/java: Unit tests, integration tests, test utilities
8.0 KiB
8.0 KiB
Architecture Alignment Report - Configuration
Date: 2025-11-20 Issue: Adapter code doesn't match actual Configuration domain model API Root Cause: Parallel AI agents generated code with mismatched APIs
✅ Correct Architecture (From Domain Model)
Configuration Class Structure
System-Wide Settings (Configuration.java):
public final class Configuration {
private final List<EndpointConfig> endpoints; // Per-endpoint configs
private final Duration pollingInterval; // System-wide
private final int bufferCapacity; // System-wide (300)
private final String grpcHost; // gRPC target
private final int grpcPort; // gRPC port
private final boolean tlsEnabled; // TLS flag
private final Duration reconnectDelay; // gRPC reconnect (5s)
private final int healthCheckPort; // Health endpoint (8080)
}
Per-Endpoint Settings (EndpointConfig.java):
public final class EndpointConfig {
private final String url; // Endpoint URL
private final Duration timeout; // Per-endpoint timeout!
private final Map<String, String> headers; // Per-endpoint headers!
}
Builder API (Correct Usage)
// ✅ CORRECT: Use static factory method
Configuration config = Configuration.builder()
.endpoints(endpointList) // List<EndpointConfig>
.pollingInterval(Duration.ofSeconds(5))
.bufferCapacity(300)
.grpcHost("localhost")
.grpcPort(50051)
.tlsEnabled(false)
.reconnectDelay(Duration.ofSeconds(5))
.healthCheckPort(8080)
.build();
// ❌ WRONG: Direct constructor access (private!)
Configuration.Builder builder = new Configuration.Builder(); // Won't compile!
❌ What Adapters Are Doing Wrong
ConfigurationFileAdapter Issues
Wrong API Calls:
// ❌ WRONG
new Configuration.Builder() // Constructor is private!
builder.grpcServerAddress(String) // Method doesn't exist
builder.grpcServerPort(int) // Method doesn't exist
builder.httpEndpoints(List<String>) // Wrong type - needs List<EndpointConfig>
builder.pollingIntervalSeconds(int) // Wrong type - needs Duration
builder.bufferSize(int) // Wrong name - should be bufferCapacity
builder.httpTimeoutSeconds(int) // Doesn't exist - timeout is per-endpoint!
builder.maxRetries(int) // Doesn't exist - adapter implementation detail
builder.retryIntervalSeconds(int) // Doesn't exist - adapter implementation detail
config.getBufferSize() // Wrong name - should be getBufferCapacity()
config.getGrpcServerPort() // Wrong name - should be getGrpcPort()
config.getHttpEndpoints() // Wrong name - should be getEndpoints()
Correct API Calls:
// ✅ CORRECT
Configuration.builder() // Static factory method
.grpcHost(String) // Correct method name
.grpcPort(int) // Correct method name
.endpoints(List<EndpointConfig>) // Correct type
.pollingInterval(Duration) // Correct type
.bufferCapacity(int) // Correct name
// No timeout here - it's per-endpoint in EndpointConfig!
// No retry config - it's adapter implementation detail!
.build()
config.getBufferCapacity() // Correct name
config.getGrpcPort() // Correct name
config.getEndpoints() // Correct name
HttpPollingAdapter Issues
Wrong Assumptions:
// ❌ WRONG: These methods don't exist in Configuration
config.getHttpTimeoutSeconds() // Timeout is per-endpoint!
config.getMaxRetries() // Retry is adapter detail!
config.getRetryIntervalSeconds() // Retry is adapter detail!
Correct Approach:
// ✅ CORRECT: Get timeout from EndpointConfig
for (EndpointConfig endpoint : config.getEndpoints()) {
Duration timeout = endpoint.getTimeout(); // Per-endpoint timeout
Map<String,String> headers = endpoint.getHeaders(); // Per-endpoint headers
// Retry logic is hardcoded in adapter (Req-FR-17)
int maxRetries = 3; // Hardcoded per requirements
int retryIntervalSeconds = 5; // Hardcoded per requirements
}
📋 Requirements Traceability
Req-FR-17: HTTP Retry Logic
- Requirement: "If the HTTP GET request fails HSP shall retry up to 3 times with 5-second intervals"
- Configuration:
http.max_retries = 3, http.retry_interval_seconds = 5 - Correct Implementation: Hardcoded in HttpPollingAdapter (adapter implementation detail)
- NOT in domain model Configuration class
Req-FR-12: HTTP Timeout
- Requirement: "Configurable timeout per endpoint"
- Correct Location: EndpointConfig.timeout (Duration)
- NOT in Configuration class (it's per-endpoint, not system-wide!)
Req-FR-13: HTTP Headers
- Requirement: "Custom headers per endpoint"
- Correct Location: EndpointConfig.headers (Map<String,String>)
- NOT in Configuration class (it's per-endpoint!)
🔧 Required Fixes
1. ConfigurationFileAdapter (16 errors)
Fix Strategy:
- Change
new Configuration.Builder()→Configuration.builder() - Parse JSON to create
List<EndpointConfig>from endpoint strings - Use correct method names:
grpcHost()instead ofgrpcServerAddress()grpcPort()instead ofgrpcServerPort()endpoints()instead ofhttpEndpoints()pollingInterval(Duration)instead ofpollingIntervalSeconds(int)bufferCapacity()instead ofbufferSize()
- Remove non-existent methods:
httpTimeoutSeconds()- use EndpointConfigmaxRetries()- hardcode in adapterretryIntervalSeconds()- hardcode in adapter
- Use correct getter names:
getBufferCapacity()instead ofgetBufferSize()getGrpcPort()instead ofgetGrpcServerPort()getEndpoints()instead ofgetHttpEndpoints()
2. HttpPollingAdapter (10 errors)
Fix Strategy:
- Remove calls to non-existent Configuration methods
- Hardcode retry logic (Req-FR-17):
private static final int MAX_RETRIES = 3; private static final int RETRY_INTERVAL_SECONDS = 5; - Get timeout and headers from EndpointConfig:
Duration timeout = endpointConfig.getTimeout(); Map<String,String> headers = endpointConfig.getHeaders(); - Implement pollEndpoint(String url, Map<String,String> headers, Duration timeout)
3. RateLimitedHttpPollingAdapter (3 errors)
Fix Strategy:
- Implement pollEndpoint(String url, Map<String,String> headers, Duration timeout)
- Same as HttpPollingAdapter
📝 Summary
The Problem:
- Adapters were generated assuming Configuration contains per-endpoint settings (timeout, headers, retries)
- Actual architecture: Configuration contains system-wide settings, EndpointConfig contains per-endpoint settings
- Retry logic should be hardcoded in adapter (Req-FR-17), not in configuration
The Solution:
- ConfigurationFileAdapter: Use correct Configuration API with Builder pattern
- HttpPollingAdapter: Hardcode retry logic, get timeout/headers from EndpointConfig
- Follow hexagonal architecture: domain model is simple, adapters handle complexity
Architecture Principle:
- Domain Model (Configuration, EndpointConfig): Simple, immutable value objects
- Adapters (HttpPollingAdapter): Handle implementation details (retry logic, connection management)
- Separation of Concerns: System-wide config vs per-endpoint config
Next Step: Apply these fixes to achieve compilation.