Skip to content

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

@galimru

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions