SW Dog
SW Dog

Reputation: 187

Validator does not work with Kotlin Spring Boot app

Problem

Validation annotations for a Kotlin Spring Boot web project do not appear to be referenced at runtime.

@Min(18)
val age: Int? = null

Expected Result

Annotated fields should throw an error if the specified validation condition is not met.

There are a lot of questions floating around the web asking about similar issues, but the answers don't seem fix this problem.

Suggestions are typically to use "get" or "field" for the annotations - e.g.

@field:Min(18)
val age: Int? = null

Reproduction of Problem

To see why this wasn't working for Kotlin I did a comparison for Kotlin vs Java using this tutorial:

https://spring.io/guides/gs/validating-form-input/

I created a Java application here:

https://github.com/lgviii/JavaSpringValidations

I careated the same app in Kotlin here:

https://github.com/lgviii/KotlinSpringValidations

The Java app does validate the input in the webpage that runs on port 8080, but the Kotlin app does not. So the only difference appears the be the language...


Question

  1. Why does the Java app work out of the box while Kotlin does not?
  2. What needs to be added to the Kotlin Spring Boot validator template project to get
    the validator to pick up the annotations like in the Java version of the project?

Upvotes: 3

Views: 1875

Answers (2)

Oliver Drotbohm
Oliver Drotbohm

Reputation: 83131

In your Kotlin sample project, the position of the @Valid annotation is incorrect. You use:

personForm: @Valid PersonForm?

This is putting the annotation on the type, a mechanism described in detail here. You're not annotating the parameter itself, which is what Spring MVC expects to trigger the validation. This is possible as the Validation API's @Valid is defined to be usable in exactly that position. If you try to use other parameter-only annotations like @ModelAttribute in that position, the compiler will reject that.

To resolve the problem, switch to the following declaration:

@Valid personForm: PersonForm?

This annotates the parameter, Spring MVC triggers the validation and requests sending inadequate data get redirected to the form as expected.

Alternatively, you can use Spring's @Validated annotation instead of JSR-303's @Valid. It essentially works the same way in this context, but prevents the misplacement as it cannot be used as type-use annotation.

Upvotes: 2

Stephane Nicoll
Stephane Nicoll

Reputation: 33121

As explained by this article:

"If you don’t specify a use-site target, the target is chosen according to the @Target annotation of the annotation being used. If there are multiple applicable targets, the first applicable target from the following list is used: param, property, field.

More information in the kotlin documentation.

Upvotes: -1

Related Questions