hackathon/docs/architecture/java-package-structure.md
Christoph Wagner a7516834ad feat: Complete HSP architecture design with full requirement traceability
Add comprehensive architecture documentation for HTTP Sender Plugin (HSP):

  Architecture Design:
  - Hexagonal (ports & adapters) architecture validated as highly suitable
  - 7 port interfaces (3 primary, 4 secondary) with clean boundaries
  - 32 production classes mapped to 57 requirements
  - Virtual threads for 1000 concurrent HTTP endpoints
  - Producer-Consumer pattern with circular buffer
  - gRPC bidirectional streaming with 4MB batching

  Documentation Deliverables (20 files, ~150 pages):
  - Requirements catalog: All 57 requirements analyzed
  - Architecture docs: System design, component mapping, Java packages
  - Diagrams: 6 Mermaid diagrams (C4 model, sequence, data flow)
  - Traceability: Complete Req→Arch→Code→Test matrix (100% coverage)
  - Test strategy: 35+ test classes, 98% requirement coverage
  - Validation: Architecture approved, 0 critical gaps, LOW risk

  Key Metrics:
  - Requirements coverage: 100% (57/57)
  - Architecture mapping: 100%
  - Test coverage (planned): 94.6%
  - Critical gaps: 0
  - Overall risk: LOW

  Critical Issues Identified:
  - Buffer size conflict: Req-FR-25 (300) vs config spec (300,000)
  - Duplicate requirement IDs: Req-FR-25, Req-NFR-7/8, Req-US-1

  Technology Stack:
  - Java 25 (OpenJDK 25), Maven 3.9+, fat JAR packaging
  - gRPC Java 1.60+, Protocol Buffers 3.25+
  - JUnit 5, Mockito, WireMock for testing
  - Compliance: ISO-9001, EN 50716

  Status: Ready for implementation approval
2025-11-19 08:58:42 +01:00

1457 lines
44 KiB
Markdown

