I recently took on the task of integrating Liquibase into the project I’m working on at work. I’d played around with Liquibase before on small personal projects, but had never faced applying it to an existing, large and in-production database.

I ran into a few problems when using the LiquibaseServletListener after having previously run changelogSync via the command line. Basically, Liquibase was trying to execute the changesets in my changelog files even though they had already been executed during changelogSync. I couldn’t understand why.

I had executed Liquibase’s changelogSync from the command line in the same directory as the file generated by generateChangeLog, something along these lines:

liquibase --driver=com.mysql.jdbc.Driver \
  --classpath=mysql-connector-java-5.1.13-bin.jar \
  --changeLogFile=accounts-changelog-schema.xml \
  --url="jdbc:mysql://localhost:3306/accounts" \
  --username=user --password=password changelogSync

Afterwards, the rows in Liquibase’s DATABASECHANGELOG table indicated everything had worked, and each of the changesets had an EXECTYPE of EXECUTED, which should have meant when the servlet listener started up the changesets would be skipped over. But Liquibase was trying to execute the changesets and I was getting a log full of errors.

Turns out that because I had defined my changelog file in a subdirectory:

<context-param>
  <param-name> liquibase.changelog</param-name >
  <param-value>db/changelog/accounts-changelog-schema.xml</param-value>
</context-param>

And had run changelogSync from the same directory as the generated changelog (which meant the FILENAME field for each changeset was ‘accounts-changelog-schema.xml’), the FILENAME field didn’t match. Hence Liquibase’s attempts to re-run the changesets.

Fixing the problem was simply a matter of updating the database

update DATABASASECHANGELOG set FILENAME = 'db/changelog/accounts-changelog-schema.xml';