tibi
tibi

Reputation: 677

HttpMessageNotReadableException instead of BeanPropertyBindingResult

I have a form with a Double field. When I add a value which is not a Double ('foo') it should give me a BeanPropertyBindingResult with an error for that field. But instead i get a HttpMessageNotReadableException.

The strange thing is that from my JUnit test I do get the BeanPropertyBindingResult

Here is my code (i try to focus on what I think is needed if more is needed I will provide it).

I have an Angular frontend:

First here is the error i get from Angular:

2018-05-22 11:28:59.143 WARN 1262 --- [ XNIO-8 task-4] o.z.p.spring.web.advice.AdviceTrait : Bad Request: JSON parse error: Can not deserialize value of type java.lang.Double from String "dddddddd": not a valid Double value; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.lang.Double from String "dddddddd": not a valid Double value at [Source: java.io.PushbackInputStream@36d5105f; line: 1, column: 1294] (through reference chain: nl.tibi.sbys.service.dto.ProjectDTO["travelRate"]) 2018-05-22 11:28:59.146 WARN 1262 --- [ XNIO-8 task-4] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize value of type java.lang.Double from String "dddddddd": not a valid Double value; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.lang.Double from String "dddddddd": not a valid Double value at [Source: java.io.PushbackInputStream@36d5105f; line: 1, column: 1294] (through reference chain: nl.tibi.sbys.service.dto.ProjectDTO["travelRate"])

when i run the code from my junit test i get this, which is what i think is best:

2018-05-22 11:32:00.516 WARN 18426 --- [ main] o.z.p.spring.web.advice.AdviceTrait : Bad Request: org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'projectDTO' on field 'travelRate': rejected value [3,5]; codes [typeMismatch.projectDTO.travelRate,typeMismatch.travelRate,typeMismatch.java.lang.Double,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [projectDTO.travelRate,travelRate]; arguments []; default message [travelRate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Double' for property 'travelRate'; nested exception is java.lang.NumberFormatException: For input string: "3,5"]

My angular code sends like this:

update( project: Project ): Observable<EntityResponseType> {
    const copy = this.convert( project );
    return this.http.put<Project>( this.resourceUrl, copy, { observe: 'response' } )
        .map(( res: EntityResponseType ) => this.convertResponse( res ) );
}

my junit test is this:

restMockMvc.perform(post(url()).param("travelRate", "3,5").param("name", "name")).andExpect(status().isUnprocessableEntity());

My method (which is not reached because of the wrong decimal value):

   @PostMapping()
   @Timed
   public ResponseEntity<ProjectDTO> createProject(@Valid ProjectDTO projectDTO) throws URISyntaxException {
    log.debug("REST request to save Project : {}", projectDTO);
    ....
    } 

How can I get the same result from Angular as from my JUnit test? ie how do I get a BeanPropertyBindingResult?

my workaround can be adding an ExceptionHandler and parsing the string message and create the BeanPropertyBindingResult myself

Upvotes: 0

Views: 693

Answers (1)

Mạnh Quyết Nguyễn
Mạnh Quyết Nguyễn

Reputation: 18235

The message is clear: Cannot convert a string parameter to your Double property.

The request body reader happens before your bean validation logic so BeanPropertyBindingResult exception does not occur.

If you want to verify input was correctly a double, you have to declare it as String in your DTO and valid it using custom validator:

public class ProjectDTO {
    @Double
    String travelRate;
}

Here @Double is your custom validator. Which is easily implemented.

Upvotes: 1

Related Questions