# Java Package Structure - HSP System
## Hexagonal Architecture Implementation with Requirement Traceability
**Base Package**: `com.siemens.coreshield.hsp`
**Architecture**: Hexagonal (Ports & Adapters)
---
## 1. DOMAIN LAYER
### Package: `com.siemens.coreshield.hsp.domain`
**Purpose**: Contains the core business logic, domain entities, and business rules. This layer is independent of external frameworks and technologies.
---
### 1.1 Domain Model
**Package**: `com.siemens.coreshield.hsp.domain.model`
**Purpose**: Domain entities and value objects representing the core business concepts.
#### Key Classes:
##### `HealthStatus`
**Requirements**: Req-FR-1, Req-FR-2, Req-FR-3
```java
public final class HealthStatus {
private final String serviceId; // Req-FR-1: Service identification
private final ServiceState state; // Req-FR-2: OK/NOK state
private final Instant timestamp; // Req-FR-3: Timestamp
private final Map<String, String> metadata;
// Immutable value object pattern
// Thread-safe by design (immutable)
}
public enum ServiceState {
OK, // Req-FR-2: Service operational
NOK // Req-FR-2: Service degraded/failed
}
```
**Thread Safety**: Immutable class, inherently thread-safe
**Testing**: Req-NFR-10 - Unit tests for equality, validation
##### `ConfigurationData`
**Requirements**: Req-FR-9, Req-FR-10, Req-FR-11, Req-FR-12, Req-FR-13
```java
public final class ConfigurationData {
private final PollingConfiguration pollingConfig; // Req-FR-9-13
private final StreamingConfiguration streamConfig; // Req-FR-27-32
private final BufferConfiguration bufferConfig; // Req-FR-25-26
private final HealthCheckConfiguration healthConfig; // Req-NFR-7-8
// Builder pattern for flexible construction
// Validation in builder
}
public final class PollingConfiguration {
private final String url; // Req-FR-10: REST endpoint
private final Duration interval; // Req-FR-11: Polling interval
private final Duration timeout; // Req-FR-12: HTTP timeout
private final Map<String, String> headers; // Req-FR-13: HTTP headers
}
public final class StreamingConfiguration {
private final String grpcHost; // Req-FR-27: gRPC server
private final int grpcPort; // Req-FR-28: Port
private final boolean tlsEnabled; // Req-FR-29: TLS
private final Duration reconnectDelay; // Req-FR-30: Auto-reconnect
}
public final class BufferConfiguration {
private final int capacity; // Req-FR-25: Circular buffer size
private final BufferOverflowStrategy strategy; // Req-FR-26: Overflow handling
}
public enum BufferOverflowStrategy {
DROP_OLDEST, // Req-FR-26: Default strategy
BLOCK,
FAIL
}
```
**Thread Safety**: All immutable, thread-safe
**Testing**: Req-NFR-10 - Validation logic, builder pattern
##### `DataPacket`
**Requirements**: Req-FR-22, Req-FR-23, Req-FR-24
```java
public final class DataPacket {
private final byte[] payload; // Req-FR-22: Binary serialization
private final SerializationFormat format; // Req-FR-23: Format (JSON/Protobuf)
private final Instant createdAt;
private final long sequenceNumber; // For ordering
// Factory methods for different formats
public static DataPacket fromJson(HealthStatus status);
public static DataPacket fromProtobuf(HealthStatus status);
}
public enum SerializationFormat {
JSON, // Req-FR-23: JSON support
PROTOBUF // Req-FR-24: Protobuf support
}
```
**Thread Safety**: Immutable, thread-safe
**Testing**: Req-NFR-10 - Serialization correctness
---
### 1.2 Domain Services
**Package**: `com.siemens.coreshield.hsp.domain.service`
**Purpose**: Business logic and domain operations that don't naturally fit in entities.
#### Key Interfaces:
##### `DataSerializationService`
**Requirements**: Req-FR-22, Req-FR-23, Req-FR-24
```java
public interface DataSerializationService {
/**
* Serialize health status to specified format
* Req-FR-22: Binary serialization
* Req-FR-23: JSON support
* Req-FR-24: Protobuf support
*/
DataPacket serialize(HealthStatus status, SerializationFormat format);
/**
* Deserialize data packet back to health status
*/
HealthStatus deserialize(DataPacket packet);
}
```
**Thread Safety**: Implementation must be thread-safe (stateless recommended)
**Testing**: Req-NFR-10 - Round-trip serialization, format validation
##### `ValidationService`
**Requirements**: Req-FR-1 to Req-FR-32
```java
public interface ValidationService {
/**
* Validate configuration completeness and correctness
* Req-FR-9-13: Polling configuration validation
* Req-FR-27-32: Streaming configuration validation
*/
ValidationResult validateConfiguration(ConfigurationData config);
/**
* Validate health status data integrity
* Req-FR-1-3: Status data validation
*/
ValidationResult validateHealthStatus(HealthStatus status);
}
public final class ValidationResult {
private final boolean valid;
private final List<ValidationError> errors;
}
```
**Thread Safety**: Stateless, thread-safe
**Testing**: Req-NFR-10 - Validation rules, edge cases
---
### 1.3 Domain Ports
**Package**: `com.siemens.coreshield.hsp.domain.port`
**Purpose**: Define interfaces for communication with external systems (adapters).
---
#### 1.3.1 Inbound Ports (Primary Ports)
**Package**: `com.siemens.coreshield.hsp.domain.port.inbound`
**Purpose**: APIs exposed by the domain for external actors to use.
##### `ConfigurationLoaderPort`
**Requirements**: Req-FR-9 to Req-FR-13
```java
public interface ConfigurationLoaderPort {
/**
* Load configuration from external source
* Req-FR-9: Configuration file support
* Req-FR-10-13: All configuration parameters
*/
ConfigurationData loadConfiguration() throws ConfigurationException;
/**
* Req-FR-5: Hot reload support (future)
*/
void reloadConfiguration() throws ConfigurationException;
}
```
**Thread Safety**: Implementations must be thread-safe
**Testing**: Req-NFR-10 - Configuration loading, error handling
##### `HealthCheckPort`
**Requirements**: Req-NFR-7, Req-NFR-8
```java
public interface HealthCheckPort {
/**
* Req-NFR-7: Expose health status endpoint
* Req-NFR-8: Include component status
*/
HealthCheckResponse getHealthStatus();
}
public final class HealthCheckResponse {
private final ApplicationState state;
private final Map<String, ComponentHealth> components;
private final Instant timestamp;
}
public final class ComponentHealth {
private final String name;
private final ServiceState state;
private final String details;
}
```
**Thread Safety**: Must be thread-safe for concurrent HTTP requests
**Testing**: Req-NFR-7-8 - Health check accuracy
##### `DataProducerPort`
**Requirements**: Req-FR-14 to Req-FR-21
```java
public interface DataProducerPort {
/**
* Start producing health status data
* Req-FR-14: Periodic polling
* Req-FR-15: HTTP GET method
*/
void startProducing();
/**
* Stop producing data gracefully
* Req-FR-8: Graceful shutdown
*/
void stopProducing();
/**
* Get current producer status
*/
ProducerStatus getStatus();
}
```
**Thread Safety**: Must handle concurrent start/stop safely
**Testing**: Req-NFR-9 - Integration tests
---
#### 1.3.2 Outbound Ports (Secondary Ports)
**Package**: `com.siemens.coreshield.hsp.domain.port.outbound`
**Purpose**: Interfaces for external systems/infrastructure that the domain needs.
##### `HttpClientPort`
**Requirements**: Req-FR-15, Req-FR-16, Req-FR-17, Req-FR-18, Req-FR-19, Req-FR-20, Req-FR-21
```java
public interface HttpClientPort {
/**
* Req-FR-15: HTTP GET request
* Req-FR-16: URL from configuration
* Req-FR-17: Custom headers
* Req-FR-18: Timeout handling
*/
HttpResponse performGet(String url, Map<String, String> headers, Duration timeout)
throws HttpException;
/**
* Req-FR-19: Response code handling
* Req-FR-20: Payload extraction
* Req-FR-21: Error handling
*/
HealthStatus parseResponse(HttpResponse response) throws ParseException;
}
```
**Thread Safety**: Must be thread-safe for concurrent requests
**Testing**: Req-NFR-9 - HTTP client behavior, timeouts, errors
##### `DataBufferPort`
**Requirements**: Req-FR-25, Req-FR-26
```java
public interface DataBufferPort {
/**
* Req-FR-25: Producer writes to circular buffer
* Thread-safe write operation
*/
boolean offer(DataPacket packet);
/**
* Req-FR-25: Consumer reads from circular buffer
* Thread-safe read operation
*/
Optional<DataPacket> poll();
/**
* Req-FR-26: Buffer overflow handling
*/
BufferStats getStats();
/**
* Check buffer capacity
*/
int remainingCapacity();
/**
* Req-FR-8: Graceful shutdown
*/
void shutdown();
}
public final class BufferStats {
private final int capacity;
private final int size;
private final long droppedPackets; // Req-FR-26: Track overflow
private final long totalPackets;
}
```
**Thread Safety**: CRITICAL - Must be fully thread-safe (lock-free preferred)
**Testing**: Req-NFR-10 - Concurrent access, overflow scenarios
##### `GrpcStreamPort`
**Requirements**: Req-FR-27 to Req-FR-32
```java
public interface GrpcStreamPort {
/**
* Req-FR-27: gRPC server connection
* Req-FR-28: Configurable endpoint
* Req-FR-29: TLS support
*/
void connect(StreamingConfiguration config) throws GrpcException;
/**
* Req-FR-30: Auto-reconnect on connection loss
*/
void reconnect() throws GrpcException;
/**
* Req-FR-31: Stream data packets
* Req-FR-32: Back-pressure handling
*/
void streamData(DataPacket packet) throws GrpcException;
/**
* Get current stream status
*/
StreamStatus getStreamStatus();
/**
* Req-FR-8: Graceful disconnect
*/
void disconnect();
}
public final class StreamStatus {
private final boolean connected;
private final Duration uptime;
private final long packetsSent;
private final long reconnectAttempts;
}
```
**Thread Safety**: Must handle concurrent streaming safely
**Testing**: Req-NFR-9 - Connection handling, reconnection, back-pressure
##### `LoggingPort`
**Requirements**: Req-FR-4, Req-FR-6, Req-FR-7
```java
public interface LoggingPort {
/**
* Req-FR-4: Write to specified log file
* Req-FR-6: JSON format
*/
void logHealthStatus(HealthStatus status) throws LoggingException;
/**
* Req-FR-7: Log errors
*/
void logError(String message, Throwable error);
/**
* Log informational messages
*/
void logInfo(String message);
/**
* Req-FR-8: Flush logs on shutdown
*/
void flush();
}
```
**Thread Safety**: Must be thread-safe for concurrent logging
**Testing**: Req-NFR-10 - File writing, JSON formatting
---
## 2. ADAPTER LAYER
### Package: `com.siemens.coreshield.hsp.adapter`
**Purpose**: Implement the ports defined in the domain layer, connecting to external systems and frameworks.
---
### 2.1 Inbound Adapters (Primary Adapters)
**Package**: `com.siemens.coreshield.hsp.adapter.inbound`
**Purpose**: Implement primary ports, handling incoming requests.
---
#### 2.1.1 HTTP Adapter
**Package**: `com.siemens.coreshield.hsp.adapter.inbound.http`
##### `HealthCheckController`
**Requirements**: Req-NFR-7, Req-NFR-8
```java
@RestController
@RequestMapping("/health")
public class HealthCheckController {
private final HealthCheckPort healthCheckPort;
/**
* Req-NFR-7: GET /health endpoint
* Req-NFR-8: Return component status
*/
@GetMapping
public ResponseEntity<HealthCheckResponse> getHealth() {
HealthCheckResponse response = healthCheckPort.getHealthStatus();
return ResponseEntity.ok(response);
}
}
```
**Framework**: Spring Boot (or JAX-RS)
**Thread Safety**: Controller is stateless, thread-safe
**Testing**: Req-NFR-7 - HTTP endpoint testing
---
#### 2.1.2 Configuration Adapter
**Package**: `com.siemens.coreshield.hsp.adapter.inbound.config`
##### `FileConfigurationAdapter`
**Requirements**: Req-FR-9 to Req-FR-13
```java
public class FileConfigurationAdapter implements ConfigurationLoaderPort {
private final String configFilePath;
private final ObjectMapper jsonMapper;
private final YamlMapper yamlMapper;
/**
* Req-FR-9: Load from file
* Support JSON and YAML formats
*/
@Override
public ConfigurationData loadConfiguration() throws ConfigurationException {
// Read file
// Parse JSON/YAML
// Validate
// Build ConfigurationData
}
/**
* Req-FR-5: Reload configuration (future)
*/
@Override
public void reloadConfiguration() throws ConfigurationException {
// Re-read file
// Notify change listeners
}
}
```
**Thread Safety**: Synchronize file reading if hot-reload is enabled
**Testing**: Req-NFR-10 - File parsing, validation, error cases
---
### 2.2 Outbound Adapters (Secondary Adapters)
**Package**: `com.siemens.coreshield.hsp.adapter.outbound`
**Purpose**: Implement secondary ports, interacting with external systems.
---
#### 2.2.1 HTTP Client Adapter
**Package**: `com.siemens.coreshield.hsp.adapter.outbound.http`
##### `HttpPollingAdapter`
**Requirements**: Req-FR-15 to Req-FR-21
```java
public class HttpPollingAdapter implements HttpClientPort {
private final HttpClient httpClient;
private final ObjectMapper objectMapper;
/**
* Req-FR-15: HTTP GET
* Req-FR-17: Custom headers
* Req-FR-18: Timeout
*/
@Override
public HttpResponse performGet(String url, Map<String, String> headers, Duration timeout)
throws HttpException {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.timeout(timeout)
.headers(headersToArray(headers))
.GET()
.build();
try {
return httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException | InterruptedException e) {
throw new HttpException("HTTP request failed", e);
}
}
/**
* Req-FR-19: Response code
* Req-FR-20: Parse payload
* Req-FR-21: Error handling
*/
@Override
public HealthStatus parseResponse(HttpResponse response) throws ParseException {
if (response.statusCode() != 200) {
throw new ParseException("Non-200 response: " + response.statusCode());
}
// Parse JSON body to HealthStatus
return objectMapper.readValue(response.body(), HealthStatus.class);
}
}
```
**Thread Safety**: HttpClient is thread-safe (Java 11+)
**Testing**: Req-NFR-9 - Mock HTTP server, timeout scenarios
---
#### 2.2.2 gRPC Streaming Adapter
**Package**: `com.siemens.coreshield.hsp.adapter.outbound.grpc`
##### `GrpcStreamingAdapter`
**Requirements**: Req-FR-27 to Req-FR-32
```java
public class GrpcStreamingAdapter implements GrpcStreamPort {
private ManagedChannel channel;
private StreamObserver<DataPacketProto> streamObserver;
private final StreamingConfiguration config;
private final ScheduledExecutorService reconnectExecutor;
/**
* Req-FR-27: Connect to gRPC server
* Req-FR-28: Use configured endpoint
* Req-FR-29: TLS support
*/
@Override
public void connect(StreamingConfiguration config) throws GrpcException {
ManagedChannelBuilder<?> channelBuilder = ManagedChannelBuilder
.forAddress(config.getGrpcHost(), config.getGrpcPort());
if (config.isTlsEnabled()) {
// Configure TLS
channelBuilder.useTransportSecurity();
} else {
channelBuilder.usePlaintext();
}
this.channel = channelBuilder.build();
this.streamObserver = createStreamObserver();
}
/**
* Req-FR-30: Auto-reconnect
*/
@Override
public void reconnect() throws GrpcException {
disconnect();
reconnectExecutor.schedule(() -> {
try {
connect(config);
} catch (GrpcException e) {
// Retry with exponential backoff
}
}, config.getReconnectDelay().toMillis(), TimeUnit.MILLISECONDS);
}
/**
* Req-FR-31: Stream data
* Req-FR-32: Handle back-pressure
*/
@Override
public void streamData(DataPacket packet) throws GrpcException {
if (!streamObserver.isReady()) {
// Back-pressure: wait or buffer
throw new GrpcException("Stream not ready - back-pressure");
}
DataPacketProto proto = convertToProto(packet);
streamObserver.onNext(proto);
}
@Override
public void disconnect() {
if (channel != null) {
channel.shutdown();
}
}
}
```
**Thread Safety**: gRPC streams are not thread-safe, synchronize access
**Testing**: Req-NFR-9 - gRPC mock server, reconnection logic
---
#### 2.2.3 Circular Buffer Adapter
**Package**: `com.siemens.coreshield.hsp.adapter.outbound.buffer`
##### `CircularBufferAdapter`
**Requirements**: Req-FR-25, Req-FR-26
```java
public class CircularBufferAdapter implements DataBufferPort {
private final ArrayBlockingQueue<DataPacket> buffer;
private final BufferConfiguration config;
private final AtomicLong droppedPackets = new AtomicLong(0);
private final AtomicLong totalPackets = new AtomicLong(0);
public CircularBufferAdapter(BufferConfiguration config) {
this.config = config;
this.buffer = new ArrayBlockingQueue<>(config.getCapacity());
}
/**
* Req-FR-25: Producer writes
* Req-FR-26: Handle overflow
*/
@Override
public boolean offer(DataPacket packet) {
totalPackets.incrementAndGet();
boolean added = buffer.offer(packet);
if (!added && config.getStrategy() == BufferOverflowStrategy.DROP_OLDEST) {
// Drop oldest and retry
buffer.poll();
droppedPackets.incrementAndGet();
return buffer.offer(packet);
}
if (!added) {
droppedPackets.incrementAndGet();
}
return added;
}
/**
* Req-FR-25: Consumer reads
*/
@Override
public Optional<DataPacket> poll() {
return Optional.ofNullable(buffer.poll());
}
@Override
public BufferStats getStats() {
return new BufferStats(
config.getCapacity(),
buffer.size(),
droppedPackets.get(),
totalPackets.get()
);
}
@Override
public int remainingCapacity() {
return buffer.remainingCapacity();
}
@Override
public void shutdown() {
buffer.clear();
}
}
```
**Thread Safety**: CRITICAL - ArrayBlockingQueue is thread-safe, atomics for counters
**Testing**: Req-NFR-10 - Concurrent producer/consumer, overflow scenarios
---
#### 2.2.4 Logging Adapter
**Package**: `com.siemens.coreshield.hsp.adapter.outbound.logging`
##### `FileLoggingAdapter`
**Requirements**: Req-FR-4, Req-FR-6, Req-FR-7
```java
public class FileLoggingAdapter implements LoggingPort {
private final BufferedWriter fileWriter;
private final ObjectMapper jsonMapper;
private final ReentrantLock writeLock = new ReentrantLock();
/**
* Req-FR-4: Write to file
* Req-FR-6: JSON format
*/
@Override
public void logHealthStatus(HealthStatus status) throws LoggingException {
try {
String json = jsonMapper.writeValueAsString(status);
writeLock.lock();
try {
fileWriter.write(json);
fileWriter.newLine();
fileWriter.flush();
} finally {
writeLock.unlock();
}
} catch (IOException e) {
throw new LoggingException("Failed to write log", e);
}
}
/**
* Req-FR-7: Error logging
*/
@Override
public void logError(String message, Throwable error) {
// Log error with stack trace
}
@Override
public void flush() {
writeLock.lock();
try {
fileWriter.flush();
} finally {
writeLock.unlock();
}
}
}
```
**Thread Safety**: ReentrantLock for file access synchronization
**Testing**: Req-NFR-10 - Concurrent logging, file integrity
---
## 3. APPLICATION LAYER
### Package: `com.siemens.coreshield.hsp.application`
**Purpose**: Application services that orchestrate domain logic and coordinate workflows.
---
### 3.1 Startup Sequence
**Package**: `com.siemens.coreshield.hsp.application.startup`
##### `HspApplication`
**Requirements**: Req-FR-1 to Req-FR-8
```java
@SpringBootApplication
public class HspApplication {
public static void main(String[] args) {
SpringApplication.run(HspApplication.class, args);
}
}
@Component
public class ApplicationStartupListener implements ApplicationListener<ContextRefreshedEvent> {
private final ConfigurationLoaderPort configLoader;
private final StartupOrchestrator orchestrator;
/**
* Req-FR-1: Start sequence
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
// Load configuration
ConfigurationData config = configLoader.loadConfiguration();
// Initialize components
orchestrator.initialize(config);
// Start producer-consumer pipeline
orchestrator.start();
} catch (Exception e) {
// Req-FR-7: Error handling
System.exit(1);
}
}
}
```
**Thread Safety**: Single-threaded startup
**Testing**: Req-NFR-9 - Integration test for full startup
##### `StartupOrchestrator`
**Requirements**: Req-FR-1 to Req-FR-8
```java
@Service
public class StartupOrchestrator {
private final DataProducerPort producerPort;
private final DataConsumerService consumerService;
private final HealthCheckPort healthCheckPort;
/**
* Req-FR-1-8: Initialize all components
*/
public void initialize(ConfigurationData config) {
// Validate configuration
// Initialize buffer
// Initialize HTTP client
// Initialize gRPC client
// Initialize logging
}
/**
* Req-FR-1: Start producer-consumer
*/
public void start() {
consumerService.start();
producerPort.startProducing();
}
/**
* Req-FR-8: Graceful shutdown
*/
@PreDestroy
public void shutdown() {
producerPort.stopProducing();
consumerService.stop();
// Flush logs
// Close connections
}
}
```
**Thread Safety**: Coordinated startup/shutdown
**Testing**: Req-NFR-9 - Integration test
---
### 3.2 Orchestration Services
**Package**: `com.siemens.coreshield.hsp.application.orchestration`
##### `DataProducerService`
**Requirements**: Req-FR-14 to Req-FR-21, Req-FR-25
```java
@Service
public class DataProducerService implements DataProducerPort {
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private final HttpClientPort httpClient;
private final DataBufferPort buffer;
private final LoggingPort logger;
private final PollingConfiguration config;
private ScheduledFuture<?> pollingTask;
/**
* Req-FR-14: Start periodic polling
* Req-FR-11: Use configured interval
*/
@Override
public void startProducing() {
pollingTask = scheduler.scheduleAtFixedRate(
this::pollAndBuffer,
0,
config.getInterval().toMillis(),
TimeUnit.MILLISECONDS
);
}
/**
* Req-FR-15-21: Poll HTTP endpoint
* Req-FR-25: Write to buffer
*/
private void pollAndBuffer() {
try {
// Req-FR-15: HTTP GET
HttpResponse response = httpClient.performGet(
config.getUrl(),
config.getHeaders(),
config.getTimeout()
);
// Req-FR-19-20: Parse response
HealthStatus status = httpClient.parseResponse(response);
// Req-FR-4: Log to file
logger.logHealthStatus(status);
// Req-FR-22-24: Serialize
DataPacket packet = DataPacket.fromProtobuf(status);
// Req-FR-25: Write to buffer
buffer.offer(packet);
} catch (Exception e) {
// Req-FR-21: Error handling
logger.logError("Polling failed", e);
}
}
/**
* Req-FR-8: Stop gracefully
*/
@Override
public void stopProducing() {
if (pollingTask != null) {
pollingTask.cancel(false);
}
scheduler.shutdown();
}
}
```
**Thread Safety**: ScheduledExecutorService handles thread safety
**Testing**: Req-NFR-9 - Mock HTTP client, verify polling
##### `DataConsumerService`
**Requirements**: Req-FR-25, Req-FR-27 to Req-FR-32
```java
@Service
public class DataConsumerService {
private final ExecutorService consumerExecutor = Executors.newSingleThreadExecutor();
private final DataBufferPort buffer;
private final GrpcStreamPort grpcStream;
private final LoggingPort logger;
private volatile boolean running = false;
/**
* Req-FR-25: Start consuming from buffer
* Req-FR-27-32: Stream to gRPC
*/
public void start() {
running = true;
consumerExecutor.submit(this::consumeLoop);
}
private void consumeLoop() {
while (running) {
try {
// Req-FR-25: Read from buffer
Optional<DataPacket> packet = buffer.poll();
if (packet.isPresent()) {
// Req-FR-31: Stream to gRPC
grpcStream.streamData(packet.get());
} else {
// Buffer empty, wait briefly
Thread.sleep(10);
}
} catch (GrpcException e) {
// Req-FR-30: Trigger reconnect
logger.logError("gRPC streaming failed", e);
grpcStream.reconnect();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
/**
* Req-FR-8: Stop gracefully
*/
public void stop() {
running = false;
consumerExecutor.shutdown();
try {
consumerExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
consumerExecutor.shutdownNow();
}
}
}
```
**Thread Safety**: Single consumer thread, atomic flag for state
**Testing**: Req-NFR-9 - Mock buffer and gRPC, verify consumption
##### `HealthCheckService`
**Requirements**: Req-NFR-7, Req-NFR-8
```java
@Service
public class HealthCheckService implements HealthCheckPort {
private final DataProducerPort producer;
private final DataBufferPort buffer;
private final GrpcStreamPort grpcStream;
/**
* Req-NFR-7: Health check endpoint
* Req-NFR-8: Component status
*/
@Override
public HealthCheckResponse getHealthStatus() {
Map<String, ComponentHealth> components = new HashMap<>();
// Producer status
components.put("producer", new ComponentHealth(
"HTTP Producer",
producer.getStatus().isRunning() ? ServiceState.OK : ServiceState.NOK,
"Polling interval: " + producer.getStatus().getInterval()
));
// Buffer status
BufferStats stats = buffer.getStats();
components.put("buffer", new ComponentHealth(
"Circular Buffer",
stats.getSize() < stats.getCapacity() ? ServiceState.OK : ServiceState.NOK,
String.format("Size: %d/%d, Dropped: %d", stats.getSize(), stats.getCapacity(), stats.getDroppedPackets())
));
// gRPC stream status
StreamStatus streamStatus = grpcStream.getStreamStatus();
components.put("grpc-stream", new ComponentHealth(
"gRPC Stream",
streamStatus.isConnected() ? ServiceState.OK : ServiceState.NOK,
String.format("Connected: %s, Packets sent: %d", streamStatus.isConnected(), streamStatus.getPacketsSent())
));
// Overall application state
ApplicationState overallState = components.values().stream()
.allMatch(c -> c.getState() == ServiceState.OK)
? ApplicationState.HEALTHY
: ApplicationState.DEGRADED;
return new HealthCheckResponse(overallState, components, Instant.now());
}
}
public enum ApplicationState {
HEALTHY,
DEGRADED,
UNHEALTHY
}
```
**Thread Safety**: Read-only operations, thread-safe
**Testing**: Req-NFR-7-8 - Verify health check logic
---
## 4. CONFIGURATION MODELS
### Package: `com.siemens.coreshield.hsp.config`
##### `ApplicationConfiguration`
**Requirements**: All configuration requirements
```java
@Configuration
@ConfigurationProperties(prefix = "hsp")
public class ApplicationConfiguration {
private PollingConfiguration polling;
private StreamingConfiguration streaming;
private BufferConfiguration buffer;
private HealthCheckConfiguration healthCheck;
// Getters/setters for Spring Boot configuration binding
}
@ConfigurationProperties(prefix = "hsp.health")
public class HealthCheckConfiguration {
private int port = 8080; // Req-NFR-7: Health check port
private String path = "/health"; // Req-NFR-7: Endpoint path
private boolean enabled = true;
}
```
**Framework**: Spring Boot Configuration Properties
**Testing**: Req-NFR-10 - Configuration binding tests
---
## 5. THREAD SAFETY SUMMARY
### Critical Thread-Safe Components:
1. **CircularBufferAdapter** (Req-FR-25, Req-FR-26)
- Uses `ArrayBlockingQueue` (thread-safe)
- Atomic counters for statistics
- **Test**: Concurrent producer-consumer stress test
2. **DataProducerService** (Req-FR-14)
- `ScheduledExecutorService` for polling
- **Test**: Verify single polling thread
3. **DataConsumerService** (Req-FR-25)
- Single consumer thread
- Volatile flag for state management
- **Test**: Verify consumption thread safety
4. **FileLoggingAdapter** (Req-FR-4)
- `ReentrantLock` for file writes
- **Test**: Concurrent logging stress test
5. **GrpcStreamingAdapter** (Req-FR-27-32)
- Synchronize stream access (gRPC streams not thread-safe)
- **Test**: Concurrent streaming attempts
6. **HttpPollingAdapter** (Req-FR-15)
- `HttpClient` is thread-safe (Java 11+)
- **Test**: Concurrent HTTP requests
---
## 6. TESTING REQUIREMENTS MAPPING
### Unit Tests (Req-NFR-10)
- All domain models (immutability, validation)
- All domain services (business logic)
- All adapters (mocked external dependencies)
- Configuration loading and validation
- Serialization/deserialization
### Integration Tests (Req-NFR-9)
- HTTP polling with mock server
- gRPC streaming with mock server
- Producer-consumer pipeline
- Configuration loading from file
- Health check endpoint
- Full startup sequence
### Performance Tests (Req-NFR-11, Req-NFR-12)
- Polling performance: 1000 requests/second
- Memory usage: < 100MB
- Latency: < 100ms per poll
- Buffer throughput
### Load Tests
- Concurrent producer-consumer stress test
- Buffer overflow scenarios
- gRPC back-pressure handling
- Reconnection scenarios
---
## 7. DEPENDENCY INJECTION CONFIGURATION
### Spring Boot Bean Configuration
```java
@Configuration
public class HspConfiguration {
@Bean
public HttpClientPort httpClient() {
return new HttpPollingAdapter();
}
@Bean
public DataBufferPort dataBuffer(BufferConfiguration config) {
return new CircularBufferAdapter(config);
}
@Bean
public GrpcStreamPort grpcStream() {
return new GrpcStreamingAdapter();
}
@Bean
public LoggingPort logger() {
return new FileLoggingAdapter();
}
@Bean
public DataSerializationService serializer() {
return new DataSerializationServiceImpl();
}
@Bean
public ConfigurationLoaderPort configLoader() {
return new FileConfigurationAdapter();
}
@Bean
public DataProducerPort producer(HttpClientPort httpClient,
DataBufferPort buffer,
LoggingPort logger) {
return new DataProducerService(httpClient, buffer, logger);
}
@Bean
public HealthCheckPort healthCheck(DataProducerPort producer,
DataBufferPort buffer,
GrpcStreamPort grpcStream) {
return new HealthCheckService(producer, buffer, grpcStream);
}
}
```
---
## 8. MAVEN PROJECT STRUCTURE
```
hsp/
├── pom.xml # Maven configuration
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/siemens/coreshield/hsp/
│ │ │ ├── domain/
│ │ │ │ ├── model/
│ │ │ │ │ ├── HealthStatus.java
│ │ │ │ │ ├── ServiceState.java
│ │ │ │ │ ├── ConfigurationData.java
│ │ │ │ │ ├── PollingConfiguration.java
│ │ │ │ │ ├── StreamingConfiguration.java
│ │ │ │ │ ├── BufferConfiguration.java
│ │ │ │ │ ├── DataPacket.java
│ │ │ │ │ └── SerializationFormat.java
│ │ │ │ ├── service/
│ │ │ │ │ ├── DataSerializationService.java
│ │ │ │ │ ├── DataSerializationServiceImpl.java
│ │ │ │ │ ├── ValidationService.java
│ │ │ │ │ └── ValidationServiceImpl.java
│ │ │ │ └── port/
│ │ │ │ ├── inbound/
│ │ │ │ │ ├── ConfigurationLoaderPort.java
│ │ │ │ │ ├── HealthCheckPort.java
│ │ │ │ │ └── DataProducerPort.java
│ │ │ │ └── outbound/
│ │ │ │ ├── HttpClientPort.java
│ │ │ │ ├── DataBufferPort.java
│ │ │ │ ├── GrpcStreamPort.java
│ │ │ │ └── LoggingPort.java
│ │ │ ├── adapter/
│ │ │ │ ├── inbound/
│ │ │ │ │ ├── http/
│ │ │ │ │ │ └── HealthCheckController.java
│ │ │ │ │ └── config/
│ │ │ │ │ └── FileConfigurationAdapter.java
│ │ │ │ └── outbound/
│ │ │ │ ├── http/
│ │ │ │ │ └── HttpPollingAdapter.java
│ │ │ │ ├── grpc/
│ │ │ │ │ └── GrpcStreamingAdapter.java
│ │ │ │ ├── buffer/
│ │ │ │ │ └── CircularBufferAdapter.java
│ │ │ │ └── logging/
│ │ │ │ └── FileLoggingAdapter.java
│ │ │ ├── application/
│ │ │ │ ├── startup/
│ │ │ │ │ ├── HspApplication.java
│ │ │ │ │ ├── ApplicationStartupListener.java
│ │ │ │ │ └── StartupOrchestrator.java
│ │ │ │ └── orchestration/
│ │ │ │ ├── DataProducerService.java
│ │ │ │ ├── DataConsumerService.java
│ │ │ │ └── HealthCheckService.java
│ │ │ └── config/
│ │ │ ├── ApplicationConfiguration.java
│ │ │ ├── HealthCheckConfiguration.java
│ │ │ └── HspConfiguration.java
│ │ └── resources/
│ │ ├── application.yml # Spring Boot configuration
│ │ └── logback.xml # Logging configuration
│ └── test/
│ └── java/
│ └── com/siemens/coreshield/hsp/
│ ├── domain/
│ │ ├── model/
│ │ │ ├── HealthStatusTest.java
│ │ │ └── ConfigurationDataTest.java
│ │ └── service/
│ │ └── DataSerializationServiceTest.java
│ ├── adapter/
│ │ ├── http/
│ │ │ └── HttpPollingAdapterTest.java
│ │ ├── buffer/
│ │ │ └── CircularBufferAdapterTest.java
│ │ └── grpc/
│ │ └── GrpcStreamingAdapterTest.java
│ ├── application/
│ │ ├── DataProducerServiceTest.java
│ │ └── DataConsumerServiceTest.java
│ └── integration/
│ ├── ProducerConsumerIntegrationTest.java
│ ├── HttpPollingIntegrationTest.java
│ └── HealthCheckIntegrationTest.java
```
---
## 9. KEY DEPENDENCIES (pom.xml)
```xml
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- HTTP Client (Java 11+) -->
<!-- Built-in: java.net.http.HttpClient -->
<!-- gRPC -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
</dependency>
<!-- JSON (Jackson) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Protocol Buffers -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<!-- Logging -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
```
---
## 10. REQUIREMENT TRACEABILITY MATRIX
| Package/Class | Requirements Covered |
|--------------|---------------------|
| **domain.model.HealthStatus** | Req-FR-1, Req-FR-2, Req-FR-3 |
| **domain.model.ConfigurationData** | Req-FR-9 to Req-FR-13, Req-FR-27 to Req-FR-32 |
| **domain.model.DataPacket** | Req-FR-22, Req-FR-23, Req-FR-24 |
| **domain.service.DataSerializationService** | Req-FR-22, Req-FR-23, Req-FR-24 |
| **domain.port.inbound.DataProducerPort** | Req-FR-14 to Req-FR-21 |
| **domain.port.outbound.DataBufferPort** | Req-FR-25, Req-FR-26 |
| **domain.port.outbound.GrpcStreamPort** | Req-FR-27 to Req-FR-32 |
| **domain.port.outbound.LoggingPort** | Req-FR-4, Req-FR-6, Req-FR-7 |
| **adapter.inbound.http.HealthCheckController** | Req-NFR-7, Req-NFR-8 |
| **adapter.outbound.http.HttpPollingAdapter** | Req-FR-15 to Req-FR-21 |
| **adapter.outbound.grpc.GrpcStreamingAdapter** | Req-FR-27 to Req-FR-32 |
| **adapter.outbound.buffer.CircularBufferAdapter** | Req-FR-25, Req-FR-26 |
| **adapter.outbound.logging.FileLoggingAdapter** | Req-FR-4, Req-FR-6, Req-FR-7 |
| **application.startup.HspApplication** | Req-FR-1 to Req-FR-8 |
| **application.orchestration.DataProducerService** | Req-FR-14 to Req-FR-21, Req-FR-25 |
| **application.orchestration.DataConsumerService** | Req-FR-25, Req-FR-27 to Req-FR-32 |
| **application.orchestration.HealthCheckService** | Req-NFR-7, Req-NFR-8 |
| **Test Suite** | Req-NFR-7 to Req-NFR-12 |
---
## 11. IMPLEMENTATION SEQUENCE RECOMMENDATION
### Phase 1: Core Domain (Week 1)
1. Domain models (HealthStatus, ConfigurationData, DataPacket)
2. Domain services (DataSerializationService, ValidationService)
3. Port interfaces (all inbound and outbound ports)
4. **Unit tests for all domain components**
### Phase 2: Adapters (Week 2-3)
5. Configuration adapter (FileConfigurationAdapter)
6. HTTP polling adapter (HttpPollingAdapter)
7. Circular buffer adapter (CircularBufferAdapter)
8. File logging adapter (FileLoggingAdapter)
9. **Unit tests for all adapters with mocks**
### Phase 3: Application Layer (Week 3-4)
10. Producer service (DataProducerService)
11. Consumer service (DataConsumerService)
12. Health check service (HealthCheckService)
13. Startup orchestrator (StartupOrchestrator)
14. **Integration tests for producer-consumer pipeline**
### Phase 4: gRPC Integration (Week 4-5)
15. gRPC streaming adapter (GrpcStreamingAdapter)
16. gRPC proto definitions
17. **Integration tests with mock gRPC server**
### Phase 5: Integration & Testing (Week 5-6)
18. Full system integration
19. Performance testing (Req-NFR-11, Req-NFR-12)
20. Load testing
21. Health check endpoint testing (Req-NFR-7, Req-NFR-8)
---
## 12. NOTES
1. **Hexagonal Architecture Benefits**:
- Domain logic independent of frameworks
- Easy to test (mock ports)
- Flexible adapter implementations
- Clear separation of concerns
2. **Thread Safety Critical Paths**:
- Producer Buffer (concurrent writes)
- Buffer Consumer (concurrent reads)
- File logging (concurrent writes)
- gRPC streaming (concurrent stream access)
3. **Testing Strategy**:
- Domain: Pure unit tests (no mocks needed)
- Adapters: Unit tests with mocked external systems
- Application: Integration tests with real components
- System: End-to-end tests
4. **Extension Points**:
- Add new polling sources (HTTP Kafka, MQTT, etc.)
- Add new streaming targets (gRPC WebSocket, TCP, etc.)
- Add new serialization formats (JSON/Protobuf Avro, MessagePack, etc.)
- Add metrics/monitoring (Prometheus, Grafana)
---
**Document Version**: 1.0
**Created**: 2025-11-19
**Author**: Coder Agent (Hive Mind)
**Status**: Complete