How Liquibase Finds Files: Liquibase Search Path
Note: The search-path property is available in Liquibase v4.13 and later.
During the Liquibase installation process, the installer creates directories and installs several files including JAR files. Liquibase is an extensible tool that enables users to add functionality and integrations to the standard installation packaged as one or more JAR files that can be downloaded separately.
JAR files are packages of aggregated Java class files and associated metadata built on a ZIP format which contains application functionality. In order to use the functionality of the JAR file, Liquibase needs to find the JAR file.
In addition to JAR files, Liquibase also needs to find the changelog and looks for both of these file types in the following locations:
- Any paths specified in the classpath setting.
- The current working directory.
- A liquibase_libs directory in the current working directory.
- A lib directory in the Liquibase install location.
- Inside any .zip or .jar files in the
liquibase_libs
orlib
directories. - Using
--search-path
(v4.13 and later). For more information about--search-path
, continue reading this page.
Note: Liquibase uses the classpath to find all JARs in any location you specify except for extension JARs, such as the Liquibase extension for DynamoDB. Extension JARs included via classpath must go in one of the following locations: ./liquibase_libs
, lib
, internal/lib
, or internal/extensions
.
Liquibase uses the paths to files as part of changeset identifiers. It is important for these paths to remain consistent and stable, because they are often included in shared changelog files, even when the physical location of those files may change from machine to machine.
To provide that separation between the file reference and the physical location of the file, Liquibase uses the concept of a "search path." The search path is the list of base physical locations where given changelog paths can be found. For each file to look up, Liquibase will check all those locations for the file.
For example, if your referenced file path is db.changelog.xml
and your search path is /Users/example/liquibase,/projects/global
, Liquibase will look for /Users/example/liquibase/db.changelog.xml
and /projects/global/db.changelog.xml
.
For example, if your referenced file path is project1/db.changelog.xml
and your search path is /Users/example/liquibase,/projects/global
, Liquibase will look for /Users/example/liquibase/project1/db.changelog.xml
and /projects/global/project1/db.changelog.xml
.
It does not matter if your referenced file path starts with a /
or not, Liquibase always looks up the file path within your search path.
Liquibase configures the search path based on these factors:
- The path specified in the
--search-path
setting - Default locations based on how you run Liquibase
- CLI: the current working directory where Liquibase commands are running, plus everything in your
LIQUIBASE_HOME/lib
andliquibase_libs
directories, plus the classpath setting - Maven: project’s classpath
- Spring Boot: application’s classpath
Note: When
--search-path
is set, Liquibase will only search along that path and it overrides the default settings. - CLI: the current working directory where Liquibase commands are running, plus everything in your
Syntax
You can set this parameter in the following ways:
Option | Syntax |
---|---|
Liquibase properties file (defaults file) |
|
Global flow file argument (example) |
|
Global CLI parameter |
|
JVM system property (JAVA_OPTS Environment Variable) |
|
Liquibase Environment Variables |
|
For more information, see Working with Command Parameters.
Tip: If you use Maven, Ant, Spring Boot, or other integrations, you can set your searchPath
in the default files, such as pom.xml
, application.yml
, and others. Check the Tools & Integrations documentation for more information.
How the Liquibase search path worked before version 4.13
Before version 4.13, the search path was not configured separately from the classpath. The logic of always looking up file references via a set of base locations was the same, but the only way to configure those locations was through the classpath configuration.
Before version 4.0, one of the default locations Liquibase added to the searchPath/classpath was the root directory in your filesystem (/). The change caused issues because of a machine-dependent changelog path, such as /home/my-user/projects/liquibase/changelog.xml
, found under the /
directory. This way, Liquibase uses the given path as part of the changeset identifier stored in the DATABASECHANGELOG table, and when you run Liquibase from /home/other-user/projects/liquibase/changelog.xml
, Liquibase sees it as a different changelog and tries to rerun all the previously run changesets.
To prevent identification issues from happening, a /
was removed as a default part of the searchPath/classpath.
How the Liquibase searchPath works in 4.0 and later versions
Starting with Liquibase 4.0, the root directory (/) is no longer a default part of the searchPath/classpath because of the issue mentioned in the previous section.
To migrate from your existing searchPath/classpath format, including the root directory (/), to version 4.0+, you can do any of the following:
- Configure your searchPath to include
/
. The configuration brings back an old behavior with no file changes. - Add the logicalFilePath attribute to the root element of your changelog files. When you set the
logicalFilePath
value to be an old file reference name, Liquibase uses it for the comparison file name, which will match what is in the database. If you add thelogicalFilePath
, it will bring back the old behavior with file changes, and you will not have any runtime configuration changes. - Coordinate updates to the DATABASECHANGELOG table so that the filepath value gets changed to be a new path. You can do it with a single SQL statement, but the exact statement will depend on the database you use. See a PostgreSQL example:
Example: update databasechangelog set filepath=substring(filepath, length('/src/my-project')
You need to figure out the SQL statement and time when you run that statement because any passed existing references will start failing once you make the change, and any passed new references will fail until you do make the change.