Heyo,
As mentioned in the GitHub issue I have a workaround. A solution is yet to be implemented.
You can manually register a shutdown hook before running spring boot.. That hook should assure that the Termination is postponed until liquibase is done.
package dang;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableJpaRepositories
@SpringBootApplication
public class DangApplication {
public static void main(String[] args) throws InterruptedException {
Thread thread = new GracefulShutdownHook();
Runtime.getRuntime().addShutdownHook(thread);
new SpringApplicationBuilder(DangApplication.class)
.registerShutdownHook(true)
.logStartupInfo(true)
.build()
.run();
Runtime.getRuntime().removeShutdownHook(thread);
}
}
And the hook:
package dang;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class GracefulShutdownHook extends Thread {
@SneakyThrows
@Override
public void run() {
super.run();
log.info("Shutdown Signal received.. Searching for Liquibase instances!");
boolean liquibaseIsRunning = true;
while (liquibaseIsRunning) {
Map<Thread,StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
for(Map.Entry<Thread, StackTraceElement[]> entry : stackTraces.entrySet()) {
StackTraceElement[] stackTraceElements = entry.getValue();
for (StackTraceElement stackTraceElement : stackTraceElements) {
if (stackTraceElement.getClassName().contains("liquibase") && stackTraceElement.getMethodName().contains("update")) {
try {
log.warn("Liquibase is currently updating");
entry.getKey().join();
liquibaseIsRunning = false;
} catch (InterruptedException e) {
log.error("Shutdown Hook was interrupted.. Fatal databaselock may be imminent", e);
if (Thread.interrupted()) {
throw e;
}
}
}
}
}
}
}
}
EDIT
After implementing my workaround a contributor of liquibase shared a different solution (It's actually the same solution just through Spring functionality) which is much better than what I did:
package dang;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableJpaRepositories
@SpringBootApplication
public class DangApplication {
public static void main(String[] args) throws InterruptedException {
new SpringApplicationBuilder(DangApplication.class)
.initializers(ConfigurableApplicationContext::registerShutdownHook) // Registers application hook before liquibase executes.
.logStartupInfo(true)
.build()
.run();
}
}