Chris J
Chris J

Reputation: 1447

Setting Liquibase Java use changelogs outside of the classpath/jar

I'm using Liquibase with Maven in a project - v4.2.0.

My changelogs are on the file system, rather than in the JAR or classpath of the project.

I'm using the following to establish my object:

liquibase = new Liquibase( changeLogFile, new FileSystemResourceAccessor(), database );

where the changelogFile is something like ~/liquibase-sql/changelog/db.changelog.xml

When I call liquibase.validate(), I get the following, after a reminder of the classpath locations:

Specifying files by absolute path was removed in Liquibase 4.0. Please use a relative path or add '/' to the classpath parameter.

I've tried various things including a file: prefix, and the file is question can be opened in terminal directly.
I have looked through the code and I'm confused by the concept of FileSystemResourceAccessor being named as such if it can only use the classpath (there's already a ClassLoaderResourceAccessor), but I can't see a way to make it work.

Based on very very old questions people have managed this before, but I assume prior to 4.0? (this works fine on 3.10.3)

Does anyone have any pointers? I've used CLI liquibase and understand the error, but I'm not sure how I can not determine the path without it being absolute, on the understanding that this would be potentially be ran on a few different machines in arbitrary locations.

This might be niche question, but thanks for any help in advance.

Upvotes: 8

Views: 3932

Answers (3)

tuk
tuk

Reputation: 6852

I am using liquibase 4.5.0 and the below thing worked for me.

val database =
        DatabaseFactory.getInstance()
            .findCorrectDatabaseImplementation(
                new JdbcConnection(
                    DriverManager.getConnection(
                        jdbcUrl,
                        getPostgresContainerConfig().username(),
                        getPostgresContainerConfig().password())));

new liquibase.Liquibase(
           "analytics/target/classes/create_db.sql",
            new FileSystemResourceAccessor(
                new File("/Users/debrajmanna/code/java/github/sp/src/java/")),
            database);

My file was in /Users/debrajmanna/code/java/github/sp/src/java/analytics/target/classes/create_db.sql

Upvotes: 0

Peter S.
Peter S.

Reputation: 591

I would like to react to putting scripts outside of classpath/jar. I took a look around because we wanted to do this as well.

From my point of view, I would say it is not a good approach because anyone can go to the location of the scripts and touch these files which can cause Liquibase to fail. Except that you can go and put any script to that location and modify a database.

I think the authors of Liquibase know why there is no straightforward approach to how to do that.

Upvotes: 0

demaniak
demaniak

Reputation: 3915

Here is what I ended up doing (for a gradle-based project):

  • force the external location to actually be part of the classpath
  • changed the XSD location to full URL (apparently liquibase has enough smarts to NOT fetch that from online location, but instead load from the cache of XSD files bundled with the distribution JAR.

For gradle, this meant adding some stuff to build.gradle like so:

sourceSets {
  test {
    //whatever else you have
    resources {
      srcDir 'src/test/resources'
      srcDir 'top-external-folder-of-changelog'
    }
  }
}    
dependencies {
  testImplementation files (path/to/external/folder)
}

The changelog schemaLocation attribute then looks like this:

xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.11.xsd"

Remember to adjust for your version,

My specific issues was with tests. For real environments, the liquibase scripts are applied to the database via an external (liquibase-based) tool.

Upvotes: 3

Related Questions