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

Deserialization exception in native image with DTO with @ConstructorProperties #32288

Closed
dpozinen opened this issue Feb 17, 2024 · 1 comment
Closed
Assignees
Labels
for: external-project Needs a fix in external project theme: aot An issue related to Ahead-of-time processing

Comments

@dpozinen
Copy link

dpozinen commented Feb 17, 2024

Problem

With the below setup:

    public static class PlayResponseValue {
        private final String result;

        @ConstructorProperties("result")
        public PlayResponseValue(String result) {
            this.result = result;
        }

        public String getResult() {
            return this.result;
        }
    }

I'm getting the following exception:

Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class com.playtika.services.samples.PlayClient$PlayResponseValue] and content type [application/json]
        at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:118)
        at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:75)
        at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:61)
        at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:36)
        at feign.InvocationContext.proceed(InvocationContext.java:36)
        ... 37 common frames omitted
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.playtika.services.samples.PlayClient$PlayResponseValue` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
        at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:406)
        at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:354)
        at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:103)
        ... 41 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.playtika.services.samples.PlayClient$PlayResponseValue` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 2]
        at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1739)

When trying to deserialize the object, but everything works perfectly when using a java application (non native).

Initially discovered when using a feign client, but it is reproducible by just using rest template.

Investigation results

At first I thought this was a hint issue, but I checked and they were indeed automatically generated.

{
    "name": "com.playtika.services.samples.PlayClient$PlayResponseValue",
    "allDeclaredConstructors": true,
    "allDeclaredFields": true,
    "methods": [ { "name": "getResult", "parameterTypes": [ ] } ]
  }

I tried adding the constructor as a method hint manually, but that didn't help.

@OlgaMaciaszek was able to reproduce this on this branch. See instructions how to build and how to run

Personally I believe the issue might be with AbstractJackson2HttpMessageConverter, please have a look.

Workarounds

Everything works in either case:

  • if the DTO is re-implemented to be a java record.
  • when @JsonCreator is added to the constructor

These workarounds are generally acceptable, although would require a lot of effort to implement across multiple services.

Since the constructor is present, the hint for it as well, I believe that native should be able to detect everything just as java would.

Environment

  • Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 17.0.9+11.1 (build 17.0.9+11-LTS-jvmci-23.0-b21, mixed mode, sharing)
  • Spring Boot 3.1.6
  • OpenFeign 4.0.4

Related Issues

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 17, 2024
@sdeleuze sdeleuze self-assigned this Feb 19, 2024
@sdeleuze sdeleuze added the theme: aot An issue related to Ahead-of-time processing label Feb 19, 2024
@sdeleuze
Copy link
Contributor

This is caused by a missing declared constructors reflection entry for com.fasterxml.jackson.databind.ext.Java7SupportImpl, see related Java7Support.java source code.

This needs to be handled on https://github.com/oracle/graalvm-reachability-metadata side, I will create related PR.

@sdeleuze sdeleuze closed this as not planned Won't fix, can't repro, duplicate, stale Feb 19, 2024
@sdeleuze sdeleuze added for: external-project Needs a fix in external project and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Feb 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project Needs a fix in external project theme: aot An issue related to Ahead-of-time processing
Projects
None yet
Development

No branches or pull requests

3 participants