I work on a SpringBoot application.
I have the following class hierarchy:
public abstract class DlqMessage {
Long id;
UUID employeeId;
EventReason reason;
}
public class ContractUpdateMessage extends DlqMessage {}
public class SingleContractUpdateMessage extends DlqMessage {
UUID benefitId;
UUID employerId;
}
So, the classes ContractUpdateMessage
and SingleContractUpdateMessage
only differ by a couple of fields.
I Have a REST controller that uses POST to create and save a new entity in the DB:
@PostMapping("/messages")
public ResponseEntity<DlqMessage> create(@RequestBody DlqMessage contractUpdateMessage) {
DlqMesssage dlqEntry = dlqEntityService.save(contractUpdateMessage);
return ResponseEntity.ok(dlqEntry);
}
Now, I have a test that randomly generates on instance of the one or the other class:
DlqMessage message = randomOneOf(contractUpdateMessageBuilder().build(), singleContractUpdateMessageBuilder().build());
Then I have a test helper class that uses RestTemplate to send a POST request to the controller:
ResponseEntity<DlqMesssage> response =
crudRestClient.post("/messages/contract", message, DlqMesssage.class, null);
return response.getBody();
And invoking the whole things I end up with the following exception:
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not construct instance of com.orbitbenefits.benefitsselection.server.errorrecovery.entity.DlqMessage: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.orbitbenefits.benefitsselection.server.errorrecovery.entity.DlqMessage: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
And it looks like my request isn't even being sent by the RestTemplate.
BTW, it all works when I split endpoints for each individual subtype:
@PostMapping("/messages/contract")
public ResponseEntity<DlqMessage> create(@RequestBody ContractUpdateMessage contractUpdateMessage) {
ContractUpdateMessage dlqEntry = (ContractUpdateMessage) dlqEntityService.save(contractUpdateMessage);
return ResponseEntity.ok(dlqEntry);
}
@PostMapping("/messages/single")
public ResponseEntity<DlqMessage> create(@RequestBody SingleContractUpdateMessage contractUpdateMessage) {
SingleContractUpdateMessage dlqEntry = (SingleContractUpdateMessage) dlqEntityService.save(contractUpdateMessage);
return ResponseEntity.ok(dlqEntry);
}
However that looks ugly and is not a "correct" solution.
Basically, I would like to know if it's possible and how to implement a REST end point that takes polymorphic instance as a parameter and how to invoke such an end point?