Upgrading from Liquibase 3.x to 4.x

I know it’s been a while since 4.0 has been released, but we still get questions about a common challenge with this upgrade.

If you see this error message, please read this post to know how to fix it.

Error Message

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

Background

When you reference a changelog file like /path/to/changelog.xml or path/to/changelog.xmlorchangelog.xml`, Liquibase has always looked for those by searching through all the directories and files in your “classpath”. It has never mattered whether you have a / at the beginning of your filename or not, the path you give is always looked for inside the entries in your classpath.

For example, if you have a classpath configured as:

  • /home/your-user
  • /liquibase/my-project
  • /liquibase/shared/files.zip

and a changelogFile of path/to/changelog.xml (or /path/to/changelog.xml`)

then, Liquibase will look for that changelog file as:

  • /home/your-user/path/to/changelog.xml
  • /liquibase/my-project/path/to/changelog.xml
  • inside /liquibase/shared/files.zip for an entry named path/to/changelog.xml

Exactly what is in your configured classpath is made up of two things:

  1. What you list in your classpath argument/liquibase.properties setting/etc.
  2. A default list of “normal” locations that the CLI/Maven/Ant/etc. interfaces know users normally expect to look for files in.

What Changed in 4.0

Prior to 4.0, one of the default classpath entries that the CLI used was your filesystem root directory. We removed that in 4.0 for several reasons.

Partly it was because it harmed performance, since includeAll path="/" would search your entire filesystem.

But also because the the reason for the “look up changelog files relative to the classpath entries” logic exists to avoid machine-specific paths. Liquibase uses the path to the changelog file as part of each changeset’s unique identifier and so that needs to remain consistent, even if your project gets moved to a different directory on the same machine or ran from another machine. To keep those paths consistent, you really want to have the classpath entry be the “machine dependent” part so that the path to the changelog file is always consistent.

By having the root of your filesystem as a default classpath entry, it was too easy for new users to just reference their changelog files with machine-dependent “absolute” paths. That works fine at first, but at some point will burn them and we want to avoid that.

Adjusting to the Change

If you are already using changelog paths relative to a classpath entry besides the root directory, there is no change you need to make. If you are seeing the “Specifying files by absolute path was removed in Liquibase 4.0.” message, it is just because the path isn’t being found as you are expecting.

If you had been trying to reference the file relative to the root directory, you have two options:

  1. Add / to your classpath setting. This brings back the old behavior with both the possible performance issue to watch for and the possible machine-dependent issues. But, if those are not a problem for you this is an easy solution.
  2. Correctly configure your classpath and update your changelogFile references to be relative to those classpath entries. Because your ran changesets will be stored with the complete path from before, you’ll need to add logicalFilePath to the changelog files to override the path portion of the changeset identifier.

Nathan

1 Like

Hi @nvoxland, Thank you for posting the suggestion! :slight_smile:

Hi @nvoxland ,
We are migrating from 3.10.3 to 4.7.1. My changelog.xml file is present in JAR file inside an ear which is set as classpath parameter. After migration to 4.7.1 i am always seeing the error “Specifying files by absolute path was removed in Liquibase 4.0. Please use a relative path or add ‘/’ to the classpath parameter.”. And no matter if i set the --changeLogFile=/changelog.xml or --changeLogFile=changelog.xml it is still failing. It seems liquibase is reading changelog.xml only if its available directly in the ear. Is there any other way to configure the changeLogFile parameter with out making changes to the ear file?

Thanks

Hi,I am getting the below error. please help me how to fix this
updateDatabase doesn’t support the “driver” attribute"

There are some breaking changes not mentioned related to the relative path changes. I think they are down to PR #1225, but not totally sure.

Say you have this layout:

src/main/resources/database/db.changelog-master.xml 
src/main/resources/database/changelogs/20180823-2054-attachments-table.xml

A master changelog file that includes other files in the ./changelogs directory. Typically like this:

    <include file="changelogs/20180823-2054-attachments-table.xml" relativeToChangelogFile="true"/>

In Liquibase 3 the file name used in the tables for this included file would be changelogs/20180823-2054-attachments-table.xml - meaning it was relative to the master file.

In Liquibase 4, the file name would be the full classpath name: database/changelogs/20180823-2054-attachments-table.xml. This is a breaking change not mentioned anywhere, AFAIK

I have not seen any way of keeping the old behavior, so AFAIK there are really just two workarounds:

  • set logicalFilePath for every script. Nothing then needs to change location, but all files need touching now and forever.
  • move all files up one level, dropping the database directory. This is the least invasive, but if you really liked the previous layout, that sucks a bit.

In case you know of a third option, like a Liquibase setting, let me know :wink:

A third option would be to do a one-time update to the databasechangelog table, which I had to do for one application that did a similar upgrade.

1 Like