1

I am trying to get Java Bean validation annotations to work with path variables and query parameters in Spring MVC controller. (Environment: Spring Boot v1.3.5, Springxxx 4.2.6, programming language Kotlin 1.0.3)

e.g.

@RequestMapping(value = "/{someId}" ...)
fun getSomething(**@SomeValidId** @PathVariable("someId") someId: String):...

I have added org.springframework.validation.beanvalidation.MethodValidationPostProcessor as described in https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/ and also added org.springframework.validation.beanvalidation.LocalValidatorFactoryBean as the validatorFactory to the above.

@Configuration
...class .... {

...

@Bean
open fun localValidatorFactoryBean() = LocalValidatorFactoryBean()

@Bean
open fun methodValidationPostProcessor() : MethodValidationPostProcessor  {
    val methodValidationPostProcessor = MethodValidationPostProcessor()
    methodValidationPostProcessor.setValidator(localValidatorFactoryBean())

    return methodValidationPostProcessor
}

}

But when I annotate the Controller class (or the interface it implements) with org.springframework.validation.annotation.Validated as suggested looks like the controller class is proxied (which seems to be as expected - https://github.com/spring-projects/spring-security/issues/3215).

@Validated
interface SomeResource  {
....

@RestController
@RequestMapping("/somepath") 
class SomeController ......: SomeResource ....

But this causes the Spring mvc request mapping setup to ignore the SomeController. Debugging through the Spring framework code looked like org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods() goes through the list of beans and tries to detect handler methods but the above controller is ignored by the looks of it as it encounters a proxy instance and it doesn't carry the @Controller or @RequestMapping annotations.

Does anyone have any idea what's missing? There seems to be a lot of information out there that seem to suggest this should be possible, but couldn't find a working example .

1 Answer 1

2

Well I found the issue - it was because the proxy created for the controller was a JDK Dynamic proxy. When I forced it to be a CGLIB proxy it started working alright.

By default Kotlin classes are final and therefore forced to use JDK Dynamic proxies, but marking the controller as 'open' was not sufficient to coerce it to use CGLIB. Had to add @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) to the controller class

@RestController
@RequestMapping("/somepath") 
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class SomeController ......: SomeResource ....
Sign up to request clarification or add additional context in comments.

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.