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

Using a sealed interface as a property in a request body seem to fail with "missing constructor" #827

Open
Klaboe opened this issue Apr 22, 2024 · 4 comments
Labels
type: enhancement New feature or request

Comments

@Klaboe
Copy link

Klaboe commented Apr 22, 2024

Issue description

I am not sure if this is a bug or if i am doing something stupid; but here goes.

First some dependecies:

//DEPS io.micronaut:micronaut-http-server-netty:4.5.1
//DEPS io.micronaut:micronaut-http-client:4.5.1
//DEPS io.micronaut:micronaut-inject-java:4.5.1
//DEPS io.micronaut.serde:micronaut-serde-jackson:2.10.1

I have created a PATCH endpoint which accepts a List of patch operations as its RequestBody:

@Patch("/entity/{id}")
@Consumes(APPLICATION_JSON_PATCH)
public SomeResponse update(@PathVariable UUID id, @Body List<PatchRequest> patchOperations) {

A PatchRequest is a simple record where one of the properties, entity, is a sealed interface, Patchable, that can be one of two types; PossibleEntityRequest1 or PossibleEntityRequest2:

@Serdeable
public record PatchRequest(
    PatchOperation op,
    Patchable entity
) { }

Patchable looks like this:

@Serdeable
public sealed interface Patchable permits PossibleEntityRequest1, PossibleEntityRequest2 { }

PossibleEntityRequest1 and PossibleEntityRequest2 are the two possible entity-inputs that should be used when patching/updating an entity and is also just records with some data-properties

When calling the endpoint, all i get is

[
  {
     "message":"Failed to convert argument [patchOperations] for value [null] due to: Unable to deserialize type [Patchable entity]: No default constructor exists","path":"/patchOperations"}]},
     "message":"Bad Request"
  }
]

I have tried using

@JsonTypeInfo(
    use=Id.NAME,
    include=As.WRAPPER_OBJECT,
    property = "type")
@JsonSubTypes({
    @Type(PossibleEntityRequest1.class),
    @Type(PossibleEntityRequest2.class)
})

on either the interface it self or on the entity property but i still get the same error.

Thoughs?

EDIT 12.06.2024

@Klaboe Klaboe changed the title Using a sealed interface as en request property seem to fail with "missing constructor" Using a sealed interface as a property in a request body seem to fail with "missing constructor" Apr 22, 2024
@Klaboe
Copy link
Author

Klaboe commented Jun 12, 2024

Retested with with micronaut 4.5.1 and micronaut-serde-jackson:2.10.1 - No change

@graemerocher graemerocher added the type: enhancement New feature or request label Jun 13, 2024
@dstepanov
Copy link
Contributor

Please create an example.

The correct way is to add @JsonTypeInfo to the interface.
This case might be different, looks like you are trying to convert null into a list, is that correct?

@Klaboe
Copy link
Author

Klaboe commented Jun 14, 2024

No i am trying to get entity to be serialized into either PossibleEntityRequest1 or PossibleEntityRequest2, since that is what the sealed interface allows. Not sure how you see this as trying to get null to become a list 😅

I have attached a project that is the bare minumum and that produces the same error:
micronaut-serialization-issue-827.zip
It has the @JsonTypeInfo on the interface

To trigger it, run the server and run simple

curl -X POST -H "Content-Type:application/json" http://localhost:8080/ -d '[ { "operation": { "r1": "R1" } } ]'

This will give the error
"Failed to convert argument [operations] for value [null] due to: Unable to deserialize type [interface sealed.inter.face.issue.SealedInterface]: No default constructor exists","path":"/operations"

It is highly likly that i just dont know how to use @JsonTypeInfo

@Klaboe
Copy link
Author

Klaboe commented Sep 5, 2024

I see that i have used POST instead of PATCH here, but it should noe matter i think.

Does it illuminate the problem? Can you reproduce it?

I have retested with 2.11 (micronaut 4.6.1) and i see no change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement New feature or request
Projects
No open projects
Status: No status
Development

No branches or pull requests

3 participants