3

I'm just experimenting with these new Java Records and I'm wondering if I could use them as DTOs for my request / response types in a spring boot application.

Therefore I just modified some code (class with a lot of boilerplate getter/setter to records), compiled and started my application. Trying some rest endpoints and all I got was an exception telling me:

No serializer found for class x.y.CreateNewShopListeCommand$Item and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS

Well, ok, records do not create 'get'prefixed getter methods. Now I wonder: is it possible to use records as request / response types for spring boot controller?

EDIT: Sample Application (https://github.com/kaipaysen/playground-jdk14-records-as-dto)

// HelloController.java
@RestController
@RequestMapping("/hello")
public class HelloController {
    
    public record HelloRequest(
        @JsonProperty("name") String name
    ) {}

    public record HelloResponse(
        @JsonProperty("message") String message
    ) {}

    @RequestMapping(method = RequestMethod.POST)
    public HelloResponse hello(@RequestBody @Valid HelloRequest query) {
        return new HelloResponse("Hello " + query.name());
    }
    
}

Calling curl -X POST -H "Content-Type: application/json" -d '{"name":"Max"}' http://localhost:8080/hello returns {"message":"Hello null"}. Debugging hello reveals that the Request is not properly deserialized. Any ideas on that spot?

EDIT#2: Just found this issue Support for JDK 14 record types #2709 in the FasterXML repo. They are working on it for jackson 2.12.

Kai
  • 871
  • 2
  • 18
  • 39
  • 2
    As [this article](https://dzone.com/articles/jdk-14-records-for-spring-devs) suggests, see if adding `@JsonProperty` could help. – Naman Sep 02 '20 at 19:53
  • Well, it did the trick for serializing but not for deserializing. I added a minimal sample above. – Kai Sep 03 '20 at 07:01

1 Answers1

1

You need to add this class level annotation to yours records.

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

In the jackson version 1.12 it should be available without annotation.

I think this's a bug in Jackson, You need to add a second field to your record because it doesn't work for the record which has only one field.

Artem
  • 358
  • 3
  • 15
  • I tried adding the annotation like this: `@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public record HelloRequest( @JsonProperty("name") String name ) {}` but it doesn't work. – Kai Sep 13 '20 at 09:23
  • try to remove @JsonProperty("name") – Artem Sep 14 '20 at 08:35
  • Still the same. Would you mind sharing a working example? – Kai Sep 15 '20 at 07:49
  • I think this's a bug in Jackson, You need to add a second field to your record. It doesn't work for record which has only one field. – Artem Sep 15 '20 at 10:48
  • Artem, you're right. Adding a second field to my HelloRequest enables deserialisation (even without annotations). The annotation in the HelloResponse is still required otherwise we'll get a "No converter found" error. – Kai Sep 16 '20 at 12:59
  • @Artem do you have a link to the Jackson bug? – nick318 May 14 '21 at 22:30