Loading data from properties file to be used by Liquibase in Maven build

Taoufik Mohdit picture Taoufik Mohdit · Mar 12, 2014 · Viewed 23.7k times · Source

I can run Liquibase changelog through maven build (liquibase:update goal) without any problems. Now I'd like Liquibase to use database credentials and URL loaded from a properties file (db.properties) depending on the selected Maven profile:

|-- pom.xml
`-- src
    `-- main
        `-- resources
            |-- local
            |   `-- db.properties
            |-- dev
            |   `-- db.properties
            |-- prod
            |   `-- db.properties
            `-- db-changelog-master.xml
            `-- db-changelog-1.0.xml

Each of the 3 properties files would look like the following:

database.driver = oracle.jdbc.driver.OracleDriver
database.url = jdbc:oracle:thin:@<host_name>:<port_number>/instance
database.username = user
database.password = password123

Now, instead of these properties being defined in the POM file itself (as explained in the accepted answer of this question liquibase using maven with two databases does not work), I'd like them to be loaded from the external properties file. I have tried different approaches to no avail:

1. I used Maven's resource element in the POM file:

<build>
      <pluginManagement>
         <plugins>
            <plugin>
               <groupId>org.liquibase</groupId>
               <artifactId>liquibase-maven-plugin</artifactId>
               <version>3.1.0</version>
               <configuration>
                  <changeLogFile>db.changelog-master.xml</changeLogFile>
                  <verbose>true</verbose>
               </configuration>
            </plugin>
         </plugins>
      </pluginManagement>
   </build>


<profiles>
    <profile>
        <id>local</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <resources>
                <resource>
                    <directory>src/main/resources/local</directory>
                </resource>
            </resources>
        </build>
        <properties>
            <liquibase.url>${database.url}</liquibase.url>
            <liquibase.driver>${database.driver}</liquibase.driver>
            <liquibase.username>${database.username}</liquibase.username>
            <liquibase.password>${database.password}</liquibase.password>
        </properties>
    </profile>
    <profile>
        <id>dev</id>
        <build>
            <resources>
                <resource>
                    <directory>src/main/resources/dev</directory>
                </resource>
            </resources>
        </build>
        <properties>
            <liquibase.url>${database.url}</liquibase.url>
            <liquibase.driver>${database.driver}</liquibase.driver>
            <liquibase.username>${database.username}</liquibase.username>
            <liquibase.password>${database.password}</liquibase.password>
        </properties>
    </profile>
</profiles>

2. I tried using the Properties Maven plugin:

   <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>properties-maven-plugin</artifactId>
      <version>1.0-alpha-2</version>
      <executions>
         <execution>
            <phase>initialize</phase>
            <goals>
               <goal>read-project-properties</goal>
            </goals>
            <configuration>
               <files>
                  <file>src/main/resources/local/db.properties</file>
               </files>
            </configuration>
         </execution>
      </executions>
   </plugin>

When I run the liquibase:update maven goal, I get this this error:

[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.1.0:update (default-cli) on project my-project: The driver has not been specified either as a parameter or in a properties file

It seems that the database properties referred to in the POM file couldn't be resolved.

Any idea how this can be achieved ?

Answer

Taoufik Mohdit picture Taoufik Mohdit · Mar 13, 2014

I managed to get this working. The key was to use the maven filter element in conjunction with the resource element as explained in Liquibase Documentation.

Also it's important to include the resources goal in the maven command:

mvn resources:resources liquibase:update -Plocal

This is the file hierarchy I used:

|-- pom.xml
`-- src
    `-- main
       |-- resources
       |   `-- liquibase.properties
       |   |-- changelog
       |       `-- db-changelog-master.xml
       |       `-- db-changelog-1.0.xml
       |-- filters
           |-- local
           |   `-- db.properties
           |-- dev
           |   `-- db.properties

The db.properties file would look like the following:

database.driver = oracle.jdbc.driver.OracleDriver
database.url = jdbc:oracle:thin:@<host_name>:<port_number>/instance
database.username = user
database.password = password123

The liquibase.properties file would look like the following:

changeLogFile: changelog/db.changelog-master.xml
driver: ${database.driver}
url: ${database.url}
username: ${database.username}
password: ${database.password}
verbose: true

The POM file would look like the following:

<build>
      <pluginManagement>
         <plugins>
            <plugin>
               <groupId>org.liquibase</groupId>
               <artifactId>liquibase-maven-plugin</artifactId>
               <version>3.1.0</version>
               <configuration>
                  <propertyFile>target/classes/liquibase.properties</propertyFile>
               </configuration>
            </plugin>
         </plugins>
      </pluginManagement>
   </build>


<profiles>
    <profile>
        <id>local</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <filters>
                <filter>src/main/filters/local/db.properties</filter>
            </filters>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    </profile>
    <profile>
        <id>dev</id>
        <build>
            <filters>
                <filter>src/main/filters/dev/db.properties</filter>
            </filters>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    </profile>
</profiles>