Skip to content

flowable-spring-boot-autoconfigure: register a DependsOnDatabaseInitializationDetector so the ProcessEngine waits for Flyway/Liquibase #4213

Description

@galimru

Is your feature request related to a problem? Please describe.

When flowable-spring-boot-starter-process is used alongside spring-boot-starter-flyway (or any other Spring Boot–managed DB initializer: Liquibase, spring.sql.init), there is no guaranteed bean-instantiation order between Flowable's processEngine and Flyway's flywayInitializer. Spring Boot's DatabaseInitializationDependencyConfigurer is the framework's mechanism for this — it walks beans flagged by registered DependsOnDatabaseInitializationDetector SPI implementations and adds @DependsOn(flywayInitializer) to each.

Spring Boot ships detectors for EntityManagerFactory, JdbcOperations, JobRepository, etc. flowable-spring-boot-autoconfigure does not register one for processEngine, and ProcessEngineAutoConfiguration does not annotate the bean with @DependsOnDatabaseInitialization. As a result, Flowable can be instantiated before Flyway, creates its ACT_* tables into an empty schema, and Flyway then refuses to start because the schema is non-empty but contains no flyway_schema_history row.

This often went unnoticed in Spring Boot 3 because HibernateJpaAutoConfiguration indirectly delayed Flowable through the JPA bean graph. With Spring Boot 4's modularised autoconfig — and projects increasingly dropping JPA in favour of plain JDBC, jOOQ, or Exposed — that incidental ordering vanishes and the race surfaces deterministically.

Steps to reproduce on Spring Boot 4.0.6 / Flowable 8.0.0:

  1. spring-boot-starter-jdbc + spring-boot-starter-flyway + flowable-spring-boot-starter-process on the classpath.
  2. No spring-boot-starter-data-jpa.
  3. Empty database, one Flyway migration in db/migration/.
  4. Boot the app. Flyway fails with Schema "public" is not empty because Flowable created ACT_* first.

Describe the solution you'd like

Register a DependsOnDatabaseInitializationDetector in flowable-spring-boot-autoconfigure that returns the names of the engine beans whose definitions are present (processEngine, and analogously cmmnEngine, dmnEngine, appEngine, etc.).

Concrete change — one class plus one META-INF/spring.factories entry inside flowable-spring-boot-autoconfigure:

public class FlowableDependsOnDatabaseInitializationDetector
        implements DependsOnDatabaseInitializationDetector {

    private static final String[] ENGINE_BEANS = {
        "processEngine", "cmmnEngine", "dmnEngine", "appEngine", "idmEngine", "eventRegistryEngine"
    };

    @Override
    public Set<String> detect(ConfigurableListableBeanFactory beanFactory) {
        Set<String> names = new HashSet<>();
        for (String name : ENGINE_BEANS) {
            if (beanFactory.containsBeanDefinition(name)) {
                names.add(name);
            }
        }
        return names;
    }
}
# META-INF/spring.factories
org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector=\
  org.flowable.spring.boot.FlowableDependsOnDatabaseInitializationDetector

This is the same approach Spring Boot itself uses to wire EntityManagerFactory and JdbcOperations behind Flyway. No behaviour change for existing users who don't have Flyway/Liquibase on the classpath — the configurer is a no-op when no DB initializer is present.

Describe alternatives you've considered

  • @DependsOnDatabaseInitialization on the bean definitions in ProcessEngineAutoConfiguration. Equivalent effect, slightly less flexible than the SPI (e.g. a user can't opt out, and you can't easily detect bean presence conditionally).
  • @AutoConfigureAfter(FlywayAutoConfiguration.class) on ProcessEngineAutoConfiguration. Doesn't work — that ordering controls auto-config class processing, not bean instantiation.
  • Each consumer registers their own detector. What we're currently doing in our service — a one-class detector that names processEngine. Works, but every Flowable+Flyway user ends up duplicating it.
  • Disable flowable.database-schema-update and ship ACT_* DDL as Flyway migrations. Most correct from a schema-ownership perspective but high maintenance — every Flowable bump requires copying upgrade scripts from org/flowable/common/db/upgrade/*.sql and revalidating.

Additional context

I'm happy to open a PR with the change above if the maintainers agree this is the right shape — just let me know whether you'd prefer the detector in flowable-spring-boot-autoconfigure next to the engine autoconfigs, or split per-engine module.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions