Issue
I am trying to save an object Rating which has another Mobile, so it includes a grade and a phone.
Here is mobile entity:
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Mobile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
}
Here is rating entity
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Rating {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Mobile mobile;
private int grade;
}
Method saveRating from RatingService class
public Rating saveRating(Rating rating) {
Rating theRating = new Rating();
Mobile theMobile = mobileRepo.getById(rating.getMobile().getId());
theRating.setGrade(rating.getGrade());
theRating.setMobile(theMobile);
return ratingRepo.save(theRating);
}
And method for saving in rest controller
@Autowired
private RatingService ratingService;
@RequestMapping(value = "/rating", method = RequestMethod.POST)
public Rating newRating(@RequestBody Rating rating){
return ratingService.saveRating(rating);
}
I have all @Service @RestController @Autowired annotations. Other stuff works as saving mobile, deleting it and viewing it, even viewing ratings which I manually added in database. I have tried variating newRating method in controller and in RatingService with it getting only the mobile id and grade and then finding mobile through mobileRepository and saving it as mobile for rating but I had not made progress with it, so I've returned to this method from witch I have started. It seems very simple to do this, but at the moment is not. Here is postman result: This is from postman
Solution
Currently, you are trying to map the values "mobile"=1, "rating"=4 to an instance with the fields "id", "mobile" (not an integer) and "grade", hence you receive the response of Bad Request
because the supplied JSON does not match the specified (@RequestBody) Java type.
Instead of using Entities as DataTransferObjects you could introduce the following dto
@Data
public class RatingDto {
private int mobileId;
private int grade;
}
Your request should then also contain the id for the mobile in a field with the name mobileId
to match the dto.
Your controller endpoint would look like that:
private Rating tryMap(RatingDto dto) {
var mobileId = dto.getMobileId();
var mobile = mobileRepo.findById(mobileId)
.orElseThrow(() ->
new IllegalArgumentException("Mobile with id " + mobileId + "could not be found.");
var rating = new Rating();
rating.setGrade(dto.getGrade);
rating.setMobile(mobile);
return rating;
}
@PostMapping(value = "/rating")
public Rating newRating(@RequestBody RatingDto dto) {
var rating = tryMap(dto);
return ratingService.saveRating(rating);
}
Answered By - Valerij Dobler
Answer Checked By - Robin (JavaFixing Admin)