Search code examples
hibernatekotlinbean-validationmicronautmicronaut-data

Kotlin, Micronaut and Hibernate custom bean validator is never called


I'm studying Micronaut and Kotlin using gRPC for a project at work, and I've ran into some problems that I can't seem to find a answer to.

I'm recriating some personal Spring projects in Micronaut using Kotlin. In those projects I create a custom bean validator annotation to verify if a parameter is duplicated or not. I've recriated it in Kotlin but it's never called, I've also debbuged the code, and it never stops at the breakpoints in the validator.

Here's my Entity class that I want to validate. Note the @UniqueEmail annotation, that's my custom validator.

@Entity
@Validated
@Introspected
@Suppress("unused")
class Autor(
        @Id
        @GeneratedValue(generator = "UUID")
        @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
        val id: String? = null,
        @field:NotNull
        val instante: LocalDateTime = LocalDateTime.now(),
        @field:NotNull
        @field:Email
        @UniqueEmail(domainClassName = "Autor")
        val email: String,
        @field:NotNull
        val nome: String,
        @field:NotNull
        @field:Size(max = 400)
        val descricao: String
) {

}

Here's the validator annotation class.

@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [UniqueEmailValidator::class])
@MustBeDocumented
annotation class UniqueEmail(
        val message: String = "Email already exists",
        val groups: Array<KClass<Any>> = [],
        val payload: Array<KClass<Any>> = [],
        val field: String = "email",
        val domainClassName: String
)

And here is the validator itself. The whole problem here, is that Micronaut never calls this method here, the value is never validated. The other bean annotations are working well, like @NotNull and @Email, but not this one.

class UniqueEmailValidator(@PersistenceContext val manager: EntityManager) : ConstraintValidator<UniqueEmail, String> {

    private lateinit var domainAttribute: String
    private lateinit var kClassName: String

    override fun initialize(params: UniqueEmail) {
        domainAttribute = params.field
        kClassName = params.domainClassName
    }

    override fun isValid(value: String?, context: ConstraintValidatorContext?): Boolean {
        if(value.equals("")) return false

        val query = manager.createQuery("SELECT e FROM $kClassName WHERE $domainAttribute = :value")
                .setParameter("value", value)
        return query.resultList.isEmpty()
    }

}

I've searched a lot, this is my first question at StackOverflow. As Micronaut is a fairly new framework, and not a lot of people uses Spring/Micronaut with kotlin, this is being a lot difficult to find sollutions to errors and specific problems like this one.

I appreciate in advance for the help. Thanks.

Edit: Here is my dependencies:

dependencies {
    kapt("io.micronaut.data:micronaut-data-processor")
    implementation("io.micronaut:micronaut-validation")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
    implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
    implementation("io.micronaut.kotlin:micronaut-kotlin-runtime")
    implementation("io.micronaut:micronaut-runtime")
    implementation("io.micronaut.grpc:micronaut-grpc-runtime")
    implementation("javax.annotation:javax.annotation-api")
    implementation("io.micronaut.sql:micronaut-jdbc-hikari")
    implementation("io.micronaut.sql:micronaut-hibernate-jpa")
    implementation("io.micronaut.data:micronaut-data-hibernate-jpa")
    implementation("io.micronaut.kafka:micronaut-kafka")
    runtimeOnly("org.slf4j:slf4j-simple")
    runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin")
    runtimeOnly("org.postgresql:postgresql")
    testImplementation("io.micronaut:micronaut-http-client")
    testRuntimeOnly("org.testcontainers:postgresql")
}

Solution

  • UniqueEmailValidator should be a bean. It requires a @Singleton annotation.