I'm trying to make use of polymorphism with Java. I build a simple CRUD app with Spring Boot and i wanted to test it with Postman...
Problem is, i got next exception:
WARN 4576 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Could not resolve subtype of [simple type, class com.shoppingprojectwithhibernate.PromotionsModule.Domain.PromotionSeason]: missing type id property 'promotionSeason' (for POJO property 'promotionSeason'); nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.balabasciuc.shoppingprojectwithhibernate.PromotionsModule.Domain.PromotionSeason]: missing type id property 'promotionSeason' (for POJO property 'promotionSeason')<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 3, column: 25] (through reference chain: com.shoppingprojectwithhibernate.PromotionsModule.Domain.Promotion["promotionSeason"])]
when i'm trying to make a POST request to an endpoint, that endpoint return an interface, and in runtime can be any subtype, i scrolled here for solutions, i used jackson used from others solutions, but none worked so far for me, can you give me a hint, please?
my interface:
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "promotionSeason")
@JsonSubTypes(
{
@JsonSubTypes.Type(value = PromotionChristmasSeason.class, name = "christmasPromotion"),
@JsonSubTypes.Type(value = PromotionEasterSeason.class, name = "easterPromotion"),
@JsonSubTypes.Type(value = NoPromotionForYouThisTimeMUHAHA.class, name = "noPromotion")
})
public interface PromotionSeason {
String isSeason();
Interface subtype:
@JsonTypeName(value = "noPromotion")
public class NoPromotionForYouThisTimeMUHAHA implements PromotionSeason {
Promotion class Entity constructor:
public Promotion(int numberOfProductsAtPromotion, PromotionSeason promotionSeason) {
this.numberOfProductsAtPromotion = numberOfProductsAtPromotion;
this.promotionSeason = promotionSeason;
}
Rest Controller class
@RestController
@RequestMapping(value = "/promotions")
public class PromotionController {
@PostMapping(value = "/createPromotion")
public ResponseEntity<String> createPromotion(@RequestBody Promotion promotion)
{
promotionService.createPromotion(promotion);
return ResponseEntity.status(HttpStatus.CREATED)
.body("Done");
}
Postman request:
{
"numberOfProductsAtPromotion" : 20,
"promotionSeason" : "noPromotion"
}
Postman response:
{
"timestamp": "2022-05-04T18:58:06.873 00:00",
"status": 400,
"error": "Bad Request",
"path": "/promotions/createPromotion"
}
Spring Response:
2022-05-04 21:19:44.374 WARN 4576 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Could not resolve subtype of [simple type, class com.shoppingprojectwithhibernate.PromotionsModule.Domain.PromotionSeason]: missing type id property 'promotionSeason' (for POJO property 'promotionSeason'); nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.balabasciuc.shoppingprojectwithhibernate.PromotionsModule.Domain.PromotionSeason]: missing type id property 'promotionSeason' (for POJO property 'promotionSeason')<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 3, column: 25] (through reference chain: com.shoppingprojectwithhibernate.PromotionsModule.Domain.Promotion["promotionSeason"])]
CodePudding user response:
Do you have any contructor in NoPromotionForYouThisTimeMUHAHA? if you have 'Type' in all implementations, you can change interfaceto abstract class and add variable here.
CodePudding user response:
It was my bad Post request all along, instead of:
Postman request:
{
"numberOfProductsAtPromotion" : 20,
"promotionSeason" : "noPromotion" }
it should be:
{
"numberOfProductsAtPromotion" : 20,
"promotionSeason" : { // "promotionSeason" is class instance var from Promotion Entity class
"promotionSeason" : "noPromotion" // "promotionSeason" is defined on interface level: `@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "promotionSeason")`
//"noPromotion" is defined on interface and subtype levels
//any more subtype(subclass) variables to init if any
}
check this: https://www.youtube.com/watch?v=IlLC3Yetil0