MethodArgumentNotValidException не выдается в случае сбоя проверки

Я пытаюсь реализовать проверку в Spring REST, следуя этому руководство. Хотя мой код в Koltin, в отличие от туториала.

Мой код выглядит следующим образом:

Класс объекта

@Entity
class PodcastEntity(@Id @GeneratedValue(strategy = GenerationType.AUTO) @NotNull
                    var id: Long = 0,
                    @field:NotEmpty(message = "Please provide an author")
                    var author: String,
                    @field:NotEmpty(message = "Please provide a title")
                    var title: String,
                    @field:NotEmpty(message = "Please provide a description")
                    var description: String,
                    @field:NotEmpty(message = "Please provide category one")
                    var categoryOne: String,
                    @field:NotEmpty(message = "Please provide category two")
                    var categoryTwo: String,
                    var filePath: String = "")

Мой метод публикации выглядит так в controller -

@PostMapping("details")
fun addPodcast(@Valid @RequestBody podcastEntity: PodcastEntity) {
    podcastService.addPodcast(podcastEntity)
}

Мой запрос POST в почтальоне выглядит так:

{
    "author" : "me 3",
    "title" : "File three",
    "description" : "this is a test desc"
}

Поскольку categoryOne и categoryTwo отсутствуют, и я не обрабатывал исключение самостоятельно, моя консоль должна отображать MethodArgumentNotValidException в соответствии с руководством. Однако я не получаю такого исключения. Я получаю исключение HttpMessageNotReadableException -

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Instantiation of [simple type, class com.krtkush.test.entities.PodcastEntity] value failed for JSON property categoryOne due to missing (therefore NULL) value for creator parameter categoryOne which is a non-nullable type; nested exception is com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.krtkush.test.entities.PodcastEntity] value failed for JSON property categoryOne due to missing (therefore NULL) value for creator parameter categoryOne which is a non-nullable type  at [Source: (PushbackInputStream); line: 5, column: 1] (through reference chain: com.krtkush.test.entities.PodcastEntity["categoryOne"])]

Я не могу понять, где я ошибаюсь. Некоторая помощь, пожалуйста?


person krtkush    schedule 06.07.2020    source источник


Ответы (2)


Вы можете решить эту проблему, предоставив обработчик HttpMessageNotReadableException, а затем проверив, является ли основная причина MissingKotlinParameterException.

После этого вы можете предоставить пользовательскую ошибку проверки.

    @ExceptionHandler
    override fun handleMessageNotReadableException(
        exception: HttpMessageNotReadableException,
        request: NativeWebRequest
    ): ResponseEntity<Problem> {
        // workaround
        val cause = exception.cause
        if (cause is MissingKotlinParameterException) {
            val violations = setOf(createMissingKotlinParameterViolation(cause))
            return newConstraintViolationProblem(exception, violations, request)
        }
        return create(Status.BAD_REQUEST, UnableToReadInputMessageProblem(), request)
    }

    private fun createMissingKotlinParameterViolation(cause: MissingKotlinParameterException): Violation {
        val name = cause.path.fold("") { jsonPath, ref ->
            val suffix = when {
                ref.index > -1 -> "[${ref.index}]"
                else -> ".${ref.fieldName}"
            }
            (jsonPath + suffix).removePrefix(".")
        }
        return Violation(name, "must not be null")
    }

Таким образом, вы получите хороший результат с правильной ошибкой ограничения.

Вы можете попытаться объявить @ExceptionHandler для MissingKotlinParameterException напрямую.

Ответ на основе вопроса Проверка Spring не нулевая, вызывающая HttpMessageNotReadableException вместо MethodArgumentNotValidException в котлин

person Damian229    schedule 06.07.2020
comment
Первый ответ на связанный вопрос был более точным, чем то, что я искал. Спасибо! - person krtkush; 07.07.2020

Следуя ссылке SO Дамиана в его ответе, я нашел первый ответ действительно полезным и более подходящим. Я изменил класс @Entitiy, сделав обязательные поля нулевыми (?) следующим образом:

@Entity
class PodcastEntity(@Id @GeneratedValue(strategy = GenerationType.AUTO)
                    var id: Long = 0,
                    @field:NotEmpty(message = "Please provide an author")
                    var author: String?,
                    @field:NotEmpty(message = "Please provide a title")
                    var title: String?,
                    @field:NotEmpty(message = "Please provide a description")
                    var description: String?,
                    @field:NotEmpty(message = "Please provide category one")
                    var categoryOne: String?,
                    @field:NotEmpty(message = "Please provide category two")
                    var categoryTwo: String?,
                    var filePath: String = "")

Это гарантирует, что код выдает MethodArgumentNotValidException во всех трех случаях: 1. Пустой аргумент 2. null аргумент 3. Отсутствующий аргумент

person krtkush    schedule 07.07.2020