Context
- Method constraints validation
- Kotlin
- Presence of extension function on parameterized type within the validated object
Problem Given the following code making use of method constraint validation
package foo
import org.slf4j.LoggerFactory
import javax.validation.Validation
import javax.validation.constraints.NotEmpty
class SimpleFooService {
fun methodName(@NotEmpty ignored: String) {
}
private fun List<String>.someExtensionFunction(extensionFunctionArg: Int) = Unit
}
fun main() {
val validator = Validation.buildDefaultValidatorFactory().validator
val executableValidator = validator.forExecutables()
try {
executableValidator.validateParameters(
SimpleFooService(),
SimpleFooService::class.java.getDeclaredMethod(SimpleFooService::methodName.name, String::class.java),
arrayOf("Some value")
)
} catch (e: Exception) {
log.error("Error", e)
}
}
val log = LoggerFactory.getLogger(SimpleFooService::class.java)
Attempting to execute the code leads to ArrayIndexOutOfBoundsException and the given arguments not being validated:
Preliminary analysis Debugging reveals that org.hibernate.validator.internal.metadata.provider.AnnotationMetaDataProvider#findExecutableMetaData is retrieving a incorrect JavaBeanExecutable result from JavaBeanHelper when processing the private final void foo.SimpleFooService.someExtensionFunction(java.util.List,int) method: The extensionFunctionArg argument has the List<String> type associated to it, instead of int That inconsistency causes AnnotationMetaDataProvider.getTypeParametersCascadingMetaDataForParameterizedType to fail. Workaround Workaround is to remove all extension functions on parameterized receiver from the validated class (which may not be desirable). Build setup
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
plugins {
kotlin("jvm") version "1.3.72"
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib"))
implementation(platform("org.springframework.boot:spring-boot-dependencies:2.3.2.RELEASE"))
implementation("org.slf4j:slf4j-api")
implementation("ch.qos.logback:logback-classic")
implementation("org.hibernate.validator:hibernate-validator")
implementation("org.glassfish:jakarta.el")
}
tasks {
"wrapper"(Wrapper::class) {
gradleVersion = "6.5.1"
distributionType = Wrapper.DistributionType.ALL
}
withType<KotlinCompile<KotlinJvmOptions>>().configureEach {
kotlinOptions {
jvmTarget = "11"
javaParameters = true
}
}
}
|