Rakesh nair
Rakesh nair

Reputation: 11

@Valid @RequestBody failed to validate incoming Json with wrong input

I want to validate incoming RequestBody.My controller API is,

@RequestMapping(value = {
        POSRequest.REQUEST_SEPARATOR + Request.UPDATE_URL,
        method = RequestMethod.PUT,
        produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Update .”,
        response = SuccessResponseDTO.class, ,
        produces = "application/json", httpMethod = "PUT")
@ApiResponses(value = {
        @ApiResponse(code = 200, message = "OK",response = SuccessResponseDTO.class),
        @ApiResponse(code = 401, message = "Unauthorized",response =ErrorResponseDTO.class),
        @ApiResponse(code = 403, message = "Forbidden",response = ErrorResponseDTO.class),
        @ApiResponse(code = 404, message = "Not Found",response = ErrorResponseDTO.class)
})
public @ResponseBody
SuccessResponseDTO update(HttpServletRequest request,
                             @ApiParam(required = true, type = "String", value = " ") @RequestParam(value = “id”, required = true) String id,
                             @ApiParam(required = true, type = "String", value = "  ") @RequestParam(value = "documentNumber", required = true) String documentNumber,
                             @ApiParam(required = true, type = "String", value = " ") @RequestParam(value = “Sid”, required = true) String sid,
                             @ApiParam(required = true, type = "UpdateDTO", value = "Update payload json ")  @Valid @RequestBody UpdateDTO pdatePayload) throws IOException {
    authorizeRequest(request, anId);
    UpdateDTO posDTO = UpdatePayload;
    UpdateAction<UpdateDTO> action = new UpdateAction(Constants.ACTION_UPDATE, DTO, principal);
    action.addAdditionalParams(Constants.KEY_INPUT_DOC_NUMBER, documentNumber);
    action.addAdditionalParams(Constants.KEY_INPUT_SUPPLIER_AN_ID, sid);
    Gson gson = new Gson();
    action.addAdditionalParams(Constants.CONTENT, gson.toJson(DTO));
    return updateService.update(action);
}

I am using annotation @Valid with @RequestBody, expecting it to validate the input JSON. Invalid input JSON where the user sends non-mapping attribute is passing through, API just ignoring the non-mapping fields without any error.

e.g. UpdateDTO contains setter and getter for the fields String name, String status.

User request with an invalid field,

{
"name":"my update",
"invalid_field":"abc"
}

converted into UpdateDTO and non-mapping fields are ignored. I expected it to error out with invalid input.

Can you please suggest to me ? How can I make it work? please let me know if you need any input

I have included the following maven dependencies,

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.8.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.8.0</version>
    </dependency>
</dependencies>

Upvotes: 0

Views: 2009

Answers (2)

Madhu Bhat
Madhu Bhat

Reputation: 15183

You have misunderstood the usage of @Valid. The @Valid annotation is used to validate beans with constraints like @NotNull, @Size, @Min etc as per the JSR 380 specification. For eg, in case you want to have a validation on the name field of UpdateDTO class such that name should never be null, you can use @NotNull on the name field, then have @Valid on the UpdateDTO object in your controller method. This would ensure that whenever the request is made without passing the name field, the validation would fail and an exception would be thrown accordingly.

For your use-case where you want an exception thrown when an unknown field is sent as part of the request, since you are using spring-boot which uses Jackson for serialization/deserialization, you just need to provide a configuration to enable deserialization failure on encountering unknown properties. This can be done by enabling it via properties as below:

spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true

or by defining a @Bean as below:

@Bean
public ObjectMapper objectMapper() {
    return Jackson2ObjectMapperBuilder
            .json()
            .featuresToEnable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
            .build();
}

Upvotes: 5

MangduYogii
MangduYogii

Reputation: 985

Use @Validated annotation to top of the controller class and add this in the controller class

 /**
 * Exception handler for ConstraintViolationException.
 * @param exception ConstraintViolationException
 * @return error message
 */
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody String annotationExceptionHandler(ConstraintViolationException exception) {
    return exception.getMessage();
}

it handle invalid input of user.

Upvotes: -1

Related Questions