如果验证失败,则不会引发MethodArgumentNotValidException

发布时间:2020-07-06 17:39

我正在尝试通过遵循this教程在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"
}

由于缺少categoryOnecategoryTwo并且我还没有自己处理异常,因此根据该教程,我的控制台应显示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"])]

我无法理解我要去哪里。请帮忙吗?

回答1

您可以通过提供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 not null validation throwing HttpMessageNotReadableException instead of MethodArgumentNotValidException in kotlin

的答案
回答2

在达米安(Damian)的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.缺少参数