configure dataSource for liquibase in spring boot

25.6k views Asked by At

I have a spring boot application and I want to add liquibase configuration change log for it.

I have created a LiquibaseConfig class for configuring liquibase:

@Configuration
public class LiquibaseConfiguration {

    @Value("${com.foo.bar.liquibase.changelog}")
    private String changelog;

    @Autowired
    MysqlDataSource dataSource;

    @Bean
    public SpringLiquibase liquibase()  {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog(changelog);
        return liquibase;
    }

}

and I have configured the datasource information in properties file:

spring.datasource.url=jdbc:mysql://localhost:3306/dms
spring.datasource.username=root
spring.datasource.password=test
spring.datasource.testWhileIdle = true
spring.jpa.show-sql = true

#liquibase
com.foo.bar.liquibase.changelog=classpath:/db/changelog/db.changelog.xml

when I run my application I receive this error:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'liquibaseConfiguration': Unsatisfied dependency expressed through field 'dataSource': No qualifying bean of type [com.mysql.jdbc.jdbc2.optional.MysqlDataSource] found for dependency [com.mysql.jdbc.jdbc2.optional.MysqlDataSource]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.mysql.jdbc.jdbc2.optional.MysqlDataSource] found for dependency [com.mysql.jdbc.jdbc2.optional.MysqlDataSource]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Now I understood that this means the application cannot autowire the MysqlDataSource dataSource; but I need to pass the data source to liquibase bean. How can I do that?

3

There are 3 answers

2
A0__oN On BEST ANSWER

Here's a simple step to integrate liquibase in spring boot

STEP 1

Add liquibase dependency

Gradle

runtime "org.liquibase:liquibase-core"

Maven

<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
    <scope>runtime</scope>
</dependency>

STEP 2

Add liquibase changelog file path in application.yml

liquibase:
  enabled: true #this is optional as enabled by default
  change-log: classpath:/liquibase/db-changelog.xml

Notice property liquibase.change-log. I'm referring path as /liquibase/db-changelog.xml. so you should have a file name db-changelog.xml inside src/main/resources/liquibase/

STEP 3

Add your changesets on the file and when Spring-Boot application is started (spring-boot:run) your changeset will be loaded.

This will use default dataSource that your app uses.

More Info: http://docs.spring.io/spring-boot/docs/1.4.3.RELEASE/reference/htmlsingle/#howto-execute-liquibase-database-migrations-on-startup

Update

For Spring Boot 2.0 as @veben pointed out in comment use

spring:
    liquibase:
        change-log: #path
0
Joseph G Gori On

Rather than autowire the datasource, create a method in your Liquibase Configuration Object to create the datasource.

private DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUsername("user");
    dataSource.setPassword("pswd");
    dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/db");
    dataSource.setSchema("dbName");
    return dataSource;
}

then in your bean generation method

liquibase.setDataSource(dataSource());

This gives you a chance to specify the database parameters on the fly, I still had the changelog location in the applications.properties file along with the enablement of liquibase. I've tried it, and it works for me.

0
DoNuT On

I had a similar construct for my application, have you tried injecting a more generic javax.sql.DataSource instead?

My guess is that Spring uses the non-specific type for this bean, on top of that you shouldn't even use a database-specific type if your application could be configured to use a totally different source, i.e. by just changing the datasource URL in the configuration file.