Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

628
Views
no se pudieron validar los parámetros de solicitud en un controlador Spring Boot/Kotlin Coroutines

En un proyecto SpringBoot/Kotlin Coroutines, tengo una clase de controlador como esta.

 @RestContollser @Validated class PostController(private val posts: PostRepository) { suspend fun search(@RequestParam q:String, @RequestParam @Min(0) offset:Int, @RequestParam @Min(1) limit:Int): ResponseEntity<Any> {} }

La validación en @ResquestBody funciona como Spring WebFlux general, pero al probar

al validar los parámetros de la solicitud , falló y arroja una excepción como:

 java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1 at java.base/java.util.Arrays$ArrayList.get(Arrays.java:4165) Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below:

No es una ConstraintViolationException .

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Creo que esto es un error en el marco cuando está usando rutinas (actualización, lo es, vi el comentario de Happy Songs). En resumen:

"@Validated de hecho aún no cumple con Coroutines, debemos solucionarlo mediante el uso de métodos compatibles con Coroutines para descubrir los parámetros del método".

El problema es que Spring mejora la firma del método en su controlador para tener un parámetro adicional, como este, agregando una continuación:

 public java.lang.Object com.example.react.PostController.search(java.lang.String,int,int,kotlin.coroutines.Continuation)

así que cuando el validador de hibernación llama a getParameter nombres para obtener la lista de parámetros en su método, cree que hay 4 en total en la solicitud y luego obtiene una excepción de índice fuera de los límites tratando de obtener el 4to (índice 3).

Si pones un punto de interrupción en el retorno de esto:

 @Override public E get(int index) { return a[index]; }

y coloque una condición de punto de interrupción de index ==3 && a.length <4 puede ver lo que está sucediendo.

Lo reportaría como un error en el rastreador de problemas de Spring.

Es mejor que adopte un enfoque alternativo, como se describe aquí, utilizando un RequestBody como DTO y utilizando la anotación @Valid

https://www.vinsguru.com/spring-webflux-validation/

over 4 years ago · Santiago Trujillo Report

0

Gracias por los comentarios de las canciones felices, encontré la mejor solución ahora para superar esta barrera de los problemas de Spring Github # 23499 .

Como se explica en los comentarios de este problema y la respuesta de PaulNuk, se agregará una Continuation a los argumentos del método en tiempo de ejecución, lo que fallará en el cálculo del índice de los nombres de los parámetros del método en Hibernate Validator.

La solución es cambiar el ParameterNameDiscoverer.getParameterNames(Method) y agregar una cadena vacía como nombre de parámetro adicional cuando se trata de una función de suspensión .

 class KotlinCoroutinesLocalValidatorFactoryBean : LocalValidatorFactoryBean() { override fun getClockProvider(): ClockProvider = DefaultClockProvider.INSTANCE override fun postProcessConfiguration(configuration: javax.validation.Configuration<*>) { super.postProcessConfiguration(configuration) val discoverer = PrioritizedParameterNameDiscoverer() discoverer.addDiscoverer(SuspendAwareKotlinParameterNameDiscoverer()) discoverer.addDiscoverer(StandardReflectionParameterNameDiscoverer()) discoverer.addDiscoverer(LocalVariableTableParameterNameDiscoverer()) val defaultProvider = configuration.defaultParameterNameProvider configuration.parameterNameProvider(object : ParameterNameProvider { override fun getParameterNames(constructor: Constructor<*>): List<String> { val paramNames: Array<String>? = discoverer.getParameterNames(constructor) return paramNames?.toList() ?: defaultProvider.getParameterNames(constructor) } override fun getParameterNames(method: Method): List<String> { val paramNames: Array<String>? = discoverer.getParameterNames(method) return paramNames?.toList() ?: defaultProvider.getParameterNames(method) } }) } } class SuspendAwareKotlinParameterNameDiscoverer : ParameterNameDiscoverer { private val defaultProvider = KotlinReflectionParameterNameDiscoverer() override fun getParameterNames(constructor: Constructor<*>): Array<String>? = defaultProvider.getParameterNames(constructor) override fun getParameterNames(method: Method): Array<String>? { val defaultNames = defaultProvider.getParameterNames(method) ?: return null val function = method.kotlinFunction return if (function != null && function.isSuspend) { defaultNames + "" } else defaultNames } }

Luego declare un nuevo bean de fábrica de validación.

 @Primary @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) fun defaultValidator(): LocalValidatorFactoryBean { val factoryBean = KotlinCoroutinesLocalValidatorFactoryBean() factoryBean.messageInterpolator = MessageInterpolatorFactory().getObject() return factoryBean }

Obtenga los códigos de muestra completos de mi Github.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!