mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 15:49:35 +01:00
fix(infra): no-db Profil robuster machen und Stub-Beans ergänzen
DatabaseProfileInitializer setzt Autoconfigure-Exclusions programmatisch,
da application-no-db.yml bei spätem Profil-Aktivierung nicht geladen wird.
SpringUnitOfWork mit @Profile("!no-db") ausgeschlossen. Stub-Beans für
BatchNumberGenerator, BatchRepository, ProductionOrderRepository,
StockMovementRepository und UnitOfWork ergänzt. generate-openapi.sh
nutzt korrektes -Dspring-boot.run.profiles=no-db.
This commit is contained in:
parent
72d59b4948
commit
0e58cbfacf
8 changed files with 258 additions and 3 deletions
|
|
@ -5,21 +5,41 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
import java.sql.DriverManager;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Prüft vor dem Context-Start, ob die Datenbank erreichbar ist.
|
||||
* Schlägt die Verbindung fehl, wird das Spring-Profil "no-db" aktiviert.
|
||||
* Damit werden JPA, DataSource und Liquibase ausgeschlossen und Stub-Beans registriert.
|
||||
*
|
||||
* WICHTIG: Die Autoconfiguration-Exclusions werden hier programmatisch gesetzt,
|
||||
* weil application-no-db.yml nicht geladen wird, wenn das Profil erst im
|
||||
* ApplicationContextInitializer (nach prepareEnvironment) hinzugefügt wird.
|
||||
*/
|
||||
public class DatabaseProfileInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DatabaseProfileInitializer.class);
|
||||
|
||||
private static final String AUTOCONFIGURE_EXCLUDE = String.join(",",
|
||||
"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration",
|
||||
"org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration",
|
||||
"org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration",
|
||||
"org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration",
|
||||
"org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration");
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext ctx) {
|
||||
var env = ctx.getEnvironment();
|
||||
var env = (ConfigurableEnvironment) ctx.getEnvironment();
|
||||
|
||||
if (env.acceptsProfiles(org.springframework.core.env.Profiles.of("no-db"))) {
|
||||
log.info("Profil 'no-db' bereits aktiv – überspringe DB-Check.");
|
||||
applyNoDbProperties(env);
|
||||
return;
|
||||
}
|
||||
|
||||
var url = env.getProperty("spring.datasource.url", "jdbc:postgresql://localhost:5432/effigenix");
|
||||
var user = env.getProperty("spring.datasource.username", "effigenix");
|
||||
var pass = env.getProperty("spring.datasource.password", "effigenix");
|
||||
|
|
@ -28,7 +48,14 @@ public class DatabaseProfileInitializer implements ApplicationContextInitializer
|
|||
log.debug("Datenbankverbindung erfolgreich – normaler Start.");
|
||||
} catch (Exception e) {
|
||||
log.warn("⚠️ Keine Datenbankverbindung – Stub-Modus aktiv. Einige Features sind nicht verfügbar. ({})", e.getMessage());
|
||||
((ConfigurableEnvironment) env).addActiveProfile("no-db");
|
||||
env.addActiveProfile("no-db");
|
||||
applyNoDbProperties(env);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyNoDbProperties(ConfigurableEnvironment env) {
|
||||
env.getPropertySources().addFirst(new MapPropertySource("no-db-overrides", Map.of(
|
||||
"spring.autoconfigure.exclude", AUTOCONFIGURE_EXCLUDE
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package de.effigenix.infrastructure.config;
|
|||
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.persistence.UnitOfWork;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
|
@ -9,6 +10,7 @@ import org.springframework.transaction.support.DefaultTransactionDefinition;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
@Component
|
||||
@Profile("!no-db")
|
||||
public class SpringUnitOfWork implements UnitOfWork {
|
||||
|
||||
private final PlatformTransactionManager txManager;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package de.effigenix.infrastructure.stub;
|
||||
|
||||
import de.effigenix.domain.production.BatchError;
|
||||
import de.effigenix.domain.production.BatchNumber;
|
||||
import de.effigenix.domain.production.BatchNumberGenerator;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Component
|
||||
@Profile("no-db")
|
||||
public class StubBatchNumberGenerator implements BatchNumberGenerator {
|
||||
|
||||
@Override
|
||||
public Result<BatchError, BatchNumber> generateNext(LocalDate date) {
|
||||
return Result.failure(new BatchError.RepositoryFailure("Stub-Modus: keine Datenbankverbindung"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package de.effigenix.infrastructure.stub;
|
||||
|
||||
import de.effigenix.domain.production.Batch;
|
||||
import de.effigenix.domain.production.BatchId;
|
||||
import de.effigenix.domain.production.BatchNumber;
|
||||
import de.effigenix.domain.production.BatchRepository;
|
||||
import de.effigenix.domain.production.BatchStatus;
|
||||
import de.effigenix.domain.production.RecipeId;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
@Profile("no-db")
|
||||
public class StubBatchRepository implements BatchRepository {
|
||||
|
||||
private static final RepositoryError.DatabaseError STUB_ERROR =
|
||||
new RepositoryError.DatabaseError("Stub-Modus: keine Datenbankverbindung");
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Optional<Batch>> findById(BatchId id) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findAll() {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Optional<Batch>> findByBatchNumber(BatchNumber batchNumber) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findByStatus(BatchStatus status) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findByProductionDate(LocalDate date) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findByRecipeIds(List<RecipeId> recipeIds) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findAllSummary() {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findByStatusSummary(BatchStatus status) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findByProductionDateSummary(LocalDate date) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<Batch>> findByRecipeIdsSummary(List<RecipeId> recipeIds) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Void> save(Batch batch) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package de.effigenix.infrastructure.stub;
|
||||
|
||||
import de.effigenix.domain.production.ProductionOrder;
|
||||
import de.effigenix.domain.production.ProductionOrderId;
|
||||
import de.effigenix.domain.production.ProductionOrderRepository;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
@Profile("no-db")
|
||||
public class StubProductionOrderRepository implements ProductionOrderRepository {
|
||||
|
||||
private static final RepositoryError.DatabaseError STUB_ERROR =
|
||||
new RepositoryError.DatabaseError("Stub-Modus: keine Datenbankverbindung");
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Optional<ProductionOrder>> findById(ProductionOrderId id) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<ProductionOrder>> findAll() {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Void> save(ProductionOrder productionOrder) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package de.effigenix.infrastructure.stub;
|
||||
|
||||
import de.effigenix.domain.inventory.MovementType;
|
||||
import de.effigenix.domain.inventory.StockId;
|
||||
import de.effigenix.domain.inventory.StockMovement;
|
||||
import de.effigenix.domain.inventory.StockMovementId;
|
||||
import de.effigenix.domain.inventory.StockMovementRepository;
|
||||
import de.effigenix.domain.masterdata.ArticleId;
|
||||
import de.effigenix.shared.common.RepositoryError;
|
||||
import de.effigenix.shared.common.Result;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
@Profile("no-db")
|
||||
public class StubStockMovementRepository implements StockMovementRepository {
|
||||
|
||||
private static final RepositoryError.DatabaseError STUB_ERROR =
|
||||
new RepositoryError.DatabaseError("Stub-Modus: keine Datenbankverbindung");
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Optional<StockMovement>> findById(StockMovementId id) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAll() {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAllByStockId(StockId stockId) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAllByArticleId(ArticleId articleId) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAllByMovementType(MovementType movementType) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAllByBatchReference(String batchReference) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAllByPerformedAtBetween(Instant from, Instant to) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAllByPerformedAtAfter(Instant from) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, List<StockMovement>> findAllByPerformedAtBefore(Instant to) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<RepositoryError, Void> save(StockMovement stockMovement) {
|
||||
return Result.failure(STUB_ERROR);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package de.effigenix.infrastructure.stub;
|
||||
|
||||
import de.effigenix.shared.common.Result;
|
||||
import de.effigenix.shared.persistence.UnitOfWork;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Component
|
||||
@Profile("no-db")
|
||||
public class StubUnitOfWork implements UnitOfWork {
|
||||
|
||||
@Override
|
||||
public <E, T> Result<E, T> executeAtomically(Supplier<Result<E, T>> work) {
|
||||
return work.get();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue