From a74dc74ec3df3c0c261d0ab8f6f899792bb8d72e Mon Sep 17 00:00:00 2001 From: geo_m Date: Thu, 29 Mar 2018 08:55:29 +0300 Subject: [PATCH 1/2] Allow validation api without implementation Allow validation api in the classpath without a validator, as long as no bean is annotated `@Validated` See gh-12669 --- .../ConfigurationPropertiesBinder.java | 14 +++++++----- ...lidationExceptionFailureAnalyzerTests.java | 22 ++++++++++++++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java index 452726be3c3..68046c091b0 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java @@ -55,7 +55,7 @@ class ConfigurationPropertiesBinder { private final Validator configurationPropertiesValidator; - private final Validator jsr303Validator; + private Validator jsr303Validator; private volatile Binder binder; @@ -66,8 +66,7 @@ class ConfigurationPropertiesBinder { .getPropertySources(); this.configurationPropertiesValidator = getConfigurationPropertiesValidator( applicationContext, validatorBeanName); - this.jsr303Validator = ConfigurationPropertiesJsr303Validator - .getIfJsr303Present(applicationContext); + } public void bind(Bindable target) { @@ -93,9 +92,12 @@ class ConfigurationPropertiesBinder { if (this.configurationPropertiesValidator != null) { validators.add(this.configurationPropertiesValidator); } - if (this.jsr303Validator != null - && target.getAnnotation(Validated.class) != null) { - validators.add(this.jsr303Validator); + + if (target.getAnnotation(Validated.class) != null) { + this.jsr303Validator = ConfigurationPropertiesJsr303Validator.getIfJsr303Present(this.applicationContext); + if (this.jsr303Validator != null) { + validators.add(this.jsr303Validator); + } } if (target.getValue() != null && target.getValue().get() instanceof Validator) { validators.add((Validator) target.getValue().get()); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java index d5c50d82e41..1a572ab9ce2 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java @@ -25,6 +25,7 @@ import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.boot.testsupport.runner.classpath.ClassPathExclusions; import org.springframework.boot.testsupport.runner.classpath.ModifiedClassPathRunner; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.validation.annotation.Validated; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; @@ -39,7 +40,7 @@ import static org.junit.Assert.fail; public class ValidationExceptionFailureAnalyzerTests { @Test - public void test() { + public void validatedPropertiesTest() { try { new AnnotationConfigApplicationContext(TestConfiguration.class).close(); fail("Expected failure did not occur"); @@ -51,6 +52,11 @@ public class ValidationExceptionFailureAnalyzerTests { } } + @Test + public void nonValidatedPropertiesTest() { + new AnnotationConfigApplicationContext(NonValidatedTestConfiguration.class).close(); + } + @EnableConfigurationProperties(TestProperties.class) static class TestConfiguration { @@ -60,8 +66,22 @@ public class ValidationExceptionFailureAnalyzerTests { } @ConfigurationProperties("test") + @Validated private static class TestProperties { } + + @EnableConfigurationProperties(NonValidatedTestProperties.class) + static class NonValidatedTestConfiguration { + + NonValidatedTestConfiguration(NonValidatedTestProperties testProperties) { + } + + } + + @ConfigurationProperties("test") + private static class NonValidatedTestProperties { + + } } From 0c98d0e7d3a8d092c409799092d3252f2e71d98c Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 4 Apr 2018 21:23:57 -0700 Subject: [PATCH 2/2] Polish "Allow validation api without implementation" Closes gh-12669 --- .../ConfigurationPropertiesBinder.java | 23 ++++++++++++------- ...onfigurationPropertiesJsr303Validator.java | 10 ++++---- ...lidationExceptionFailureAnalyzerTests.java | 7 +++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java index 68046c091b0..1575e5c9ea0 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java @@ -55,7 +55,9 @@ class ConfigurationPropertiesBinder { private final Validator configurationPropertiesValidator; - private Validator jsr303Validator; + private final boolean jsr303Present; + + private volatile Validator jsr303Validator; private volatile Binder binder; @@ -66,7 +68,8 @@ class ConfigurationPropertiesBinder { .getPropertySources(); this.configurationPropertiesValidator = getConfigurationPropertiesValidator( applicationContext, validatorBeanName); - + this.jsr303Present = ConfigurationPropertiesJsr303Validator + .isJsr303Present(applicationContext); } public void bind(Bindable target) { @@ -92,12 +95,8 @@ class ConfigurationPropertiesBinder { if (this.configurationPropertiesValidator != null) { validators.add(this.configurationPropertiesValidator); } - - if (target.getAnnotation(Validated.class) != null) { - this.jsr303Validator = ConfigurationPropertiesJsr303Validator.getIfJsr303Present(this.applicationContext); - if (this.jsr303Validator != null) { - validators.add(this.jsr303Validator); - } + if (this.jsr303Present && target.getAnnotation(Validated.class) != null) { + validators.add(getJsr303Validator()); } if (target.getValue() != null && target.getValue().get() instanceof Validator) { validators.add((Validator) target.getValue().get()); @@ -105,6 +104,14 @@ class ConfigurationPropertiesBinder { return validators; } + private Validator getJsr303Validator() { + if (this.jsr303Validator == null) { + this.jsr303Validator = new ConfigurationPropertiesJsr303Validator( + this.applicationContext); + } + return this.jsr303Validator; + } + private BindHandler getBindHandler(ConfigurationProperties annotation, List validators) { BindHandler handler = new IgnoreTopLevelConverterNotFoundBindHandler(); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesJsr303Validator.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesJsr303Validator.java index 3c8cf0bfdfe..bf70742cfec 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesJsr303Validator.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesJsr303Validator.java @@ -38,8 +38,7 @@ final class ConfigurationPropertiesJsr303Validator implements Validator { private final Delegate delegate; - private ConfigurationPropertiesJsr303Validator( - ApplicationContext applicationContext) { + ConfigurationPropertiesJsr303Validator(ApplicationContext applicationContext) { this.delegate = new Delegate(applicationContext); } @@ -53,15 +52,14 @@ final class ConfigurationPropertiesJsr303Validator implements Validator { this.delegate.validate(target, errors); } - public static ConfigurationPropertiesJsr303Validator getIfJsr303Present( - ApplicationContext applicationContext) { + public static boolean isJsr303Present(ApplicationContext applicationContext) { ClassLoader classLoader = applicationContext.getClassLoader(); for (String validatorClass : VALIDATOR_CLASSES) { if (!ClassUtils.isPresent(validatorClass, classLoader)) { - return null; + return false; } } - return new ConfigurationPropertiesJsr303Validator(applicationContext); + return true; } private static class Delegate extends LocalValidatorFactoryBean { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java index 1a572ab9ce2..bcd19182478 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/diagnostics/analyzer/ValidationExceptionFailureAnalyzerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -54,7 +54,8 @@ public class ValidationExceptionFailureAnalyzerTests { @Test public void nonValidatedPropertiesTest() { - new AnnotationConfigApplicationContext(NonValidatedTestConfiguration.class).close(); + new AnnotationConfigApplicationContext(NonValidatedTestConfiguration.class) + .close(); } @EnableConfigurationProperties(TestProperties.class) @@ -71,7 +72,6 @@ public class ValidationExceptionFailureAnalyzerTests { } - @EnableConfigurationProperties(NonValidatedTestProperties.class) static class NonValidatedTestConfiguration { @@ -84,4 +84,5 @@ public class ValidationExceptionFailureAnalyzerTests { private static class NonValidatedTestProperties { } + }