Search code examples
validationgrails-ormmicronaut

Weird validation error handling in Micronaut


I have a controller action to serve my react front-end. It requires the validation messages in the special format:

  @Transactional
  @Post( uri = '{/id}', consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON )
  HttpResponse save( @PathVariable @Nullable Long id, @Body Map body ){
    def o = bindFromIdAndBody id, body

    if( o.save( flush:true ) ){
      log.info "version >> $o.version"
      HttpResponse.ok o
    }else{
      log.info '-------------------------'
      List errors = o.errors.fieldErrors.collect{ FieldError fe ->
        fe.codes.findResult{ String c -> 
          messageSource.getMessage c, fe.arguments, null, Locale.default
        } ?: fe.codes.last()
      }
      log.info "save failed for $o: $errors"
      HttpResponse.badRequest( errors:errors )
    }
  }

When I call the action, I'm getting 400 Bad Request in my client, but instead of { errors:[ {..}, {..}, {..} ] style JSON, I see rather:

{
  "message":"Validation Error(s) occurred during save() : Field error in object ...  default message [Property [{0}] of class [{1}] cannot be blank]\r\n",
  "path":"fullName",
  "_links":{"self":{"href":"/person/42","templated":false}}
}

Also the else{} block is never reached, I don't get any further logs.

Any hints?


Solution

  • It appears, that in GORM configuration for Micronaut done via

      compile 'io.micronaut.configuration:micronaut-hibernate-gorm'
    

    the failOnError is set to true by default. That led to ValidationException being thrown on save() instead of populating o.errors.

    To fix the issue I added the line

    grails.gorm.failOnError: false
    

    to my application.yml and now it's working like charm.