Yanming Zhou opened SPR-17431 and commented


package com.example;

import static org.junit.Assert.assertEquals;

import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import javax.validation.constraints.NotEmpty;

import org.aopalliance.intercept.MethodInterceptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

import com.example.MethodValidationPostProcessorTests.MyConfiguration;

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyConfiguration.class)
public class MethodValidationPostProcessorTests {

    @Autowired
    private MyInterface myInterface;

    @Autowired
    private MyInterface myImplementation;

    @Test(expected = ConstraintViolationException.class)
    public void testJdkProxy() throws Exception {
        assertEquals("", myInterface.echo(""));
    }

    @Test(expected = ConstraintViolationException.class)
    public void testImplementation() throws Exception {
        assertEquals("", myImplementation.echo(""));
    }

    @Validated
    public interface MyInterface {

        public String echo(@NotEmpty String text);

    }

    @Configuration
    static class MyConfiguration {

        @Bean
        public FactoryBean<MyInterface> myInterface() {
            return new FactoryBean<MyInterface>() {

                @Override
                public MyInterface getObject() throws Exception {
                    return (MyInterface) new ProxyFactory(MyInterface.class,
                            (MethodInterceptor) mi -> mi.getArguments()[0])
                                    .getProxy(MyInterface.class.getClassLoader());
                }

                @Override
                public Class<?> getObjectType() {
                    return MyInterface.class;
                }

            };
        }

        @Bean
        public MyInterface myImplementation() {
            return new MyInterface() {

                @Override
                public String echo(String text) {
                    return text;
                }

            };
        }

        @Bean
        public LocalValidatorFactoryBean validatorFactory() {
            return new LocalValidatorFactoryBean();
        }

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

    }

}

testImplementation() pass and testJdkProxy() failed


Affects: 5.1.1

Issue Links: - #21907 MethodValidationPostProcessor validates FactoryBean methods for which validation is not applicable - #21919 MethodValidationPostProcessor still validates FactoryBean methods on CGLIB proxies

Comment From: spring-projects-issues

Yanming Zhou commented

Maybe it caused by FactoryBean not jdk proxy.

Comment From: snicoll

Thanks for the sample. Updating to a supported version is behaving as expected.