1

Spring does not create an instance of class implementing ConstraintValidator. Even when I annotate RolesValidator with @Configuartion Spring create its instance, but validation doesn't work.

Here is my code:

@Constraint(validatedBy = [RolesValidator::class])
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class ValidateRoles(
    val message: String = "{com.app.authservice.validators.ValidateRoles.message}",
    val groups: Array<KClass<*>> = arrayOf(),
    val payload: Array<KClass<out Payload>> = arrayOf()
)

//------Validator------

class RolesValidator : ConstraintValidator<ValidateRoles, Collection<String>> {
    lateinit var allowedValues: List<String>

    override fun initialize(constraintAnnotation: ValidateRoles?) {
        allowedValues = RoleType.values().map { it.name }
    }

    override fun isValid(value: Collection<String>?, context: ConstraintValidatorContext?): Boolean {
        return allowedValues.containsAll(value!!)
    }
}

//------Usage------

class AccountUpdateRolesDTO {
    @NotNull
    @ValidateRoles
    var roles: Set<String> = emptySet()
}

//------Controller------

@PreAuthorize("hasAnyAuthority($_ADMIN)")
@Transactional
@PutMapping("/{accountId}/roles")
fun updateRoles(
    @RequestBody @Valid body: AccountUpdateRolesDTO,
    @PathVariable accountId: Long,
    jwt: JWTData
): ResponseEntity<Void> {
    return ResponseEntity(HttpStatus.OK)
}

@edit https://github.com/spring-projects/spring-framework/issues/21242 (formerly SPR-16701)

2
  • Do you see any exceptions in log? How do you now that that's not created? Commented Apr 8, 2018 at 4:32
  • I setup a break point in the Validator and it's never invoked nor initialized. And no, no exceptions Commented Apr 8, 2018 at 8:56

2 Answers 2

1

If you leverage annotation use-site targets, Kotlin tests pass as well:

class KotlinBodyDTO {
    @field:NotNull
    @field:ValidateRolesKotlin
    var roles: Set<String> = emptySet()
}
Sign up to request clarification or add additional context in comments.

Comments

0

It seems that Spring doesn't recognize annotations in Kotlin. After I converted the annotation to Java everything was ok.

@Constraint(validatedBy = RolesValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ValidateRoles {
    String message() default "{com.app.authservice.validators.ValidateRoles.message}";

    Class[] groups() default {};

    Class[] payload() default {};
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.