Closed karstengresch closed 1 year ago
/cc @DavideD, @FroMage, @Sanne, @Sgitario, @gavinking, @loicmathieu
I think this issue is duplicated with https://github.com/quarkusio/quarkus/issues/10768. This is a very good explanation of the issue by @DavideD https://github.com/quarkusio/quarkus/issues/10768#issuecomment-1023581785 The workaround I used to make your reproducer work is the one described in https://github.com/quarkusio/quarkus/issues/10768#issuecomment-848942893, plus adding the offset as part of the formatted:
@Type(type = "org.bydoing.TimestampWithTimezone")
@Column(name = "exampledate", nullable = false, updatable = false, columnDefinition = "timestamp with time zone not null")
@JsonbDateFormat(value="yyyy-MM-dd'T'HH:mm:ss.SSSXXX") // see new formatter
public OffsetDateTime exampledate;
Alternatively, you can instruct JsonB to default offset to zero as said in the exception:
Caused by: javax.json.bind.JsonbException: Error parsing class java.time.OffsetDateTime from value: 2022-03-10T12:15:50-04:00. Check your @JsonbDateFormat has all time units for class java.time.OffsetDateTime type, or consider using org.eclipse.yasson.YassonConfig#ZERO_TIME_PARSE_DEFAULTING.
at org.eclipse.yasson.internal.serializer.AbstractDateTimeDeserializer.parseWithFormatterInternal(AbstractDateTimeDeserializer.java:135)
at org.eclipse.yasson.internal.serializer.AbstractDateTimeDeserializer.deserialize(AbstractDateTimeDeserializer.java:59)
at org.eclipse.yasson.internal.serializer.AbstractValueTypeDeserializer.deserialize(AbstractValueTypeDeserializer.java:64)
at org.eclipse.yasson.internal.serializer.ObjectDeserializer.deserializeNext(ObjectDeserializer.java:183)
at org.eclipse.yasson.internal.serializer.AbstractContainerDeserializer.deserializeInternal(AbstractContainerDeserializer.java:94)
... 24 more
See how to configure JSON B here: https://quarkus.io/guides/rest-json#json-b
I think the problem is that the pattern and the date you've specified don't contain an offset. If you remove the annotation @JsonDateFormat
and add Z
at the end of the date, it should be able to parse the date correctly:
curl -X 'POST' \
'http://localhost:8080/example' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": 0,
"exampledate": "2022-03-10T12:15:50Z"
}'
But you will face another issue. Currently there is a problem about using timestamp with time zone with Postgres and Hibernate Reactive.
This happens because postgres doesn't actually save the time zone and convert everything to UTC:
For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's TimeZone parameter, and is converted to UTC using the offset for the timezone zone.
At the moment, if you want to handle timezones with Hibernate Reactive and Postgres, you might need to store the offset in a separate field.
I also don't think it's a good idea to drop-and-create tables in several different places.
In the properties, you already specify the property quarkus.hibernate-orm.database.generation=drop-and-create
.
So, you don't have to recreate the table in the import.sql or in the test.
I've created a git patch containing the changes I've applied to make the example work: https://gist.github.com/DavideD/9e383b1177c6ddb0624812af43ac557b
This will map the column exampledate as timestamp
(and not timestampz
)
Thanks @Sgitario for the explanation and even more @DavideD for the even deeper explanation and the patch!
That was extremely fast, much appreciated. I'll test this out (b.t.w. I had already tested all sorts of format Strings as well as all sorts of HTTP-body-param values) and give you some feedback on this!
@DavideD - thanks very much, I can confirm it's working with your example.
For the later interested reader: working solution in branch https://github.com/karstengresch/jsonbdatereproducer/tree/solution
Notes to that:
2022-01-10T12:15:50-04:00
Hope this is useful for somebody stumbling upon this.
I'm closing this issue, but if you have other questions don't hesitate to ask.
By the way, in case you don't know, if you add the prefix %prod
to some properties in the application.properties
,
Quarkus will automatically starts a docker container with the correct database to run the tests.
These are the changes I've done so that mvn quarkus:dev
would also start the db:
quarkus.datasource.db-kind=postgresql
%prod.quarkus.datasource.username=exampledb
%prod.quarkus.datasource.password=exampledb
# podman run -it --rm=true --name exampledb -e POSTGRES_USER=exampledb -e POSTGRES_PASSWORD=exampledb -e POSTGRES_DB=exampledb -p 5432:5432 postgres:14.5
%prod.quarkus.datasource.reactive.url=vertx-reactive:postgresql://localhost:5432/exampledb
quarkus.datasource.reactive.max-size=20
exampledb.schema.create=true
quarkus.hibernate-orm.database.generation=drop-and-create
Thanks very much again, @DavideD !
I incorporated this into the working solution, but commented it out:
Working on macOS and using Podman. This doesn't seem to be supported, https://quarkus.io/blog/quarkus-devservices-testcontainers-podman/
Following the instructions from https://quarkus.io/guides/podman incl. alias docker='podman'
didn't work. I think I somewhere read there was some quarkus property where podman could be specified but this was IIRC just for image creation, not dev services/tescontainers.
I for sure know my next RH notebook will be Linux based (as most of my home machines are) :D
Describe the bug
I want to implement basic CRUD for LocalDateTime/OffsetDateTime members, but fail with create/insert/POST.
A reproducer project has been created here: https://github.com/karstengresch/jsonbdatereproducer.git
Expected behavior
The POST method should be executed, a new record should have been inserted into the DB and the method should HTTP 200.
Actual behavior
Exceptions when calling the POST endpoint:
LocalDateTime
OffsetDateTime
How to Reproduce?
Created a project via https://code.quarkus.io/
Followed the guides at https://quarkus.io/guides/hibernate-reactive-panache and https://quarkus.io/guides/reactive-sql-clients (but using the Panache approach, not the reactive clients, i.e. no named query for inserts).
Not following the CRUD resource approach (https://quarkus.io/guides/rest-data-panache) due to missing pgsql support.
Final pom.xml (NB Lombok added, see full file in repo!):
DB manually started (as dev services DB instantiation didn't work) w/
podman run -it --rm=true --name exampledb -e POSTGRES_USER=exampledb -e POSTGRES_PASSWORD=exampledb -e POSTGRES_DB=exampledb -p 5432:5432 postgres:14.5
to get
(omitting the "id" parameter is optional)
and the error is
Output of
uname -a
orver
Darwin KGRHMBP01 21.5.0 Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:22 PDT 2022; root:xnu-8020.121.3~4/RELEASE_X86_64 x86_64
Output of
java -version
openjdk 17.0.4.1 2022-08-12 OpenJDK Runtime Environment Temurin-17.0.4.1+1 (build 17.0.4.1+1) OpenJDK 64-Bit Server VM Temurin-17.0.4.1+1 (build 17.0.4.1+1, mixed mode, sharing)
GraalVM version (if different from Java)
N/A, no native compile, only JVM mode
Quarkus version or git rev
2.13.2.Final
Build tool (ie. output of
mvnw --version
orgradlew --version
)Maven home: ~/.m2/wrapper/dists/apache-maven-3.8.1-bin/2l5mhf2pq2clrde7f7qp1rdt5m/apache-maven-3.8.1 Java version: 17.0.4.1, vendor: Eclipse Adoptium, runtime: ~/.sdkman/candidates/java/17.0.4.1-tem Default locale: en_US, platform encoding: UTF-8 OS name: "mac os x", version: "12.4", arch: "x86_64", family: "mac"
Additional information
Used io.quarkus/999-SNAPSHOT
Maybe I just missed (i.e. misunderstood) something elementary (e.g. wrong formatter String or else) and this is not a bug, then please see this contribution to