Class FailoverAutoConfiguration

java.lang.Object
com.societegenerale.failover.configuration.FailoverAutoConfiguration

@AutoConfiguration @ConditionalOnExpression("${failover.enabled:true} eq true") @EnableConfigurationProperties(FailoverProperties.class) @EnableAspectJAutoProxy public class FailoverAutoConfiguration extends Object
Root Spring Boot autoconfiguration for the failover framework.

Activates when failover.enabled=true (the default). Registers all core failover infrastructure beans: AOP aspect, expiry policy, key generators, payload enricher, recovered-payload handler, method-exception policy, schedulers, and the in-memory store factory (when no other store type is configured).

Store-type-specific beans (Caffeine, JDBC) and the final assembled FailoverStore bean are produced by FailoverStoreAutoConfiguration (with per-tenant routing layered on by FailoverStoreMultiTenantAutoConfiguration when enabled).

Note on structure: the core beans are declared flat on this class (rather than grouped into nested @Configuration classes) on purpose. @ConditionalOnMissingBean relies on auto-configuration ordering to let a user-declared bean win; nested @Configuration classes lose that deferred ordering and break bean-override (the framework's primary extension point). Keep new beans flat here unless they have no @ConditionalOnMissingBean.

Author:
Anand Manissery
  • Constructor Details

    • FailoverAutoConfiguration

      public FailoverAutoConfiguration()
  • Method Details

    • failoverClock

      @ConditionalOnMissingBean @Bean public FailoverClock failoverClock()
      Creates the default failover clock bean.
      Returns:
      default DefaultFailoverClock
    • defaultKeyGenerator

      @ConditionalOnMissingBean(name="defaultKeyGenerator") @Bean(name="defaultKeyGenerator") public KeyGenerator defaultKeyGenerator()
      Creates the default key generator bean.
      Returns:
      DefaultKeyGenerator, which derives the key by joining the method arguments' string representations (see DefaultKeyGenerator for the per-argument rules)
    • keyGeneratorLookup

      @ConditionalOnMissingBean @Bean public KeyGeneratorLookup keyGeneratorLookup()
      Creates the key-generator lookup bean.
      Returns:
      BeanFactoryKeyGeneratorLookup resolving named key-generator beans
    • failoverKeyGenerator

      @ConditionalOnMissingBean(name="failoverKeyGenerator") @Bean(name="failoverKeyGenerator") public KeyGenerator failoverKeyGenerator(@Qualifier("defaultKeyGenerator") KeyGenerator defaultKeyGenerator, KeyGeneratorLookup keyGeneratorLookup)
      Creates the composite failover key generator.
      Parameters:
      defaultKeyGenerator - fallback key generator when no named override is found
      keyGeneratorLookup - lookup that resolves per-@Failover named key generators
      Returns:
      composite FailoverKeyGenerator that delegates to named generators or the default
    • failoverExpiryExtractor

      @ConditionalOnMissingBean @Bean public FailoverExpiryExtractor failoverExpiryExtractor()
      Creates the failover expiry extractor bean.
      Returns:
      BeanFactoryFailoverExpiryExtractor resolving named expiry-policy beans
    • defaultExpiryPolicy

      @ConditionalOnMissingBean(name="defaultExpiryPolicy") @Bean public ExpiryPolicy<Object> defaultExpiryPolicy(FailoverClock clock, FailoverExpiryExtractor failoverExpiryExtractor)
      Creates the default expiry policy bean.
      Parameters:
      clock - clock used to compute expiry timestamps
      failoverExpiryExtractor - extractor that reads expiry duration from @Failover
      Returns:
      default expiry policy based on the annotation's configured duration
    • expiryPolicyLookup

      @ConditionalOnMissingBean @Bean public ExpiryPolicyLookup<Object> expiryPolicyLookup()
      Creates the expiry-policy lookup bean.
      Returns:
      BeanFactoryExpiryPolicyLookup resolving named expiry-policy beans
    • failoverExpiryPolicy

      @ConditionalOnMissingBean(name="failoverExpiryPolicy") @Bean(name="failoverExpiryPolicy") public ExpiryPolicy<Object> failoverExpiryPolicy(@Qualifier("defaultExpiryPolicy") ExpiryPolicy<Object> defaultExpiryPolicy, ExpiryPolicyLookup<Object> expiryPolicyLookup)
      Creates the composite failover expiry policy.
      Parameters:
      defaultExpiryPolicy - fallback expiry policy when no named override is found
      expiryPolicyLookup - lookup that resolves per-@Failover named expiry policies
      Returns:
      composite expiry policy that delegates to named policies or the default
    • payloadEnricher

      @ConditionalOnMissingBean @Bean public PayloadEnricher<Object> payloadEnricher()
      Creates the default payload enricher bean.
      Returns:
      default pass-through DefaultPayloadEnricher
    • payloadSplitterLookup

      @ConditionalOnMissingBean @Bean public PayloadSplitterLookup<Object,Object> payloadSplitterLookup()
      Creates the payload-splitter lookup bean.
      Returns:
      BeanFactoryPayloadSplitterLookup resolving named splitter beans
    • contextPropagator

      @ConditionalOnMissingBean(name="contextPropagator") @Bean public ContextPropagator contextPropagator(List<ContextPropagator> contextPropagators)
      Composes the active ContextPropagator from every ContextPropagator bean in the application context, plus an always-on MdcContextPropagator:
      1. All ContextPropagator beans, gathered in ordered form. This includes the auto-configured TenantContextPropagator (when failover.store.multitenant.enabled=true) and MicrometerContextPropagator (when io.micrometer.tracing.Tracer is on the classpath and a Tracer bean exists), and any custom ContextPropagator bean you declare. Annotate a custom bean with @Order to control its position in the chain.
      2. MdcContextPropagator — always appended last (innermost: restored immediately before the slice runs).
      Declare a bean named contextPropagator to replace this composition entirely; declare any other ContextPropagator bean to add it to the chain.

      The parameter is a List (not an ObjectProvider) on purpose: Spring's collection injection excludes the bean currently in creation, so this contextPropagator bean does not gather itself (which would be a self-referential BeanCurrentlyInCreationException). The list is ordered by @Order/Ordered.

      Parameters:
      contextPropagators - all ContextPropagator beans in the context (self excluded), @Order-sorted
      Returns:
      a single propagator or a CompositeContextPropagator when multiple are present
    • scatterGatherExecutor

      @ConditionalOnMissingBean(name="scatterGatherExecutor") @ConditionalOnProperty(prefix="failover.scatter", name="parallel", havingValue="true") @Bean(name="scatterGatherExecutor") public org.springframework.core.task.TaskExecutor scatterGatherExecutor(FailoverProperties properties)
      Virtual-thread executor for parallel slice dispatch in scatter/gather operations. Activated only when failover.scatter.parallel=true.

      Override by declaring a bean named scatterGatherExecutor.

      Unbounded by default. When failover.scatter.concurrency-limit > 0 the virtual-thread executor is wrapped in a BoundedTaskExecutor that caps concurrent slice fan-out and applies the configured rejection-policy on overload (audit R-2); accepted slices still run on virtual threads.

      Returns:
      virtual-thread SimpleAsyncTaskExecutor (optionally bounded) named failover-scatter-*
    • failoverScanner

      @ConditionalOnMissingBean @Bean public FailoverScanner failoverScanner()
      Registers a Spring-native scanner that locates all @Failover-annotated methods by walking the already-built ApplicationContext.
      Returns:
      SpringContextFailoverScanner
    • failoverStartupSummaryLogger

      @ConditionalOnMissingBean @Bean public FailoverStartupSummaryLogger failoverStartupSummaryLogger(FailoverProperties properties, org.springframework.context.ApplicationContext applicationContext, org.springframework.beans.factory.ObjectProvider<FailoverScanner> scannerProvider)
      Logs a single consolidated startup summary covering infrastructure configuration and all discovered @Failover endpoints. Fires on ApplicationReadyEvent so the scanner has already completed its scan before the summary is printed.
      Parameters:
      properties - failover configuration properties
      applicationContext - Spring application context for bean-type detection
      scannerProvider - optional failover scanner for per-endpoint details
      Returns:
      FailoverStartupSummaryLogger
    • recoveredPayloadHandler

      @ConditionalOnMissingBean @Bean public RecoveredPayloadHandler recoveredPayloadHandler()
      Registers the default no-op RecoveredPayloadHandler that returns the payload unchanged.
      Returns:
      pass-through PassThroughRecoveredPayloadHandler
    • loggerObservablePublisher

      @Bean public ObservablePublisher loggerObservablePublisher()
      Registers a ObservablePublisher that writes failover reports to SLF4J.
      Returns:
      MdcLoggerObservablePublisher
    • compositeObservablePublisher

      @ConditionalOnMissingBean @Bean public CompositeObservablePublisher compositeObservablePublisher(List<ObservablePublisher> observablePublishers, FailoverClock clock)
      Registers a composite publisher that stamps the publish timestamp once and broadcasts to every ObservablePublisher in the context. Stamping once here ensures all delegates receive the same timestamp regardless of how many publishers are registered.
      Parameters:
      observablePublishers - all ObservablePublisher beans in the context
      clock - clock used to stamp the single publish timestamp
      Returns:
      composite publisher
    • failoverObservablePublisher

      @ConditionalOnMissingBean(name="failoverObservablePublisher") @Bean(autowireCandidate=false) public ObservablePublisher failoverObservablePublisher(CompositeObservablePublisher composite, FailoverProperties properties)
      The dispatching publisher used by the failover handler and the startup observer — wrapping the CompositeObservablePublisher in an AsyncObservablePublisher so metric publishing can never block or slow the caller's @Failover call (the core observability contract). Disable via failover.observable.async.enabled=false to publish synchronously (deterministic for tests).

      autowireCandidate = false is essential: this bean is an ObservablePublisher but must never be collected into compositeObservablePublisher(java.util.List<com.societegenerale.failover.core.observable.publisher.ObservablePublisher>, com.societegenerale.failover.core.clock.FailoverClock)'s List<ObservablePublisher> fan-out (that would recurse). Consumers therefore fetch it by name. The async instance's close() is invoked on shutdown by Spring's inferred destroy method, flushing the queue.

      Parameters:
      composite - the leaf fan-out publisher this decorates
      properties - async settings (enabled flag + queue capacity)
      Returns:
      an AsyncObservablePublisher when async is enabled (default), else the composite itself
    • failoverMetricsDroppedMeterBinder

      @ConditionalOnClass(io.micrometer.core.instrument.MeterRegistry.class) @Bean public io.micrometer.core.instrument.binder.MeterBinder failoverMetricsDroppedMeterBinder(org.springframework.context.ApplicationContext applicationContext)
      Exposes failover.metrics.dropped.total when async publishing is active, so any metric dropped by a full queue is observable rather than silent. Bound only when the dispatching publisher is in fact an AsyncObservablePublisher (i.e. async enabled).
      Parameters:
      applicationContext - context used to resolve the (non-autowire-candidate) dispatching publisher by name
      Returns:
      a MeterBinder registering the drop counter, or a no-op when publishing is synchronous
    • failoverCardinalityMeterFilter

      @ConditionalOnClass(io.micrometer.core.instrument.config.MeterFilter.class) @ConditionalOnProperty(prefix="failover.observable.cardinality", name="enabled", havingValue="true", matchIfMissing=true) @Bean public io.micrometer.core.instrument.config.MeterFilter failoverCardinalityMeterFilter(FailoverProperties properties)
      Cardinality guard for the failover.* meters: caps the number of distinct name tag values, denying further new series once the cap is hit so a misconfigured high-cardinality failover name can never explode the registry. On by default (failover.observable.cardinality).
      Parameters:
      properties - failover properties (cardinality cap)
      Returns:
      a meter filter bounding the name tag cardinality on failover.* meters
    • failoverHandler

      @ConditionalOnMissingBean @Bean public FailoverHandler<Object> failoverHandler(@Qualifier("failoverKeyGenerator") KeyGenerator keyGenerator, @Qualifier("failoverExpiryPolicy") ExpiryPolicy<Object> expiryPolicy, FailoverClock clock, FailoverStore<Object> failoverStore, PayloadEnricher<Object> payloadEnricher, RecoveredPayloadHandler recoveredPayloadHandler, org.springframework.context.ApplicationContext applicationContext, FailoverExpiryExtractor failoverExpiryExtractor, PayloadSplitterLookup<Object,Object> payloadSplitterLookup, @Qualifier("contextPropagator") ContextPropagator contextPropagator, @Qualifier("scatterGatherExecutor") org.springframework.beans.factory.ObjectProvider<org.springframework.core.task.TaskExecutor> scatterGatherExecutorProvider, FailoverProperties failoverProperties)
      Assembles the full FailoverHandler decorator chain: AdvancedFailoverHandler(ScatterGatherFailoverHandler(DefaultFailoverHandler)).
      Parameters:
      keyGenerator - composite key generator
      expiryPolicy - composite expiry policy
      clock - failover clock
      failoverStore - the assembled store (async/sync, single/multi-tenant)
      payloadEnricher - enriches payloads on store
      recoveredPayloadHandler - handles recovered (or null) payloads
      applicationContext - resolves the (non-autowire-candidate) dispatching publisher by name
      failoverExpiryExtractor - reads expiry from @Failover
      payloadSplitterLookup - looks up named splitter beans
      contextPropagator - propagates thread context to scatter executor threads
      scatterGatherExecutorProvider - optional executor for parallel scatter (null = sequential)
      failoverProperties - framework properties (provides the scatter slice timeout)
      Returns:
      assembled AdvancedFailoverHandler
    • methodExceptionHandler

      @ConditionalOnMissingBean @Bean public MethodExceptionHandler methodExceptionHandler(MethodExceptionPolicy methodExceptionPolicy)
      Registers the MethodExceptionHandler that applies the active exception policy.
      Parameters:
      methodExceptionPolicy - active exception policy (rethrow, never-throw, or custom)
      Returns:
      MethodExceptionHandler
    • failoverExecution

      @ConditionalOnProperty(prefix="failover", name="type", havingValue="basic", matchIfMissing=true) @ConditionalOnMissingBean @Bean public FailoverExecution<Object> failoverExecution(FailoverHandler<Object> failoverHandler, MethodExceptionHandler methodExceptionHandler, org.springframework.context.ApplicationContext applicationContext)
      Registers BasicFailoverExecution, active when failover.type=basic (the default).
      Parameters:
      failoverHandler - assembled failover handler
      methodExceptionHandler - exception handler applying the configured policy
      applicationContext - resolves the non-blocking dispatching publisher (by name) for upstream-duration metrics
      Returns:
      BasicFailoverExecution
    • failoverAspect

      @ConditionalOnProperty(prefix="failover", name="aspect.enabled", havingValue="true", matchIfMissing=true) @Bean public FailoverAspect<Object> failoverAspect(FailoverExecution<Object> failoverExecution)
      Registers the AOP aspect that intercepts @Failover-annotated methods.
      Parameters:
      failoverExecution - the configured failover execution strategy
      Returns:
      FailoverAspect
    • resourceLoader

      @ConditionalOnMissingBean @Bean public ResourceLoader resourceLoader()
      Registers a resource loader for reading classpath resources (e.g. MANIFEST.MF).
      Returns:
      ClassPathResourceLoader
    • manifestInfoExtractor

      @ConditionalOnMissingBean @Bean public ManifestInfoExtractor manifestInfoExtractor(ResourceLoader resourceLoader)
      Registers a caching manifest extractor for reading build metadata from MANIFEST.MF.
      Parameters:
      resourceLoader - resource loader for reading MANIFEST.MF
      Returns:
      caching wrapper around DefaultManifestInfoExtractor
    • failoverObserver

      @ConditionalOnMissingBean @Bean(initMethod="observe") public FailoverObserver failoverObserver(CompositeObservablePublisher observablePublisher, FailoverScanner failoverScanner, FailoverClock clock, ManifestInfoExtractor manifestInfoExtractor, FailoverExpiryExtractor failoverExpiryExtractor, FailoverProperties failoverProperties)
      Creates the failover reporter bean that publishes a startup summary.
      Parameters:
      observablePublisher - composite publisher that receives the startup report
      failoverScanner - scans for all @Failover-annotated methods
      clock - clock for the report timestamp
      manifestInfoExtractor - extracts build info from MANIFEST.MF
      failoverExpiryExtractor - reads expiry config from @Failover
      failoverProperties - active failover properties for inclusion in the report
      Returns:
      reporter that publishes a full failover summary on application startup