5

I have a Spring RestController that any attempt to post to it returns 400 Bad Request despite seeing the correct data being sent in Chrome Developer Tools. The @Valid annotation is kicking it out because the ParameterDTO object is not being populated at all.

My Controller

@RestController
@RequestMapping(path = "/api/parameters", consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
public class ParameterResource {

    private final ParameterService parameterService;

    @Autowired
    public ParameterResource(ParameterService parameterService) {
        this.parameterService = parameterService;
    }

    @GetMapping
    public ResponseEntity<?> getParameters(@RequestParam(value = "subGroupId", required = false) Integer subGroupId) {
        if (subGroupId != null) {
            return ResponseEntity.ok(parameterService.getParameters(subGroupId));
        }
        return ResponseEntity.ok(parameterService.getParameters());
    }

    @PostMapping
    public ResponseEntity<?> createParameter(@Valid ParameterDTO parameterData) {
        int id = parameterService.saveParameter(parameterData);
        URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                .buildAndExpand(id).toUri();
        return ResponseEntity.created(uri).build();
    }

    @GetMapping(path = "/levels")
    public ResponseEntity<?> getParameterLevels() {
        return ResponseEntity.ok(ParameterLevels.getParameterLevelMap());
    }

    @GetMapping(path = "/levels/{id}/values")
    public ResponseEntity<?> getLevelValues(@PathVariable("id") int levelId) {
        return ResponseEntity.ok(parameterService.getParameterLevelValues(levelId));
    }

    @GetMapping(path = "/types")
    public ResponseEntity<?> getParameterTypes() {
        return ResponseEntity.ok(parameterService.getParameterTypes());
    }
}

I was using axios from JavaScript and though my problem might be there but I have the same issue using Postman. I am setting the Content-Type and Accept header. It seems like Spring is not deserializing the data at all.

enter image description here

enter image description here

greyfox
  • 6,426
  • 23
  • 68
  • 114
  • I think you are missing `@RequestBody` before `ParameterDTO parameterData` declaration – bart.s Feb 23 '17 at 20:02
  • That is not required the controller is declared as a @RestController, RequestBody was needed prior to that being added in Spring 4 – greyfox Feb 23 '17 at 20:07
  • 1
    yes, it is required. What `@RestController` gives you is `@ResponseBody` bounding, not `@RequestBody` – bart.s Feb 23 '17 at 20:10
  • Ahhhh you are right, bone head mistake....... this is what happens when you switch between .NET and Spring. Thanks! If you make it an answer I will accept it – greyfox Feb 23 '17 at 20:14

1 Answers1

8

You need to add @RequestBody annotation before ParameterDTO parameterData declaration, like below:

    @PostMapping
    public ResponseEntity<?> createParameter(@RequestBody @Valid ParameterDTO parameterData) {
        int id = parameterService.saveParameter(parameterData);
        URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                .buildAndExpand(id).toUri();
        return ResponseEntity.created(uri).build();
    }
bart.s
  • 688
  • 5
  • 12