Springboot : lancer Flyway après les DDL de JPA

Vous avez une petite application Spring Boot et jusque là, vous êtiez totalement satisfait de la génération et mise à jour automatique de la structure de la base de données par JPA. Pour cela, il suffit d’ajouter dans son fichier application.properties :

spring.jpa.hibernate.ddl-auto=update

Ensuite, on place nos scripts SQL dans src/main/resources/db/migration en respectant les nommage de fichier qui va bien.

Mais voilà, votre application évolue tout doucement et vous devez insérer des données de référentiel dans votre base de données. Oh mince, il y a un second developpeur qui arrive.

Il n’en demeure pas moins que vous restez fainéant et vous ne voulez pas transmettre des scripts SQL de main en main.

Heureusement, il y a Flyway. Une simple dépendance à ajouter pour gérer les migrations de base de données.

<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>

C’est pas mal mais Flyway se lance avant la gestion de la structure par JPA et les tables n’existent pas encore quand Flyway essaye d’y insérer des données.

Vous n’allez tout de même pas ajouter les scripts de création de table vous même, au cas où personne ne l’aurait compris : vous êtes fainéant.

Une solution pointe le bout de son nez. Il suffit de désactiver Flyway dans le fichier

application.properties :

spring.flyway.enabled=false

Et de lancer la migration Flyway à la main au moment où l’application Spring Boot est prête à l’aide d’un ApplicationListener :

@Order(0)
@Component
public class FlywayInitializer 
        implements ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    private DataSource datasource;
    
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        var flyway = Flyway.configure()
            .dataSource(datasource)
            .baselineOnMigrate(true)
            .load();
            
        flyway.migrate();
    }
}

Et voilà, vous avez réussi à utiliser tous les outils de manière intelligente et fainéante. Bravo.

Ceci étant dit, ce petit hack est bien pratique sur une petite application mais ce n’est pas pour rien qu’il faille tricher pour arriver à ce résultat. Si l’application prend vraiment de l’ampleur (en terme d’équipe ou d’infrastructure), je vous conseille fortement de respecter ce que nous impose l’intégration de Flyway par défaut et de faire l’effort de gérer soit même les mises à jour de structure.

Les développeurs Spring Boot ont choisi avec sagesse de rendre la création de l’EntityManager dépendant de Flyway pour éviter de vous frotter à des problèmes de mises à jour concurrentes (entre autres exemples de ce qui pourrait mal se passer).