Skip to content

Bean validation doesn't work with Kotlin coroutine controller #23152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
FearlessHyena opened this issue Jun 19, 2019 · 10 comments
Closed

Bean validation doesn't work with Kotlin coroutine controller #23152

FearlessHyena opened this issue Jun 19, 2019 · 10 comments
Assignees
Labels
status: duplicate A duplicate of another issue

Comments

@FearlessHyena
Copy link

Affects:Spring 5.2.0.M2


Same issue as mentioned here

Adding a @Validated annotation to a coroutine @RestController throws an ArrayIndexOutOfBoundsException

Using Spring Boot 2.2.0.M3 and Coroutines 1.3.0-M1

java.lang.ArrayIndexOutOfBoundsException: 2
	at java.util.Arrays$ArrayList.get(Arrays.java:3841) ~[na:1.8.0_181]
	at org.hibernate.validator.internal.metadata.aggregated.ParameterMetaData$Builder.build(ParameterMetaData.java:169) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData$Builder.findParameterMetaData(ExecutableMetaData.java:435) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData$Builder.build(ExecutableMetaData.java:388) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl$BuilderDelegate.build(BeanMetaDataImpl.java:788) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.metadata.aggregated.BeanMetaDataImpl$BeanMetaDataBuilder.build(BeanMetaDataImpl.java:648) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManager.createBeanMetaData(BeanMetaDataManager.java:192) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManager.lambda$getBeanMetaData$0(BeanMetaDataManager.java:160) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:324) ~[na:1.8.0_181]
	at org.hibernate.validator.internal.metadata.BeanMetaDataManager.getBeanMetaData(BeanMetaDataManager.java:159) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.engine.ValidationContext$ValidationContextBuilder.forValidateParameters(ValidationContext.java:619) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:254) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateParameters(ValidatorImpl.java:224) ~[hibernate-validator-6.0.12.Final.jar:6.0.12.Final]
	at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:97) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.kotlin.experimental.coroutine.web.CoroutineController$$EnhancerBySpringCGLIB$$220f8cfd.delayedMultiply(<generated>) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:891) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) ~[spring-webmvc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.34.jar:8.5.34]`
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jun 19, 2019
@sdeleuze sdeleuze self-assigned this Jun 19, 2019
@sdeleuze sdeleuze added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jun 19, 2019
@sdeleuze
Copy link
Contributor

In Spring official support, Coroutines are not supported with Spring MVC, and I have not been able to reproduce the issue with WebFlux, so I close this issue as invalid. Feel free to reopen with a repro project using WebFlux if you can reproduce it.

@a8t3r
Copy link

a8t3r commented Aug 17, 2019

Hello!
This bug has the same nature as #21470, but relates to kotlin.coroutines.Continuation
A possible workaround is just disable KotlinReflectionParameterNameDiscoverer:

@Configuration
class ValidationConfig {

    companion object {

        @Bean
        @Primary
        fun validator(): LocalValidatorFactoryBean {
            val factoryBean = LocalValidatorFactoryBean()
            factoryBean.setParameterNameDiscoverer(StandardReflectionParameterNameDiscoverer())
            return factoryBean
        }
    }
}

@s-volkov-1
Copy link

Why is this closed? I bumped into this bug with webflux environment

@snicoll
Copy link
Member

snicoll commented Dec 23, 2020

@sergey-volkov-lm please review the history of the issue before commenting. In his comment that closed the issue, Sébatien mentioned that:

have not been able to reproduce the issue with WebFlux, so I close this issue as invalid. Feel free to reopen with a repro project using WebFlux if you can reproduce it.

If you can share such project (either as a zip attached to this issue or by sharing a link to a GitHub repository) we can reopen the issue as already mentioned.

@s-volkov-1
Copy link

@snicoll
Copy link
Member

snicoll commented Dec 23, 2020

Thank you very much for the sample @sergey-volkov-lm.

@snicoll snicoll reopened this Dec 23, 2020
@snicoll snicoll added status: waiting-for-triage An issue we've not yet triaged or decided on and removed status: invalid An issue that we don't feel is valid labels Dec 23, 2020
@s-volkov-1
Copy link

Probably same problem: #23499

@yuri-li
Copy link

yuri-li commented Feb 6, 2021

spring-issue-23152-demo.zip

My Solution:

@Component
@Validated
class DemoControllerValidator{
    fun validate(@Positive positiveNumber: Int) = positiveNumber
}

@Validated
@RestController
class DemoController(val validator:DemoControllerValidator) {
    @GetMapping("test")
    suspend fun test(@RequestParam @Positive positiveNumber: Int): MessageResponse {
        val validatedParam = validator.validate(positiveNumber)
        delay(1000L)
        return MessageResponse(UUID.randomUUID().toString().take(5))
    }
}

@swapnil-gawali
Copy link

Any update on this?

@sdeleuze sdeleuze added status: duplicate A duplicate of another issue and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 7, 2021
@sdeleuze
Copy link
Contributor

sdeleuze commented Apr 7, 2021

This issue is indeed a duplicate of #23499, Hibernate Validator needs to supports Coroutines to avoid this issue. If you care please create a related issue in Hibernate Validator and reference it in #23499.

@sdeleuze sdeleuze closed this as completed Apr 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

8 participants