【发布时间】:2019-08-23 12:57:00
【问题描述】:
我正在开发一个 SpringBoot 应用程序。
我有以下类层次结构:
public abstract class DlqMessage {
Long id;
UUID employeeId;
EventReason reason;
}
public class ContractUpdateMessage extends DlqMessage {}
public class SingleContractUpdateMessage extends DlqMessage {
UUID benefitId;
UUID employerId;
}
因此,ContractUpdateMessage 和 SingleContractUpdateMessage 类只有几个字段不同。
我有一个 REST 控制器,它使用 POST 在数据库中创建和保存新实体:
@PostMapping("/messages")
public ResponseEntity<DlqMessage> create(@RequestBody DlqMessage contractUpdateMessage) {
DlqMesssage dlqEntry = dlqEntityService.save(contractUpdateMessage);
return ResponseEntity.ok(dlqEntry);
}
现在,我有一个在一个或另一个类的实例上随机生成的测试:
DlqMessage message = randomOneOf(contractUpdateMessageBuilder().build(), singleContractUpdateMessageBuilder().build());
然后我有一个测试助手类,它使用 RestTemplate 向控制器发送 POST 请求:
ResponseEntity<DlqMesssage> response =
crudRestClient.post("/messages/contract", message, DlqMesssage.class, null);
return response.getBody();
并调用整个事情,我最终得到以下例外:
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
看起来我的请求甚至没有被 RestTemplate 发送。
顺便说一句,当我为每个单独的子类型拆分端点时,这一切都有效:
@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);
}
然而,这看起来很难看,并不是一个“正确”的解决方案。
基本上,我想知道它是否可能以及如何实现以多态实例作为参数的REST端点以及如何调用这样的端点?
【问题讨论】: