'Spring Boot: start liquibase changes only once Tomcat started

Right now, my Liquibase scripts are integrated in my product (a Spring boot application). I would like to know if there is an easy way to postpone the Liquibase changes once Tomcat has finished to start from a Spring Boot application?

Or if need to separate Liquibase changes from the Spring Boot app to run this behavior?



Solution 1:[1]

A similar question was asked previously. It has several answers, but I'll summarize the most popular below.: Spring Boot. Running liquibase changelog after JPA auto-dll tables generation on hsqldb

Answer posted by Radek Posto?owicz

Possible solution is to disable automatic boot liquibase run via application.properties:

spring.jpa.hibernate.ddl-auto=create
liquibase.enabled=false

and then manually configure SpringLiquibase bean to depend on entityManagerFactory:

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;

import liquibase.integration.spring.SpringLiquibase;

@SpringBootApplication
public class DemoApplication {

    @Autowired
    private DataSource dataSource;

    @Bean
    public LiquibaseProperties liquibaseProperties() {
        return new LiquibaseProperties();
    }

    @Bean
    @DependsOn(value = "entityManagerFactory")
    public SpringLiquibase liquibase() {
        LiquibaseProperties liquibaseProperties = liquibaseProperties();
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setChangeLog(liquibaseProperties.getChangeLog());
        liquibase.setContexts(liquibaseProperties.getContexts());
        liquibase.setDataSource(getDataSource(liquibaseProperties));
        liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
        liquibase.setDropFirst(liquibaseProperties.isDropFirst());
        liquibase.setShouldRun(true);
        liquibase.setLabels(liquibaseProperties.getLabels());
        liquibase.setChangeLogParameters(liquibaseProperties.getParameters());
        return liquibase;
    }

    private DataSource getDataSource(LiquibaseProperties liquibaseProperties) {
        if (liquibaseProperties.getUrl() == null) {
            return this.dataSource;
        }
        return DataSourceBuilder.create().url(liquibaseProperties.getUrl())
            .username(liquibaseProperties.getUser())
             .password(liquibaseProperties.getPassword()).build();
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

However I'd strongly encourage to use liquibase to build schema as well. I believe it was designed (see org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseJpaDependencyConfiguration) to run before hibernate's ddl-auto so that it's possible to set ddl-auto=validate and have liquibase schema validated by hibernate.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tabbyfoo