quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.87k stars 2.71k forks source link

Hibernate Reactive selects and stores a `Clock` before application is given any control #43577

Open kdubb opened 2 months ago

kdubb commented 2 months ago

Describe the bug

Hibernate Reactive stores a Clock for use when injecting temporal values (e.g., @CurrentTimestamp or @CreationTimestamp).

This means the only way to set the time zone to UTC is to use system properties and/or the environment, which is painful. It requires you to update multiple build tasks (in Gradle) and ensure it's set properly in production before starting the app.

Also, there appears to be a hibernate.testing.clock property it checks during its Clock caching, but I have found no way to set that in Hibernate Reactive.

Expected behavior

Users have an easy way to set the clock to UTC for dev and, more importantly, testing.

During my experience in tracking this down, the easiest method was thought to be using @QuarkusMain or @Observes StartupEvent, but neither of these works because the Clock is cached prior to application code getting control.

Actual behavior

The Clock is cached before any code can run.

This leaves the developer tracking down which build tasks need to be configured with JVM args to set the clock to their chosen timezone.

Additionally, when running without a build tool, you need to set the timezone via JVM args as well.

How to Reproduce?

  1. Create a Gradle project with Hibernate Reactive
  2. Add an @Entity with @CreationTimestamp
  3. Run ./gradlew -Duser.timezone=UTC quarkusDev or quarkus -Duser.timezone=UTC dev
  4. This will set the clock to UTC for the running dev mode.
  5. Resume continuous testing, the Hibernate clock will now use the OS's current time zone.

Output of uname -a or ver

macOS 14.6.1

Output of java -version

21.0.1

Quarkus version or git rev

3.15.1

Build tool (ie. output of mvnw --version or gradlew --version)

Gradle 8.9

Additional information

No response

quarkus-bot[bot] commented 2 months ago

/cc @DavideD (hibernate-reactive), @gavinking (hibernate-reactive)

kdubb commented 2 months ago

It should be noted that due to this issue and the inability to set the timezone for all configurations (see #43578), we ultimately abandoned using Hibernate's @CreationTimestamp and @UpdateTimestamp, which use the cached Clock with the default time zone.

codespearhead commented 2 months ago

Set those two properties [1][2] and try again:

quarkus.hibernate-orm.mapping.timezone.default-storage=normalize
quarkus.hibernate-orm.jdbc.timezone=UTC

[1] https://quarkus.io/guides/all-config#quarkus-hibernate-orm_quarkus-hibernate-orm-mapping-timezone-default-storage [2] https://quarkus.io/guides/hibernate-reactive

kdubb commented 2 months ago

It'll take me a bit to test this. I am currently a bit swamped and as I said, we abandoned any use of the Clock in Hibernate and instead made a base class to handle the creation and update of timestamps.