Java 8 finally brought the long-awaited equivalents of Joda’s LocalDate and LocalDateTime classes to the core Java API. They’re available in the java.time package. Unfortunately, JPA had been a little slow to pick up on the changes, and so persisting the new LocalDate and LocalDateTime properties of your entities is kind of a pain.
JSON serialization of your entities is actually pretty straightforward, following the example set in this blog post by Chris Ritchie.
Persistence, on the other hand, relied until recently on a custom converter, as described here by Adam Bien. Running locally, we were able to make good use of a converter on our current project. Unfortunately, for reasons that are still unclear to me, we started seeing StreamCorruptedExceptions when we went to run our app inside a Docker instance and talk to a MySQL instance inside a different Docker instance.
I attributed this problem to a number of different sources, since “StreamCorruptedException: Invalid Header” doesn’t hit on anything date-specific on the first few pages of Google. I gutted the entire object model and removed all the @ManyToMany and @ManyToOne relationships. I removed our convenience methods. I re-configured the build plan and our Play! configuration files. Nothing worked.
At some point, I took the “invalid header” reported in the exception and put it through a hex-to-ascii converter. The header was always the same, and it was always the binary representation of “2015,” which led me back to examining our LocalDate and LocalDateTime behavior, including the converters.
I gutted the converters, and had them return empty strings, nulls, or the current date’s string representation, which I thought would allow us to at least get objects out of the database with garbage dates attached to them. No such luck. I copy-pasted other people’s converters from a few different sources. I even chased our Serializers around, since the StreamCorruptedException eventually manifested as a SerializationException. Nothing worked.
I called in some of the more senior people from our team. They shrugged. I had hoped it would be obvious.
This morning, having slept, I got up to take another crack at it. Now that I know what to look for, the solution is obvious, and a bunch of blog posts and stackoverflow answers are being updated to include it: you can just add a dependency on the hibernate-java8 library, and you’ll be good to go. In SBT, that looks like this:
"org.hibernate" % "hibernate-java8" % "5.0.1.Final",
I spent the better part of three days chasing that around. I’m not totally comfortable with the fact that the converters never worked, but at least we can keep moving forward on this project.