Spring Boot REST Validierung mit Kotlin
Kategorie Software Engineering | 1 Kommentar »
In meinem aktuellen Projekt setze ich die Programmiersprache Kotlin zusammen mit dem Spring Boot Framework ein. Ich mache gerade meine ersten Kotlin Schritte und stolpere jetzt natürlich über alle möglichen Probleme. Erster Stolperstein: Validierung von REST API Eingaben.
Die notwendigen Maven Abhängigkeiten für Spring Boot Validierung lauten:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
Möchte ich den Request Body eines REST Endpoints validieren, füge ich die @Valid Annotation hinzu:
import javax.validation.Valid
@RestController
@RequestMapping(consumes = [MediaType.APPLICATION_JSON_VALUE])
class EchoController {
@PostMapping
fun echo(
@RequestBody @Valid message: MessageDto,
) = message
}
Jetzt muss ich nur noch eine MessageDto Klasse erstellen und alle Properties mit den gewünschten Annotationen für die Validierung versehen. Hier bietet sich in Kotlin natürlich eine Data Class an.
import javax.validation.constraints.NotBlank
data class MessageDto (
@NotBlank
val message: String
)
Leider ist es nicht ganz so einfach :-(
Der Kotlin Compiler generiert im Fall einer Property wie „message“ mehrere Elemente:
- ein Feld
- ein Parameter im Default Constructor
- eine getter Funktion
- eine setter Funktion, wenn die Property als änderbar („var“) statt fix („val“) deklariert wäre
Die Annotation kann sich aber nur auf eines dieser Elemente beziehen. Der Kotlin Compiler schaut zunächst, welche Ziele in der Definition der Annotation laut @Target erlaubt sind. @NotBlank kann auf eine ganze Reihe von Code Elementen angewendet werden:
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
Der Kotlin Compiler prüft diese Targets gegen folgende Liste:
- PARAMETER
- PROPERTY
- FIELD
Das oberste Element Parameter ist sowohl in der @Target als auch in der internen Compiler Liste enthalten und deshalb wird die Annotation auf den generierten Parameter im Default Constructor angewendet.
Tatsächlich muss die @NotBlank Annotation an das zur Property gehörende Feld oder an die getter Funktion gebunden werden. Dazu gibt es die so genannten „use-site targets“. Die korrekte Annotation (siehe Zeile 4) muss also lauten:
import javax.validation.constraints.NotBlank
data class MessageDto (
@field:NotBlank
val message: String
)
Dann funktioniert die Validierung auch wie erwartet.
[…] Kotlin wird von Spring einwandfrei unterstützt. Viele Spring Handbücher bieten inzwischen Beispiele in Java und Kotlin. Es gibt auch eine Unmenge an Spring – Kotlin Tutorials. Die Arbeit mit Kotlin und Spring macht Spaß! Aber Vorsicht: Es gibt ein paar fiese Stolpersteine, etwa bei der Validierung von Kotlin Data-Klassen mit Jackson. […]