2

I currently develop a project with Hibernate and WildFly. The database I'm using is a mariaDB.

When I insert a java.time.Instant into the database, the JPA applies two hours on the inserted timestamp (which is always UTC in the java code).

I tried to start WildFly with -Duser.timezone=UTC in the standalone.conf (Java Opts) and command-line argument. The management console shows this timezone, but all log-output and database inputs are in my system timezone (+2). When I set my Windows timezone to UTC, the odd behaviour stops and the times in the database are correct.

I also tried to set the hibernate property <property name="hibernate.jdbc.time_zone" value="UTC"/> and on my mariaDB SET GLOBAL time_zone = "+00:00" which didn't work as well.

What am I missing here?

maio290
  • 6,440
  • 1
  • 21
  • 38
  • Assuming you're working with a `timestamp` type in the database, likely something is setting the *session* time zone for the connection. See about [Connection Time Zones](https://mariadb.com/kb/en/library/time-zones/#connection-time-zones) in the docs. – Matt Johnson-Pint May 10 '18 at 05:55
  • This should be fixed with the jbdc.time_zone - which didn't work as well... – maio290 May 15 '18 at 10:43

2 Answers2

1

If you want to be sure that your Java app will always be UTC, you should override the JVM timezone at application startup.

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

Source

How do I programmatically set the time zone in Java?

By doing this, you will override any other weird timezone configuration of your deployment servers, my understanding is that the behaviour you're expecting here.

This code should be added to application startup. It depends on the framework you're using.

For JEE5+, you can create singleton boostrap EJB:

@Singleton
@Startup
public class StartupBean {

    @PostConstruct
    private void startup() {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }
}

For Springboot 1.5+, you can create a hook anywhere with this:

@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
Benjamin Caure
  • 2,090
  • 20
  • 27
  • I just tried the version with the Singleton and StartupBean, it's not working. Again, all times in the database are shifted by two hours and not UTC. :/ – maio290 May 09 '18 at 13:45
  • OK so lets admit jvm and db are both set properly to UTC. Problem might come from user input : is it stored 2 hours less or 2 hours more in db ? User inputs comes from JSP/JSF or REST API ? – Benjamin Caure May 09 '18 at 19:52
  • It's stored +2 hours, in my system's timezone. However, I think it's a bug related to Hibernate, therefore I've opened a bug there: https://hibernate.atlassian.net/browse/HHH-12578 – maio290 May 15 '18 at 10:36
1

So the answer to this problem was rather easy.

I used the Hibernate version packed with WildFly12 - which is 5.1.10. According to Chris Cranford

the hibernate.jdbc.time_zone setting wasn't introduced until 5.2.3

although no error was thrown by any subsystem here. Updating your Hibernate will do the trick.

  1. Go into wildfly-12.0.0.Final\modules\system\layers\base\org\hibernate\main
  2. Download the core and envers library and put it into the folder.
  3. Modify the module.xml and update the versions and remove the -java8-* and entitymanger-*.jar -> they are depreacted and moved into the core.
  4. Restart your WildFly and your problems will be gone.

There might be a good reason why the WildFly team didn't use a newer Hibernate version, but I'm not sure, why. So it could be that you have some errors / unwanted behaviour with the swapped libraries.

Actually, a simple error message that the property is unknown could have saved me some time. Either I didn't find it within the logs or it's just not a error...

maio290
  • 6,440
  • 1
  • 21
  • 38