Reputation: 511
I am doing an tomcat appliaction in a windows enviroment that when deployed creates/updates the DB Schema on the oracle db. For this I am using the Liquibase SDK 3.3.2. So basically I call the SDK an tell it to do an update from my changelog.xml. This parts works as fine. The code form the java class
...
Liquibase liquibase = new Liquibase(CHANGE_LOG,
new ClassLoaderResourceAccessor(getClass().getClassLoader()), db);
liquibase.update("");
The problem is, when something goes wrong and I do a Rollback from the command line nothing happens. I get no exceptions or error messages. Just a message "Rollback succesfull", but in the DB there is no change at all. Now the funny thing is when I do the update for my change log file from cmd and then do the rollback also from the cmd then the Rollback works. The command line call looks as following:
Liquibase --changeLogFile=C:\myProject\src\main\resources\database\master.xml --logLevel=DEBUG rollbackCount 5
My liquibase.properties file looks as following:
driver: oracle.jdbc.OracleDriver
classpath:ojdbc6.jar
url: jdbc:oracle:thin:@192.168.56.101:1521:orcl
username: myUser
password: mypassword
The question does some know why does this happens? Are there any incompatibilties between SDK and cmd tool?
Upvotes: 4
Views: 6953
Reputation: 697
This same issue happened to me. As stated, the classpath reference for liquibase runner was different when executed via SpringBoot application vs Gradle task. In order to fix it I had to add the following to my dependencies
closure in my build.gradle
file.
liquibaseRuntime files("src/main/resources")
Adding this seems like fix the issue.
Upvotes: 0
Reputation: 391
For the benefit of other readers, I'd like to add my experiences and understanding.
It's important to understand what is happening when you run a rollback from the command line
Liquibase consults the changelog file you provided via the --changeLogFile
argument.
It will iterate through the changesets mentioned in this file, comparing their checksum to the checksum for the corresponding record in the DATABASECHANGELOG
database table.
Now here's the important bit: the checksum is calculated from the filename (including the path) and the file contents.
If the checksums do not match, the changeset is not eligible for rollback.
If you ran Liquibase from inside a web-application, the chances are that the Liquibase changelog was located on the classpath, which means that the filename column in the DATABASECHANGELOG
table is prefixed with classpath:
ID AUTHOR FILENAME CreateWidgetTable NabilH classpath:liquibase/sprint1/create.widget.table.xml
This is not the case when you run via the command line
This will cause the checksum validation to fail and changeset to be ignored
However, I think there is a better solution than what you have proposed. You can point the --classpath
argument of Liquibase command line at your WAR, and specify the --changeLogFilePath
relative to the classpath.
Assume that I store my changelog in src/main/resources/liquibase/changelog.xml
.
On the classpath therefore, this file is accessible via liquibase/changelog.xml
.
java -jar lib/liquibase-core-3.5.3.jar\
--url=jdbc:h2:tcp://localhost/~/test --username=sa --password=\
--logLevel=DEBUG --classpath=/opt/tomcat9/webapps/springLiquibase.war\
--changeLogFile=liquibase/changelog.xml rollback v1
Upvotes: 4
Reputation: 511
The problem was the path to the change log file. Liquibase stores somewhere the path to the chengeLog and comapres it to the given change log at calling. If they are not the same Liquibase will just go on without a changeLog and warning.
So in my case when calling Liquibase from the tomcat app the path was: database\master.xml and when calling it from the console I gave the path C:\myProject\src\main\resources\database\master.xml in the comand line. This caused the method to return null although Liquibase knew the path to the changeLog. So that was the reason it did not worked.
A workaround is to call liquibase from the command line from the same folder as the application did using a relative path.
Technical reason: After debuggin LB I found this. The Method DatabaseChageLog.getChangeSet() is returning null althoug the chanegeLog path is correct. This happens when creating the ChangeLogIterator for runnign the RollbackVisitor in the method Liquibase.rollback(int changesToRollback, Contexts contexts, LabelExpression labelExpression). This do not happens with the ValidationVisitor becasuse the ChangeLogIterator is created differently, that is why I did not get any error\warnings
Upvotes: 9