Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

622
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda