3

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")
}
PanzerBerg
  • 33
  • 5

1 Answers1

3

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

Sascha Frinken
  • 3,134
  • 1
  • 24
  • 27
  • Thanks for the answer, but it did not work. I've added `@Singleton`, nothing else has changed, I've also tried debbuging and it never calls the function. I've also tried using `@UniqueEmail` and `@field:UniqueEmail` in my Entity, and also, nothing happend. Do you know have any other solution in mind? Do you think might be some dependency? Thanks. – PanzerBerg Nov 27 '20 at 01:00
  • Is your `UniqueEmailValidator` extending the micronaut [ConstraintValidator](https://docs.micronaut.io/latest/api/io/micronaut/validation/validator/constraints/ConstraintValidator.html)? – Sascha Frinken Nov 27 '20 at 07:49
  • 1
    Yes, it is. Extending `ConstraintValidator` receiving my annotation `UniqueEmail` and the type of the values `String` – PanzerBerg Nov 27 '20 at 12:56
  • So, I've managed to make it work, at least Micronaut is now calling the method and class. It was someting to do with my dependencies, not sure what. But now the `isValid` functions is stuck in a infinite loop, it throws a `StackOverflowError`, not sure why – PanzerBerg Nov 27 '20 at 16:32
  • @PanzerBerg, have you fixed your issue? May I ask you to share your solution (maybe trhow github)? – Jim C Dec 29 '20 at 16:27
  • 1
    @JimC I've had to drop the project because the first Sprint at my work was about to start, so I didn't had much time to study about this. I did manage to make Micronaut access the annotation, but, for some reason, when inside, it keeps executing in an infinite loop until the compiler throw a `StackOverflowException`. I have a repository of the project, but I dropped it some time ago. [Here it is, if you want to check it out](https://github.com/PanzerBerg/micronaut-grpc-casa-do-codigo/tree/master/src/main/kotlin/com/zup), it is in services/validators – PanzerBerg Dec 31 '20 at 14:02
  • 1
    @JimC A lot of my problems were with Gradle. I've had never used it before, got accustomed to Maven. I've had to create the habit to run a Gradle clean build every time I changed something on the code... otherwise some Bean or annotation would stop working. – PanzerBerg Dec 31 '20 at 14:04