3

I have a DTO object like this:

data class ClientDto(
        var uuid: String,
        var ip: String,
        var lastSeen: Date? = Date()
) {
    internal fun toEntity() = Client(uuid=uuid, ip=ip, lastSeen=Date())
}

... and a controller like this:

@RestController
internal class ClientController {

    @Autowired
    private lateinit var service : ClientService

    @GetMapping("/clients")
    internal fun getClients() =  service.findAll()

    @PostMapping("/clients")
    internal fun postClient(@RequestBody client: ClientDto) = service.add(client)
}

Now I post with httpie something like this:

http POST localhost:8080/clients uuid=my-uuid ip=192.123.31:8080

And get:

{
    "error": "Bad Request",
    "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
    "message": "JSON parse error: Can not construct instance of awesome.discovery.domain.dto.ClientDto: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of awesome.discovery.domain.dto.ClientDto: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream@71c6ae97; line: 1, column: 2]",
    "path": "/clients",
    "status": 400,
    "timestamp": 1519587678605
}
  1. What is wrong with this post?
  2. More importantly how can I debug this, e.g. know what it tries and how to get to understand where it goes wrong?
shredding
  • 4,376
  • 3
  • 36
  • 66

1 Answers1

5

1- Your DTO needs to provide a default constructor (empty constructor with no arguments). It's what the error says

2- Spring configures Jackson to use reflection for automatic deserialization of JSON according to the type of the RequestParam. You can customize this behaviour implementing JsonDeserializer. If you want to debug you can put a breakpoint on the method annotated with PostMapping

SrThompson
  • 4,388
  • 2
  • 12
  • 23
  • 1
    I did understand that kotlins Default constructor is set like I did in data classes. – shredding Feb 26 '18 at 06:57
  • 1
    Ah, you are right. Here is an answer regarding visisibillity of the default constructor in Java: https://stackoverflow.com/a/47530515/333566 – shredding Feb 26 '18 at 06:59
  • That's right, I don't use kotlin but I've had this similar issue with project lombok's `Data` and `Value` annotations – SrThompson Feb 26 '18 at 13:17