Last Updated: February 25, 2016
·
1.36K
· bripkens

Automatically applying Liquibase changesets to HSQL

This is a quick tip for usage of Liquibase with HSQL. You may use the former tool for relational database schema migrations and the latter as in-memory database on the developers’ machines. Today, with feature branches and project customisation, i.e. changes that are specific for a single customer, you may have to shutdown the database, restart and reapply the migrations on a regular basis. Of course, this is a task that can be automated!

Typical situation: you are working on the project’s main development branch, but you now wish to review a colleague’s new feature, which has been developed in a feature branch. You switch to the feature branch, start the server, open the application and BAM, an exception occurs due a failed schema validation. The reason: your colleague made some schema changes in the feature branch that you forgot to apply.

Improving your Liquibase and HSQL workflow is rather simple: restart the database whenever the schema changes and apply the migrations! This is how you can do it in bash (sorry Windows users).

#!/bin/bash
set -e

HSQL_PID=""
PROJECT=""

if [[ $1 = "customisation" ]]; then
    echo "Using customer specific changelogs..."
    PROJECT="$PROJECT_REPO/customisation"
else
    echo "Using default changelogs..."
    PROJECT="$PROJECT_REPO/database"
fi

control_c() {
    kill $HSQL_PID
    exit
}
trap control_c SIGHUP SIGINT SIGTERM 0

start() {
    # Start HSQL
    java -cp "$M2_REPO/org/hsqldb/hsqldb/2.2.9/hsqldb-2.2.9.jar" \
         org.hsqldb.Server \
         -database.0 mem:myDB \
         -dbname.0 myDB &
    HSQL_PID=$!

    # Schema update
    mvn -f "$PROJECT/pom.xml" liquibase:update -Plocal --no-snapshot-updates
}

start

while true; do
    if hash inotifywait 2>/dev/null; then
        WATCH_DIR="$PROJECT/src/changelogs"
        echo "Watching $WATCH_DIR for changes..."

        # Wait for changelog changes
        inotifywait --recursive $WATCH_DIR \
                    --event modify \
                    --event move \
                    --event create \
                    --event delete

        # Just a precaution: wait until the VCS is done changing the branch
        sleep 1
    else
        echo "[Press any key to discard the schema and apply a new one...]"
        read
    fi

    # kill HSQL and wait until it is actually shut down
    kill $HSQL_PID
    while kill -0 "$HSQL_PID"; do
        sleep 0.1
    done

    start
done

You need to make sure that you have two environment variables setup. There should be a variable PROJECTREPO which points to the root directory of your project’s repository and M2REPO which points to the Maven repository. You may also need to tweak a few paths, e.g. the version of HSQL that you are using as well as the Maven project and profile names. At last, you should install the inotify-tools (unfortunately not available on OS X). inotifywait (part of the inotify-tools) is used to watch the changelog directory for changes. The project’s Wiki has a section on installation.

Once setup, usage is pretty easy: start the script and let it do the rest. When the inotify-tools are not installed, you need to switch to your terminal and hit “the any key” in order to discard the current and apply a new schema.