1

I have a springboot application with a rest controller sitting up top. The user access the controller through /test and passes in a json like so:

{"ssn":"123456789"}

I want to validate the input by at least making sure there's not an empty ssn being passed in like so:

{"ssn":""}

So here's my controller:

@RequestMapping(
            value = "/test",
            method = RequestMethod.POST,
            consumes = "application/json",
            produces = "application/json")
@ResponseBody
public JsonNode getStuff(@RequestHeader HttpHeaders header,
                                 @RequestBody String payload,
                                 BindingResult bindingResult) {
    validator.validate(payload, bindingResult);
    if(bindingResult.hasErrors()) {
        throw new InvalidRequestException("The request is incorrect", bindingResult);
    }
    /* doing other stuff */
}

And here's my validator:

@Component
public class RequestValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return false;
    }

    @Override
    public void validate(Object target, Errors errors) {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode ssn = null;
        try {
            ssn = mapper.readTree((String) target);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(ssn.path("ssn").isMissingNode() || ssn.path("ssn").asText().isEmpty()) {
            errors.rejectValue("ssn", "Missing ssn", new Object[]{"'ssn'"}, "Must provide a valid ssn.");
        }
    }
}

I tried testing this with postman and I keep getting this error:

HTTP Status 500 - Invalid property 'ssn' of bean class [java.lang.String]: Bean property 'ssn' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

What exactly is the problem here? I don't understand what it's talking about in relation to getters and setters.

Edit 1: The value of the payload as requested

{"ssn":""}
oberlies
  • 11,503
  • 4
  • 63
  • 110
Richard
  • 5,840
  • 36
  • 123
  • 208
  • any reason "supports" is returning false. – Sanj Mar 24 '16 at 23:11
  • @Sanj oh no, not really. Just no use for it so didn't bother providing any other implementation. – Richard Mar 24 '16 at 23:35
  • can you see what is the value of payload? System.out.println(payload) in the controller. – Sanj Mar 24 '16 at 23:55
  • From the error message, it seems that something tries to deserialize the request body, although the parameter type is `String`. This is surprising – and I was also not able to reproduce it. Do you still have a the full stack trace of the error? Otherwise, I suppose that this question is not useful any more... – oberlies Feb 27 '19 at 09:57

1 Answers1

1

By default Spring Boot configures Json parser, so any Json you pass to the controller will be parsed. Spring is expecting an object with a property called 'ssn' to bind the request value.

This means that you should create a model object like this:

public class Data {
    String ssn;

}

And use it to bind your request body like this:

@RequestMapping(
        value = "/test",
        method = RequestMethod.POST,
        consumes = "application/json",
        produces = "application/json")
@ResponseBody
public JsonNode getStuff(@RequestHeader HttpHeaders header,
                                 @RequestBody Data payload,
                                 BindingResult bindingResult) {
    validator.validate(payload, bindingResult);
    if(bindingResult.hasErrors()) {
        throw new InvalidRequestException("The request is incorrect", bindingResult);
    }
    /* doing other stuff */
}

You also need to adapt your Validator to use this new Data object.

Milan
  • 1,780
  • 1
  • 16
  • 29