Skip to content

AbstractMethodError when calling validated method of MethodValidationPostProcessor is using a @Lazy validator [SPR-15629] #20188

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
spring-projects-issues opened this issue Jun 6, 2017 · 1 comment
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jun 6, 2017

Andy Wilkinson opened SPR-15629 and commented

In exploring a possible fix for this Spring Boot issue I've hit a problem when MethodValidationPostProcessor is configured with a CustomValidatorBean that's @Lazy. This small sample reproduces the problem with Spring Framework 4.3.8.RELEASE and Hibernate Validator 5.3:

package com.example;

import javax.validation.Validator;
import javax.validation.constraints.Size;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.CustomValidatorBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

public class LazyValidatorProblem {

	@Configuration
	static class ValidatorConfiguration {

		@Bean
		public Validator customValidator() {
			return new CustomValidatorBean();
		}

	}

	@Configuration
	static class BeanPostProcessorConfiguration {

		@Bean
		public static MethodValidationPostProcessor methodValidationPostProcessor(
				@Lazy Validator validator) {
			MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
			postProcessor.setValidator(validator);
			return postProcessor;
		}

	}

	@Configuration
	static class ServiceConfiguration {

		@Bean
		public SampleService sampleService() {
			return new SampleService();
		}

	}

	@Validated
	static class SampleService {

		public void doSomething(@Size(min = 3, max = 10) String name) {

		}

	}

	public static void main(String[] args) {
		new AnnotationConfigApplicationContext(ValidatorConfiguration.class,
				BeanPostProcessorConfiguration.class, ServiceConfiguration.class)
						.getBean(SampleService.class).doSomething("testing");
	}

}

The failure that you should see is:

Exception in thread "main" java.lang.AbstractMethodError: org.springframework.validation.beanvalidation.CustomValidatorBean.forExecutables()Ljavax/validation/executable/ExecutableValidator;
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
	at com.sun.proxy.$Proxy9.forExecutables(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:216)
	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:201)
	at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
	at com.example.LazyValidatorProblem$SampleService$$EnhancerBySpringCGLIB$$d8a8543a.doSomething(<generated>)
	at com.example.LazyValidatorProblem.main(LazyValidatorProblem.java:58)

This happens because SpringValidatorAdapter does not implement the forExecutables method that was added to Validator in Bean Validation 1.1. The problem does not occur with Spring Framework 5.0 as a result of this commit.


Affects: 4.3.8

Reference URL: spring-projects/spring-boot#9416

Issue Links:

Referenced from: commits b7337b3, 8330134, 55b0fe1

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

We're calling unwrap(Validator.class) on SpringValidatorAdapter now, which covers both LocalValidatorFactoryBean and CustomValidatorBean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants