diff --git a/pom.xml b/pom.xml index c3d8d9c..652841e 100644 --- a/pom.xml +++ b/pom.xml @@ -76,6 +76,13 @@ jackson-datatype-jsr310 + + + org.fireflyframework + fireflyframework-kernel + ${project.version} + + org.fireflyframework diff --git a/src/main/java/org/fireflyframework/transactional/saga/composition/CompositionValidationException.java b/src/main/java/org/fireflyframework/transactional/saga/composition/CompositionValidationException.java index a074e13..3621616 100644 --- a/src/main/java/org/fireflyframework/transactional/saga/composition/CompositionValidationException.java +++ b/src/main/java/org/fireflyframework/transactional/saga/composition/CompositionValidationException.java @@ -16,6 +16,8 @@ package org.fireflyframework.transactional.saga.composition; +import org.fireflyframework.kernel.exception.FireflyException; + import java.util.List; import java.util.stream.Collectors; @@ -26,7 +28,7 @@ * during composition building, including helpful suggestions for * resolving the problems. */ -public class CompositionValidationException extends RuntimeException { +public class CompositionValidationException extends FireflyException { private final String compositionName; private final List validationIssues; diff --git a/src/main/java/org/fireflyframework/transactional/saga/engine/ReactiveStreamOptimizations.java b/src/main/java/org/fireflyframework/transactional/saga/engine/ReactiveStreamOptimizations.java index 3a04720..7fc17ab 100644 --- a/src/main/java/org/fireflyframework/transactional/saga/engine/ReactiveStreamOptimizations.java +++ b/src/main/java/org/fireflyframework/transactional/saga/engine/ReactiveStreamOptimizations.java @@ -17,6 +17,7 @@ package org.fireflyframework.transactional.saga.engine; +import org.fireflyframework.kernel.exception.FireflyException; import org.fireflyframework.transactional.saga.core.SagaContext; import org.fireflyframework.transactional.saga.registry.SagaDefinition; import org.fireflyframework.transactional.saga.registry.StepDefinition; @@ -319,7 +320,7 @@ public interface LayerExecutor { Mono executeStep(String stepId); } - public static class CircuitBreakerException extends RuntimeException { + public static class CircuitBreakerException extends FireflyException { public CircuitBreakerException(String message) { super(message); } diff --git a/src/main/java/org/fireflyframework/transactional/saga/engine/SagaCompensator.java b/src/main/java/org/fireflyframework/transactional/saga/engine/SagaCompensator.java index 82b8a66..e5364ce 100644 --- a/src/main/java/org/fireflyframework/transactional/saga/engine/SagaCompensator.java +++ b/src/main/java/org/fireflyframework/transactional/saga/engine/SagaCompensator.java @@ -17,6 +17,7 @@ package org.fireflyframework.transactional.saga.engine; +import org.fireflyframework.kernel.exception.FireflyException; import org.fireflyframework.transactional.saga.core.SagaContext; import org.fireflyframework.transactional.saga.registry.SagaDefinition; import org.fireflyframework.transactional.saga.registry.StepDefinition; @@ -304,7 +305,7 @@ private Object resolveCompensationArg(Method comp, Object input, Object result) /** * Exception thrown when compensation fails and the error handler decides to fail the saga. */ - public static class CompensationFailedException extends RuntimeException { + public static class CompensationFailedException extends FireflyException { public CompensationFailedException(String message, Throwable cause) { super(message, cause); } diff --git a/src/main/java/org/fireflyframework/transactional/saga/persistence/serialization/SagaStateSerializer.java b/src/main/java/org/fireflyframework/transactional/saga/persistence/serialization/SagaStateSerializer.java index 41047c0..39ec272 100644 --- a/src/main/java/org/fireflyframework/transactional/saga/persistence/serialization/SagaStateSerializer.java +++ b/src/main/java/org/fireflyframework/transactional/saga/persistence/serialization/SagaStateSerializer.java @@ -16,6 +16,7 @@ package org.fireflyframework.transactional.saga.persistence.serialization; +import org.fireflyframework.kernel.exception.FireflyException; import org.fireflyframework.transactional.saga.persistence.SagaExecutionState; /** @@ -80,7 +81,7 @@ public interface SagaStateSerializer { /** * Exception thrown when serialization or deserialization fails. */ - class SerializationException extends Exception { + class SerializationException extends FireflyException { public SerializationException(String message) { super(message); } diff --git a/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidationService.java b/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidationService.java index 1fc9690..0e54789 100644 --- a/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidationService.java +++ b/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidationService.java @@ -16,6 +16,7 @@ package org.fireflyframework.transactional.saga.validation; +import org.fireflyframework.kernel.exception.FireflyException; import org.fireflyframework.transactional.saga.registry.SagaDefinition; import org.fireflyframework.transactional.saga.registry.SagaRegistry; import org.fireflyframework.transactional.saga.registry.StepDefinition; @@ -284,11 +285,11 @@ public void validateSagaInputsOrThrow(SagaDefinition saga, Object inputs) throws /** * Exception thrown when saga validation fails. */ - public static class SagaValidationException extends Exception { + public static class SagaValidationException extends FireflyException { public SagaValidationException(String message) { super(message); } - + public SagaValidationException(String message, Throwable cause) { super(message, cause); } diff --git a/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidator.java b/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidator.java index 5775f7a..645ccaa 100644 --- a/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidator.java +++ b/src/main/java/org/fireflyframework/transactional/saga/validation/SagaValidator.java @@ -16,6 +16,7 @@ package org.fireflyframework.transactional.saga.validation; +import org.fireflyframework.kernel.exception.FireflyException; import org.fireflyframework.transactional.saga.registry.SagaDefinition; import org.fireflyframework.transactional.saga.registry.StepDefinition; @@ -266,7 +267,7 @@ private static void validateInputRequirements(SagaDefinition saga, Object inputs /** * Exception thrown when circular dependencies are detected. */ - public static class CircularDependencyException extends Exception { + public static class CircularDependencyException extends FireflyException { public CircularDependencyException(String message) { super(message); } diff --git a/src/main/java/org/fireflyframework/transactional/shared/annotations/EnableTransactionalEngine.java b/src/main/java/org/fireflyframework/transactional/shared/annotations/EnableTransactionalEngine.java index 19e2323..b0de973 100644 --- a/src/main/java/org/fireflyframework/transactional/shared/annotations/EnableTransactionalEngine.java +++ b/src/main/java/org/fireflyframework/transactional/shared/annotations/EnableTransactionalEngine.java @@ -17,8 +17,6 @@ package org.fireflyframework.transactional.shared.annotations; -import org.fireflyframework.transactional.saga.config.SagaPersistenceAutoConfiguration; -import org.fireflyframework.transactional.saga.config.SagaRedisAutoConfiguration; import org.fireflyframework.transactional.shared.config.TransactionalEngineConfiguration; import org.springframework.context.annotation.Import; @@ -27,10 +25,19 @@ /** * Enables the Transactional Engine (Saga orchestrator) components in a Spring application. *

- * Imports {@link org.fireflyframework.transactional.config.TransactionalEngineConfiguration} that wires: + * This annotation imports {@link TransactionalEngineConfiguration} directly so it works + * in both Spring Boot (auto-configuration) and plain Spring contexts + * (e.g. {@code AnnotationConfigApplicationContext}). + *

+ * Additional conditional configurations (persistence, Redis, composition) are registered via + * {@code META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports} + * and activated automatically in Spring Boot applications. + *

+ * Components wired by this annotation: * - {@code SagaRegistry}: scans for @Saga beans and indexes steps * - {@code SagaEngine}: the in-memory orchestrator - * - {@code SagaEvents}: default implementation {@code SagaLoggerEvents} (override by declaring your own bean) + * - {@code TccEngine}: the TCC coordinator + * - {@code SagaEvents}: default implementation (override by declaring your own bean) * - {@code StepLoggingAspect}: AOP aspect for additional logging * - {@code WebClient.Builder}: convenience bean for HTTP clients */ @@ -38,6 +45,6 @@ @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Import({TransactionalEngineConfiguration.class, SagaPersistenceAutoConfiguration.class, SagaRedisAutoConfiguration.class}) +@Import(TransactionalEngineConfiguration.class) public @interface EnableTransactionalEngine { } diff --git a/src/main/java/org/fireflyframework/transactional/shared/config/TransactionalEngineConfiguration.java b/src/main/java/org/fireflyframework/transactional/shared/config/TransactionalEngineConfiguration.java index 7bad0fb..a6f923c 100644 --- a/src/main/java/org/fireflyframework/transactional/shared/config/TransactionalEngineConfiguration.java +++ b/src/main/java/org/fireflyframework/transactional/shared/config/TransactionalEngineConfiguration.java @@ -156,6 +156,12 @@ public TccEventPublisher tccEventPublisher() { return new NoOpTccEventPublisher(); } + @Bean + @ConditionalOnMissingBean + public SagaPersistenceProvider sagaPersistenceProvider() { + return new org.fireflyframework.transactional.saga.persistence.impl.InMemorySagaPersistenceProvider(); + } + @Bean @ConditionalOnMissingBean public TccPersistenceProvider tccPersistenceProvider() { diff --git a/src/main/java/org/fireflyframework/transactional/shared/engine/backpressure/CircuitBreakerBackpressureStrategy.java b/src/main/java/org/fireflyframework/transactional/shared/engine/backpressure/CircuitBreakerBackpressureStrategy.java index 2d336dc..7be95f4 100644 --- a/src/main/java/org/fireflyframework/transactional/shared/engine/backpressure/CircuitBreakerBackpressureStrategy.java +++ b/src/main/java/org/fireflyframework/transactional/shared/engine/backpressure/CircuitBreakerBackpressureStrategy.java @@ -16,6 +16,7 @@ package org.fireflyframework.transactional.shared.engine.backpressure; +import org.fireflyframework.kernel.exception.FireflyException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import reactor.core.publisher.Flux; @@ -254,7 +255,7 @@ public record CircuitBreakerMetrics( /** * Exception thrown when circuit breaker is open. */ - public static class CircuitBreakerException extends RuntimeException { + public static class CircuitBreakerException extends FireflyException { public CircuitBreakerException(String message) { super(message); } diff --git a/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 544b9ff..08f0ec2 100644 --- a/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,3 +1,4 @@ +org.fireflyframework.transactional.shared.config.TransactionalEngineConfiguration org.fireflyframework.transactional.saga.config.SagaPersistenceAutoConfiguration org.fireflyframework.transactional.saga.config.SagaRedisAutoConfiguration org.fireflyframework.transactional.saga.config.SagaCompositionAutoConfiguration diff --git a/src/test/java/org/fireflyframework/transactional/persistence/integration/RedisPersistenceIntegrationTest.java b/src/test/java/org/fireflyframework/transactional/persistence/integration/RedisPersistenceIntegrationTest.java index 6c89b27..a98682f 100644 --- a/src/test/java/org/fireflyframework/transactional/persistence/integration/RedisPersistenceIntegrationTest.java +++ b/src/test/java/org/fireflyframework/transactional/persistence/integration/RedisPersistenceIntegrationTest.java @@ -22,6 +22,8 @@ import org.fireflyframework.transactional.saga.core.SagaContext; import org.fireflyframework.transactional.saga.engine.SagaEngine; import org.fireflyframework.transactional.saga.engine.StepInputs; +import org.fireflyframework.transactional.saga.config.SagaPersistenceAutoConfiguration; +import org.fireflyframework.transactional.saga.config.SagaRedisAutoConfiguration; import org.fireflyframework.transactional.shared.annotations.EnableTransactionalEngine; import org.fireflyframework.transactional.shared.core.StepStatus; import org.fireflyframework.transactional.saga.persistence.SagaExecutionState; @@ -34,6 +36,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; @@ -101,6 +104,7 @@ static void configureProperties(DynamicPropertyRegistry registry) { @Configuration @EnableTransactionalEngine + @Import({SagaPersistenceAutoConfiguration.class, SagaRedisAutoConfiguration.class}) static class TestConfig { @Bean