M1 Vollständiger Grundstand mit Build, Konfiguration, Tests und Smoke-Tests
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
package de.gecheckt.pdf.umbenenner.bootstrap;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
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.application.config.InvalidStartConfigurationException;
|
||||
import de.gecheckt.pdf.umbenenner.application.config.StartConfigurationValidator;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Manual bootstrap runner that constructs the object graph and drives the startup flow.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* AP-006: Validates configuration before processing begins, returns exit code 2 on invalid config.
|
||||
*/
|
||||
public class BootstrapRunner {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(BootstrapRunner.class);
|
||||
|
||||
private final ConfigurationPortFactory configPortFactory;
|
||||
private final ValidatorFactory validatorFactory;
|
||||
private final UseCaseFactory useCaseFactory;
|
||||
private final CommandFactory commandFactory;
|
||||
|
||||
/**
|
||||
* Functional interface for creating a ConfigurationPort.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ConfigurationPortFactory {
|
||||
ConfigurationPort create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for creating a StartConfigurationValidator.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ValidatorFactory {
|
||||
StartConfigurationValidator create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for creating a RunBatchProcessingUseCase.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface UseCaseFactory {
|
||||
RunBatchProcessingUseCase create(ConfigurationPort configPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for creating a SchedulerBatchCommand.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface CommandFactory {
|
||||
SchedulerBatchCommand create(RunBatchProcessingUseCase useCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the BootstrapRunner with default factories for production use.
|
||||
*/
|
||||
public BootstrapRunner() {
|
||||
this.configPortFactory = PropertiesConfigurationPortAdapter::new;
|
||||
this.validatorFactory = StartConfigurationValidator::new;
|
||||
this.useCaseFactory = NoOpRunBatchProcessingUseCase::new;
|
||||
this.commandFactory = SchedulerBatchCommand::new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the BootstrapRunner with custom factories for testing.
|
||||
*
|
||||
* @param configPortFactory factory for creating ConfigurationPort 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,
|
||||
ValidatorFactory validatorFactory,
|
||||
UseCaseFactory useCaseFactory,
|
||||
CommandFactory commandFactory) {
|
||||
this.configPortFactory = configPortFactory;
|
||||
this.validatorFactory = validatorFactory;
|
||||
this.useCaseFactory = useCaseFactory;
|
||||
this.commandFactory = commandFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the application startup sequence.
|
||||
* <p>
|
||||
* AP-003: Manually wires the object graph and invokes the CLI command.
|
||||
* AP-005: Wires ConfigurationPort adapter and passes it to the use case.
|
||||
* AP-006: Validates configuration before allowing processing to start.
|
||||
*
|
||||
* @return exit code: 0 for success, 1 for unexpected failure, 2 for invalid configuration
|
||||
*/
|
||||
public int run() {
|
||||
LOG.info("Bootstrap flow started.");
|
||||
try {
|
||||
// Step 1: Create the configuration port adapter (adapter-out layer)
|
||||
ConfigurationPort configPort = configPortFactory.create();
|
||||
|
||||
// Step 2: Load configuration
|
||||
var config = configPort.loadConfiguration();
|
||||
|
||||
// Step 3: Validate configuration (AP-006)
|
||||
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 5: Create the CLI command adapter with the use case
|
||||
SchedulerBatchCommand command = commandFactory.create(useCase);
|
||||
|
||||
// Step 6: Execute the command
|
||||
boolean success = command.run();
|
||||
|
||||
if (success) {
|
||||
LOG.info("No-op startup path completed successfully.");
|
||||
}
|
||||
|
||||
return success ? 0 : 1;
|
||||
} catch (InvalidStartConfigurationException e) {
|
||||
// Controlled failure for invalid configuration - log clearly without stack trace
|
||||
LOG.error("Configuration validation failed: {}", e.getMessage());
|
||||
return 2;
|
||||
} catch (IllegalStateException e) {
|
||||
// Configuration loading failed due to missing/invalid required properties
|
||||
// Treat as invalid configuration for controlled failure
|
||||
LOG.error("Configuration loading failed: {}", e.getMessage());
|
||||
return 2;
|
||||
} catch (Exception e) {
|
||||
LOG.error("Bootstrap failure during startup.", e);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package de.gecheckt.pdf.umbenenner.bootstrap;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Main entry point for the PDF Umbenenner application.
|
||||
* <p>
|
||||
* AP-003: Delegates to {@link BootstrapRunner} for manual object graph construction
|
||||
* and execution of the minimal no-op startup path.
|
||||
*/
|
||||
public class PdfUmbenennerApplication {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(PdfUmbenennerApplication.class);
|
||||
|
||||
/**
|
||||
* Application entry point.
|
||||
*
|
||||
* @param args command line arguments (currently unused)
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
LOG.info("Starting PDF Umbenenner application...");
|
||||
try {
|
||||
BootstrapRunner runner = new BootstrapRunner();
|
||||
int exitCode = runner.run();
|
||||
if (exitCode == 0) {
|
||||
LOG.info("PDF Umbenenner application completed successfully.");
|
||||
} else {
|
||||
LOG.error("PDF Umbenenner application terminated with error code {}.", exitCode);
|
||||
}
|
||||
System.exit(exitCode);
|
||||
} catch (Exception e) {
|
||||
LOG.fatal("Unexpected technical bootstrap failure in PDF Umbenenner application.", e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Bootstrap module for application startup and technical wiring.
|
||||
* <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.
|
||||
*/
|
||||
package de.gecheckt.pdf.umbenenner.bootstrap;
|
||||
28
pdf-umbenenner-bootstrap/src/main/resources/log4j2.xml
Normal file
28
pdf-umbenenner-bootstrap/src/main/resources/log4j2.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<!-- Console appender for stdout -->
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
|
||||
</Console>
|
||||
|
||||
<!-- Rolling file appender for logs in ./logs/ directory -->
|
||||
<RollingFile name="File" fileName="logs/pdf-umbenenner.log"
|
||||
filePattern="logs/pdf-umbenenner-%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
|
||||
<SizeBasedTriggeringPolicy size="10 MB"/>
|
||||
</Policies>
|
||||
<DefaultRolloverStrategy max="7"/>
|
||||
</RollingFile>
|
||||
</Appenders>
|
||||
|
||||
<Loggers>
|
||||
<!-- Root logger at INFO level -->
|
||||
<Root level="info">
|
||||
<AppenderRef ref="Console"/>
|
||||
<AppenderRef ref="File"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
Reference in New Issue
Block a user