Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jackson desrialization to Record fails in native builds #25984

Closed
deej-io opened this issue Jun 7, 2022 · 10 comments
Closed

Jackson desrialization to Record fails in native builds #25984

deej-io opened this issue Jun 7, 2022 · 10 comments
Labels
area/jackson Issues related to Jackson (JSON library) area/mandrel env/graalvm-java17 Relating to using GraalVM native generation Java 11 kind/bug Something isn't working triage/invalid This doesn't seem right

Comments

@deej-io
Copy link

deej-io commented Jun 7, 2022

Describe the bug

We are currently trying to use Java records as POJOs and using Jackson for (de)-serialisation, however, we are hitting the following runtime error:

❯ ./target/jacksonrecords-0.0.1-SNAPSHOT-runner 
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2022-06-07 10:52:33,816 INFO  [io.quarkus] (main) jacksonrecords 0.0.1-SNAPSHOT native (powered by Quarkus 2.9.2.Final) started in 0.004s. 
2022-06-07 10:52:33,818 INFO  [io.quarkus] (main) Profile prod activated. 
2022-06-07 10:52:33,818 INFO  [io.quarkus] (main) Installed features: [cdi]
2022-06-07 10:52:33,818 ERROR [io.qua.run.Application] (main) Failed to start application (with profile prod): com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Failed to access RecordComponents of type `io.acme.jacksonrecords.SomeRecord`
 at [Source: (String)"{
  "name": "John",
  "surname": "Smith"
}
"; line: 1, column: 1]
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1904)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:268)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:642)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4805)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4675)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3597)
	at io.acme.jacksonrecords.Main.run(Main.java:20)
	at io.acme.jacksonrecords.Main_ClientProxy.run(Unknown Source)
	at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:124)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:67)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:41)
	at io.quarkus.runner.GeneratedMain.main(Unknown Source)

2022-06-07 10:52:33,819 INFO  [io.quarkus] (main) jacksonrecords stopped in 0.000s

I have create repository that replicates this issue here: https://github.com/djrollins/quarkus-native-jackson-records.

Expected behavior

Jackson should successfully de-serialize to Java records in native builds.

Actual behavior

Compiled program emits a runtime error when attempting to de-serialize to a Java record.

How to Reproduce?

1, Clone this example repository: https://github.com/djrollins/quarkus-native-jackson-records
2. Create a native build with mvn package -Pnative
3. Execute the compiled program with ./target/jacksonrecords-0.0.1-SNAPSHOT-runner
4. Observe the com.fasterxml.jackson.databind.exc.InvalidDefinitionException error.

Output of uname -a or ver

Linux archlinux 5.17.9-arch1-1 #1 SMP PREEMPT Wed, 18 May 2022 17:30:11 +0000 x86_64 GNU/Linux

Output of java -version

openjdk version "17.0.3" 2022-04-19 OpenJDK Runtime Environment (build 17.0.3+7) OpenJDK 64-Bit Server VM (build 17.0.3+7, mixed mode)

GraalVM version (if different from Java)

Using latest docker image for quay.io/quarkus/ubi-quarkus-mandrel:22.0-java17

Quarkus version or git rev

2.9.2.Final

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

Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537) Maven home: /opt/maven Java version: 17.0.3, vendor: N/A, runtime: /usr/lib/jvm/java-17-openjdk Default locale: en_GB, platform encoding: UTF-8 OS name: "linux", version: "5.17.9-arch1-1", arch: "amd64", family: "unix"

Additional information

No response

@deej-io deej-io added the kind/bug Something isn't working label Jun 7, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Jun 7, 2022

/cc @Karm, @galderz, @geoand, @gsmet, @zakkak

@quarkus-bot quarkus-bot bot added area/jackson Issues related to Jackson (JSON library) area/mandrel labels Jun 7, 2022
@zakkak
Copy link
Contributor

zakkak commented Jun 8, 2022

Hi @djrollins this looks like oracle/graal#3984.

Can you please check if the issue is still reproducible with Mandrel 22.1 or 21.3.2?
i.e. using quay.io/quarkus/ubi-quarkus-mandrel:22.1-java17 or quay.io/quarkus/ubi-quarkus-mandrel:21.3-java17?

@SpeedsterF2
Copy link

SpeedsterF2 commented Jun 9, 2022

Still persist as far as I can see on my own project:

mvn clean package -Pnative
-DskipTests=true
-Dquarkus.native.reuse-existing=false
-Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-mandrel:22.1-java17
-Dquarkus.container-image.build=true
-Dquarkus.container-image.push=true
-Dquarkus.container-image.group=...

results in
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Failed to access RecordComponents of type de.lisaplus.lisa.subsystem.model.geo.GeoJsonResponse

@SpeedsterF2
Copy link

SpeedsterF2 commented Jun 9, 2022

Still present with Mandrel 22.1:
https://github.com/SpeedsterF2/quarkus-native-jackson-records (master)
Still present with Mandrel 21.3.2:
https://github.com/SpeedsterF2/quarkus-native-jackson-records/tree/mandrel-21.3.2 (mandrel-21.3.2)

