Implementierung für M2 vorläufig abgeschlossen
This commit is contained in:
@@ -5,11 +5,20 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import de.gecheckt.pdf.umbenenner.adapter.inbound.cli.SchedulerBatchCommand;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.outbound.configuration.PropertiesConfigurationPortAdapter;
|
||||
import de.gecheckt.pdf.umbenenner.adapter.outbound.lock.FilesystemRunLockPortAdapter;
|
||||
import de.gecheckt.pdf.umbenenner.application.config.InvalidStartConfigurationException;
|
||||
import de.gecheckt.pdf.umbenenner.application.config.StartConfigurationValidator;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.BatchRunOutcome;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.in.RunBatchProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.ConfigurationPort;
|
||||
import de.gecheckt.pdf.umbenenner.application.usecase.NoOpRunBatchProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.application.port.out.RunLockPort;
|
||||
import de.gecheckt.pdf.umbenenner.application.usecase.M2BatchRunProcessingUseCase;
|
||||
import de.gecheckt.pdf.umbenenner.domain.model.BatchRunContext;
|
||||
import de.gecheckt.pdf.umbenenner.domain.model.RunId;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Manual bootstrap runner that constructs the object graph and drives the startup flow.
|
||||
@@ -17,7 +26,7 @@ import de.gecheckt.pdf.umbenenner.application.usecase.NoOpRunBatchProcessingUseC
|
||||
* AP-003 Implementation: Creates all required components using plain Java constructor injection
|
||||
* and executes the minimal no-op batch processing path.
|
||||
* <p>
|
||||
* AP-005: Integrates configuration loading via PropertiesConfigurationPortAdapter.
|
||||
* AP-005: CLI adapter and bootstrap wiring for M2 batch orchestration with run lock integration.
|
||||
* <p>
|
||||
* AP-006: Validates configuration before processing begins, returns exit code 1 on invalid config.
|
||||
*/
|
||||
@@ -26,6 +35,7 @@ public class BootstrapRunner {
|
||||
private static final Logger LOG = LogManager.getLogger(BootstrapRunner.class);
|
||||
|
||||
private final ConfigurationPortFactory configPortFactory;
|
||||
private final RunLockPortFactory runLockPortFactory;
|
||||
private final ValidatorFactory validatorFactory;
|
||||
private final UseCaseFactory useCaseFactory;
|
||||
private final CommandFactory commandFactory;
|
||||
@@ -38,6 +48,14 @@ public class BootstrapRunner {
|
||||
ConfigurationPort create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for creating a RunLockPort from the configured lock file path.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface RunLockPortFactory {
|
||||
RunLockPort create(Path lockFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for creating a StartConfigurationValidator.
|
||||
*/
|
||||
@@ -51,7 +69,7 @@ public class BootstrapRunner {
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface UseCaseFactory {
|
||||
RunBatchProcessingUseCase create(ConfigurationPort configPort);
|
||||
RunBatchProcessingUseCase create(ConfigurationPort configPort, RunLockPort runLockPort);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,11 +82,14 @@ public class BootstrapRunner {
|
||||
|
||||
/**
|
||||
* Creates the BootstrapRunner with default factories for production use.
|
||||
* <p>
|
||||
* AP-006: Uses FilesystemRunLockPortAdapter for file-based exclusive run locking.
|
||||
*/
|
||||
public BootstrapRunner() {
|
||||
this.configPortFactory = PropertiesConfigurationPortAdapter::new;
|
||||
this.runLockPortFactory = FilesystemRunLockPortAdapter::new;
|
||||
this.validatorFactory = StartConfigurationValidator::new;
|
||||
this.useCaseFactory = NoOpRunBatchProcessingUseCase::new;
|
||||
this.useCaseFactory = M2BatchRunProcessingUseCase::new;
|
||||
this.commandFactory = SchedulerBatchCommand::new;
|
||||
}
|
||||
|
||||
@@ -76,15 +97,18 @@ public class BootstrapRunner {
|
||||
* Creates the BootstrapRunner with custom factories for testing.
|
||||
*
|
||||
* @param configPortFactory factory for creating ConfigurationPort instances
|
||||
* @param runLockPortFactory factory for creating RunLockPort instances
|
||||
* @param validatorFactory factory for creating StartConfigurationValidator instances
|
||||
* @param useCaseFactory factory for creating RunBatchProcessingUseCase instances
|
||||
* @param commandFactory factory for creating SchedulerBatchCommand instances
|
||||
*/
|
||||
public BootstrapRunner(ConfigurationPortFactory configPortFactory,
|
||||
RunLockPortFactory runLockPortFactory,
|
||||
ValidatorFactory validatorFactory,
|
||||
UseCaseFactory useCaseFactory,
|
||||
CommandFactory commandFactory) {
|
||||
this.configPortFactory = configPortFactory;
|
||||
this.runLockPortFactory = runLockPortFactory;
|
||||
this.validatorFactory = validatorFactory;
|
||||
this.useCaseFactory = useCaseFactory;
|
||||
this.commandFactory = commandFactory;
|
||||
@@ -112,20 +136,37 @@ public class BootstrapRunner {
|
||||
StartConfigurationValidator validator = validatorFactory.create();
|
||||
validator.validate(config);
|
||||
|
||||
// Step 4: Create the use case with the configuration port (application layer)
|
||||
RunBatchProcessingUseCase useCase = useCaseFactory.create(configPort);
|
||||
// Step 4: Create the run lock port from the validated config (AP-006)
|
||||
RunLockPort runLockPort = runLockPortFactory.create(config.runtimeLockFile());
|
||||
|
||||
// Step 5: Create the CLI command adapter with the use case
|
||||
// Step 5: Create the batch run context (M2-AP-003)
|
||||
// Generate a unique run ID and initialize the run context
|
||||
RunId runId = new RunId(UUID.randomUUID().toString());
|
||||
BatchRunContext runContext = new BatchRunContext(runId, Instant.now());
|
||||
LOG.info("Batch run started. RunId: {}", runId);
|
||||
|
||||
// Step 6: Create the use case with the configuration port and run lock (application layer)
|
||||
RunBatchProcessingUseCase useCase = useCaseFactory.create(configPort, runLockPort);
|
||||
|
||||
// Step 7: Create the CLI command adapter with the use case
|
||||
SchedulerBatchCommand command = commandFactory.create(useCase);
|
||||
|
||||
// Step 6: Execute the command
|
||||
boolean success = command.run();
|
||||
// Step 8: Execute the command with the run context and handle the outcome
|
||||
BatchRunOutcome outcome = command.run(runContext);
|
||||
|
||||
if (success) {
|
||||
LOG.info("No-op startup path completed successfully.");
|
||||
// Mark run as completed (AP-003)
|
||||
runContext.setEndInstant(Instant.now());
|
||||
|
||||
if (outcome.isSuccess()) {
|
||||
LOG.info("Batch run completed successfully. RunId: {}", runContext.runId());
|
||||
return 0;
|
||||
} else if (outcome.isLockUnavailable()) {
|
||||
LOG.warn("Batch run aborted: another instance is already running. RunId: {}", runContext.runId());
|
||||
return 1;
|
||||
} else {
|
||||
LOG.error("Batch run failed. RunId: {}", runContext.runId());
|
||||
return 1;
|
||||
}
|
||||
|
||||
return success ? 0 : 1;
|
||||
} catch (InvalidStartConfigurationException e) {
|
||||
// Controlled failure for invalid configuration - log clearly without stack trace
|
||||
LOG.error("Configuration validation failed: {}", e.getMessage());
|
||||
|
||||
@@ -1,7 +1,29 @@
|
||||
/**
|
||||
* Bootstrap module for application startup and technical wiring.
|
||||
* Bootstrap module for application startup and technical object graph construction.
|
||||
* <p>
|
||||
* Responsibility: Orchestrate the startup flow, load configuration, validate it,
|
||||
* create and wire all application components, and invoke the CLI adapter entry point.
|
||||
* <p>
|
||||
* Components:
|
||||
* <ul>
|
||||
* <li>{@link de.gecheckt.pdf.umbenenner.bootstrap.BootstrapRunner}
|
||||
* — Orchestrator of startup sequence and object graph construction (M2-AP-005)</li>
|
||||
* <li>{@link de.gecheckt.pdf.umbenenner.bootstrap.PdfUmbenennerApplication}
|
||||
* — Main entry point that invokes BootstrapRunner (M1)</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* M2 Implementation:
|
||||
* <ul>
|
||||
* <li>Uses factory pattern with pluggable interfaces for all ports and use cases</li>
|
||||
* <li>Manually constructs object graph without framework dependencies</li>
|
||||
* <li>Ensures strict inward dependency direction toward application and domain</li>
|
||||
* <li>Ready for extension by later milestones via factory methods</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This package contains the main entry point and manual object graph construction.
|
||||
* AP-003: Provides a minimal, controlled startup path without dependency injection frameworks.
|
||||
* <p>
|
||||
* AP-005: CLI adapter and complete M2 object graph wiring.
|
||||
* <p>
|
||||
* AP-006: Wires FilesystemRunLockPortAdapter (adapter-out) from validated config; retired temporary no-op lock.
|
||||
*/
|
||||
package de.gecheckt.pdf.umbenenner.bootstrap;
|
||||
Reference in New Issue
Block a user