Manual run of SpringLiquibase uses wrong timezone

Viewed 389

I use liquibase to reset my database between tests. From a standard spring boot run at the start of my tests it inserts data with the correct TZ. When I run it manually, it applies a different TZ.

I have application.properties set up with spring.jpa.properties.hibernate.jdbc.time_zone=UTC and liquibase enabled. When inserting time data into a time column, it inserts 12:00:00 without issue.

When I try to rerun liquibase between my tests, everything is fine except times are inserted with the current local TZ (+01:00) giving me 13:00:00 instead.

@Autowired
SpringLiquibase liquibase;

public void clean() {
   liquibase.setShouldRun(true);
   liquibase.setDropFirst(true);
   liquibase.afterPropertiesSet();
}

There is a setChangelogProperties method, but I cannot find documentation for any TZ related stuff.

I have tried reinjecting the DataSource, tried TIME, TIME WITHOUT TIMEZONE, but to no avail.

When re-running the same SpringLiquibase bean run during the application initialisation I would expect the same TZ info and any other config to be maintained and reused.

UPDATE

After trying many different timezone settings throughout the tests, the only thing that has worked is -Duser.timezone=UTC from the command line.

Setting this as System.setProperty("-Duser.timezone","UTC") as early as I can, and also prior to re-running liquibase has no effect.

Is there a way I can get spring to set this for before it loads everything?

It is strange that the first run via spring is fine, but consequent ones appear to lose the timezone setting.

UPDATE 2

Setting TimeZone.setDefault(TimeZone.getTimeZone("UTC")) either never gets picked up or does not happen early enough.

Adding the following to my test runner

    static {
        System.setProperty("UTC");
    }

also appears to not execute earlier enough, or does not get propagated properly to liquibase.

It definitely feels like SpringLiquibase is going by its own rules, or something strange is happening with the driver loading

1 Answers

Just had this issue because liquibase was loading H2 before the timezone was set. As you've noticed there's an important gap between setting the Timezone on the JVM/command-line, and the first time you have access to the code to set it in the test.

Earlier than ContextRefreshedEvent even, you have to use a custom ApplicationContextInitializer (kotlin, soz):

class MyInitializer() : ApplicationContextInitializer<ConfigurableApplicationContext> {
  @Override
  override fun initialize(applicationContext: ConfigurableApplicationContext) {
        TimeZone.setDefault(TimeZone.getTimeZone(ZoneOffset.UTC))
  }
}

then to register it, add to a property class: context.initializer.classes=com.foo.MyInitializer

Related