@deej-io
Copy link
Author

deej-io commented Jun 12, 2022

Thank you both for responding to this issue. I can confirm that @SpeedsterF2 is right and this issue is still present in Mandrel 22.1.

[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Running Quarkus native-image plugin on native-image 22.1.0.0-Final Mandrel Distribution (Java Version 17.0.3+7)
...

❯ ./target/jacksonrecords-0.0.1-SNAPSHOT-runner
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2022-06-12 10:55:53,875 INFO  [io.quarkus] (main) jacksonrecords 0.0.1-SNAPSHOT native (powered by Quarkus 2.9.2.Final) started in 0.007s.
2022-06-12 10:55:53,880 INFO  [io.quarkus] (main) Profile prod activated.
2022-06-12 10:55:53,881 INFO  [io.quarkus] (main) Installed features: [cdi]
2022-06-12 10:55:53,881 ERROR [io.qua.run.Application] (main) Failed to start application (with profile prod): com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Failed to access RecordComponents of type `io.acme.jacksonrecords.SomeRecord`
 at [Source: (String)"{
  "name": "John",
  "surname": "Smith"
}
"; line: 1, column: 1]
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1904)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:268)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:642)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4805)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4675)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3597)
	at io.acme.jacksonrecords.Main.run(Main.java:20)
	at io.acme.jacksonrecords.Main_ClientProxy.run(Unknown Source)
	at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:124)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:67)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:41)
	at io.quarkus.runner.GeneratedMain.main(Unknown Source)

2022-06-12 10:55:53,881 INFO  [io.quarkus] (main) jacksonrecords stopped in 0.000s

@SpeedsterF2
Copy link

SpeedsterF2 commented Jun 22, 2022

quarkus v2.10.0 with default quay.io/quarkus/ubi-quarkus-mandrel:22.0-java17 fails:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Failed to access RecordComponents of type io.acme.jacksonrecords.SomeRecord
at [Source: (String)"{
"name": "John",
"surname": "Smith"
}
"; line: 1, column: 1]
...

quarkus v2.10.0 with quay.io/quarkus/ubi-quarkus-mandrel:22.1-java17 fails with the same stack trace:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Failed to access RecordComponents of type io.acme.jacksonrecords.SomeRecord
at [Source: (String)"{
"name": "John",
"surname": "Smith"
}
"; line: 1, column: 1]
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1904)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:268)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:642)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4805)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4675)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3597)
at io.acme.jacksonrecords.Main.run(Main.java:20)
at io.acme.jacksonrecords.Main_ClientProxy.run(Unknown Source)
at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:124)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:67)
at io.quarkus.runtime.Quarkus.run(Quarkus.java:41)
at io.quarkus.runner.GeneratedMain.main(Unknown Source)

@vaclavsvejcar
Copy link
Contributor

vaclavsvejcar commented Jun 22, 2022

I'm having the same issue with GraalVM 22.1.0 (OpenJDK 17.0.3) and Quarkus 2.9.2.Final. I guess there's no workaround for this at this moment, right?

@zakkak zakkak added the env/graalvm-java17 Relating to using GraalVM native generation Java 11 label Jun 29, 2022
@zakkak
Copy link
Contributor

zakkak commented Jun 29, 2022

Since SomeRecord needs to be accessed reflectively in order for serialization/deserialization to work you need to apply the following patch in order to make it work.

diff --git a/src/main/java/io/acme/jacksonrecords/SomeRecord.java b/src/main/java/io/acme/jacksonrecords/SomeRecord.java
index fefaac3..18a9de3 100644
--- a/src/main/java/io/acme/jacksonrecords/SomeRecord.java
+++ b/src/main/java/io/acme/jacksonrecords/SomeRecord.java
@@ -1,4 +1,7 @@
 package io.acme.jacksonrecords;
 
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+@RegisterForReflection
 record SomeRecord(String name, String surname) {
 }

(Tested with Mandrel 22.1 and Quarkus 2.10.1.Final)

@vaclavsvejcar
Copy link
Contributor

Since SomeRecord needs to be accessed reflectively in order for serialization/deserialization to work you need to apply the following patch in order to make it work.

diff --git a/src/main/java/io/acme/jacksonrecords/SomeRecord.java b/src/main/java/io/acme/jacksonrecords/SomeRecord.java
index fefaac3..18a9de3 100644
--- a/src/main/java/io/acme/jacksonrecords/SomeRecord.java
+++ b/src/main/java/io/acme/jacksonrecords/SomeRecord.java
@@ -1,4 +1,7 @@
 package io.acme.jacksonrecords;
 
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+@RegisterForReflection
 record SomeRecord(String name, String surname) {
 }

(Tested with Mandrel 22.1 and Quarkus 2.10.1.Final)

That did the trick, I must have overlooked this in the documentation. Thank you!

@geoand
Copy link
Contributor

geoand commented Jun 30, 2022

Closing this as in this case explicit registration is required

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/jackson Issues related to Jackson (JSON library) area/mandrel env/graalvm-java17 Relating to using GraalVM native generation Java 11 kind/bug Something isn't working triage/invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

5 participants