Custom Hibernate constraint in Kotlin

February 17th 2023 Kotlin Quarkus

Quarkus uses Hibernate Validator for validation. This means that the correct way to do custom field validation is to create a custom constraint. The steps to do this are well documented. However, since I am still learning Kotlin, it was not trivial for me to convert the sample code to Kotlin, especially the annotation part.

Each constraint must have a corresponding annotation that can be used to apply a constraint to a field:

import javax.validation.Constraint
import javax.validation.Payload
import kotlin.annotation.AnnotationTarget.*
import kotlin.reflect.KClass

@Constraint(validatedBy = [SloPhoneValidator::class])
annotation class SloPhone(
    val message: String = "{org.example.validators.SloPhone.message}",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Payload>> = []

The most important part of the constraint is of course the validator class:

import javax.validation.ConstraintValidator
import javax.validation.ConstraintValidatorContext

class SloPhoneValidator : ConstraintValidator<SloPhone, String> {
    override fun isValid(
            value: String?,
            constraintContext: ConstraintValidatorContext?
    ): Boolean {
        if (value == null) {
            return true

        val phoneUtil = PhoneNumberUtil.getInstance()

        return try {
            val slovenianNumberProto = phoneUtil.parse(value, "SI")
        } catch (e: NumberParseException) {

To implement this validation example, I am using Google's library for phone number parsing, formatting and validation:


The annotation class also references the error message, which must be placed in the resource:

org.example.validators.SloPhone.message=must be a valid Slovenian phone number

This is already enough to use the constraint on a class field:

class ContactDetails {
    var mobilePhone: String? = null
    var workPhone: String? = null

When called if an invalid phone number a Quarkus REST endpoint would now respond with:

  "title": "Constraint Violation",
  "status": 400,
  "violations": [
      "field": "autoValidation.person.mobilePhone",
      "message": "must be a valid Slovenian phone number"

As described in my previous blog post there are cases in Quarkus where you want to apply a constraint programmatically to a field. For this you also need the ConstraintDef class for your constraint:

class SloPhoneDef : ConstraintDef<SloPhoneDef, SloPhone>(

You can then reference it in a validator factory customizer:

class ContactDetailsValidatorFactoryCustomizer : ValidatorFactoryCustomizer {
    override fun customize(configuration: BaseHibernateValidatorConfiguration<*>) {
        val constraintMapping = configuration.createConstraintMapping()



You can find the full source code for this example in my GitHub repository.

Implementing a custom Hibernate Validator constraint requires a lot of plumbing code. In this post, I presented a sample implementation in Kotlin that follows the steps from the official Hibernate Validator documentation.

Get notified when a new blog post is published (usually every Friday):

If you're looking for online one-on-one mentorship on a related topic, you can find me on Codementor.
If you need a team of experienced software engineers to help you with a project, contact us at Razum.
Creative Commons License