Skip to content

Commit

Permalink
Unwrap Validator proxy for access to forExecutables (if necessary)
Browse files Browse the repository at this point in the history
Issue: SPR-15807
  • Loading branch information
jhoeller committed Sep 10, 2017
1 parent 17f42fc commit d1f42ac
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -81,7 +81,7 @@ public class MethodValidationInterceptor implements MethodInterceptor {
}


private final Validator validator;
private volatile Validator validator;


/**
Expand Down Expand Up @@ -116,7 +116,18 @@ public Object invoke(MethodInvocation invocation) throws Throwable {

if (forExecutablesMethod != null) {
// Standard Bean Validation 1.1 API
Object execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, this.validator);
Object execVal;
try {
execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, this.validator);
}
catch (AbstractMethodError err) {
// Probably an adapter (maybe a lazy-init proxy) without BV 1.1 support
Validator nativeValidator = this.validator.unwrap(Validator.class);
execVal = ReflectionUtils.invokeMethod(forExecutablesMethod, nativeValidator);
// If successful, store native Validator for further use
this.validator = nativeValidator;
}

Method methodToValidate = invocation.getMethod();
Set<ConstraintViolation<?>> result;

Expand All @@ -137,13 +148,11 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
}

Object returnValue = invocation.proceed();

result = (Set<ConstraintViolation<?>>) ReflectionUtils.invokeMethod(validateReturnValueMethod,
execVal, invocation.getThis(), methodToValidate, returnValue, groups);
if (!result.isEmpty()) {
throw new ConstraintViolationException(result);
}

return returnValue;
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.validation.Validator;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
Expand All @@ -26,6 +27,10 @@

import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.MutablePropertyValues;
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.context.support.StaticApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
Expand Down Expand Up @@ -64,7 +69,6 @@ public void testMethodValidationPostProcessor() {
ac.close();
}


private void doTestProxyValidation(MyValidInterface proxy) {
assertNotNull(proxy.myValidMethod("value", 5));
try {
Expand Down Expand Up @@ -115,6 +119,13 @@ private void doTestProxyValidation(MyValidInterface proxy) {
}
}

@Test
public void testLazyValidatorForMethodValidation() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class);
ctx.getBean(MyValidInterface.class).myValidMethod("value", 5);
}


@MyStereotype
public static class MyValidBean implements MyValidInterface<String> {
Expand Down Expand Up @@ -165,4 +176,16 @@ public interface OtherGroup {
public @interface MyValid {
}


@Configuration
public static class LazyMethodValidationConfig {

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

}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,7 @@

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.validation.Validator;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
Expand All @@ -26,11 +27,16 @@

import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.MutablePropertyValues;
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.context.support.StaticApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor;
import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.CustomValidatorBean;
import org.springframework.validation.beanvalidation.MethodValidationInterceptor;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

Expand Down Expand Up @@ -68,7 +74,6 @@ public void testMethodValidationPostProcessor() {
ac.close();
}


@SuppressWarnings("unchecked")
private void doTestProxyValidation(MyValidInterface proxy) {
assertNotNull(proxy.myValidMethod("value", 5));
Expand Down Expand Up @@ -120,6 +125,13 @@ private void doTestProxyValidation(MyValidInterface proxy) {
}
}

@Test
public void testLazyValidatorForMethodValidation() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class);
ctx.getBean(MyValidInterface.class).myValidMethod("value", 5);
}


@MyStereotype
public static class MyValidBean implements MyValidInterface<String> {
Expand Down Expand Up @@ -170,4 +182,16 @@ public interface OtherGroup {
public @interface MyValid {
}


@Configuration
public static class LazyMethodValidationConfig {

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

}

0 comments on commit d1f42ac

Please sign in to comment.